混合索引字段和非索引字段的Django过滤器的效率



假设我有一个类似的模型

class Widget(models.Model):
a = models.CharField(db_index=True, unique=True)
b = models.CharField()

然后我执行一个类似的过滤器

Widgets.objects.filter(a=a, b=b).get()

你是否期望这方面的表现(1(相同;或者(2(更糟?-如果模型被定义为:

class Widget(models.Model):
a = models.CharField(db_index=True, unique=True)
b = models.CharField(db_index=True)  # <--- now b is indexed

我的意思是,从逻辑上讲,因为a是索引的并且是唯一的,所以最多可以为a的某个值找到一个结果,所以引擎可以只在a上进行查找,然后检查结果b字段是否为预期值,而不在b上使用任何索引。

但在实践中,生成的SQL和底层SQL引擎在查询规划方面是否足够聪明,能够解决这一问题?这样的查询规划是琐碎的吗?

并不是说索引本身就是使用的。数据库会收集有关指数特异性的统计数据,有时全扫描更有效。例如,如果数据库期望返回很大一部分元素。在这种情况下,它将执行磁盘I/O以返回记录,因此首先使用索引可能会较慢。

您是否期望此操作的性能(1(相同;或者(2(更糟?

大致相同,或者稍差。以防索引这两个字段。数据库通常会查找最能加速的字段的索引。b可能对此更好,因此它将使用b的索引,并且";扫描";对于CCD_ 5的字段。

但是,您可以同时索引。您可以使用Meta选项[Django-doc]的indexes选择[Django/doc]:

class Widget(models.Model):
a = models.CharField(db_index=True, unique=True)
b = models.CharField(db_index=True)
class Meta:
indexes = [
models.Index(fields=['a', 'b'])# ← index together
]

也就是说,如果a(或b(已经可以显著减少搜索空间,则加速不会那么多。索引用于仅检索数据库所需的磁盘的这些部分。然而,如果第二个索引减少了元素的数量,但它仍然需要或多或少相同的段,则速度不会那么快,因为I/O(非常(经常是瓶颈。

最新更新