在Postgres数据库中,我注意到我可以在同一组列上添加复合索引键,但顺序不同。例句:
创建索引index_1。A USING btree (x, y);创建索引index_2。A USING btree (y, x);
请注意,索引的不同之处在于被索引的列的顺序。
我希望Postgres将列列表视为无序集合。
这种添加两个相似索引的能力是否意味着WHERE和ON子句中条件的顺序对检索速度有影响?
我希望Postgres将列列表视为无序集合。
原因很简单:计算机内存不是多维的。
假设您有10个项目,每个项目都有x
和y
的唯一组合。在纸上,你可以把它们画在一个网格上,x
在一个轴上,y
在另一个轴上。要查找特定x
的所有值,可以沿着相应的行查找;对于特定y
的所有值,请向下查找相应的列。如果你需要三个变量,就很难在纸上画出来,但你可以想象一个立方体;数学家将可视化高维的"超立方体"。
计算机内存(和存储)不是这样工作的;它只是一个记录的线性列表,一个接一个。所以你的双元素索引不是存储为一个网格,而是存储为一个排序列表。如果索引位于(x, y)
上,则基本排列如下:
- 按
x
排序 - 在具有相同
x
的每个组中,按y
对这些记录进行排序
(实际结构比列表更复杂,因此很容易跳转到正确的组,并且您不必在每次需要添加低值x
时重写整个索引,但我认为一般原则对于当前的讨论来说已经足够好了。)
现在,如果您想找到具有特定x
的所有元素,您可以跳转到该记录组,并返回它们。但是如果你想找到具有特定y
的所有元素,你必须查看每个组,看看是否有。
这种添加两个相似索引的能力是否意味着WHERE和ON子句中条件的顺序对检索速度有影响?
它们在查询中出现的顺序通常无关紧要,因为查询定义的是逻辑结果,而不是执行顺序。重要的是DBMS想要检查它们的顺序以有效地返回该数据。
例如,假设我们知道x
和y
从0
均匀分布到99
。对于WHERE x = 0 AND y = 42
子句,我们使用哪个索引并不重要:
- 如果我们在
(x, y)
上使用索引,我们跳转到x=0
的桶,并在该桶中查找y=42
项。 - 如果我们在
(y, x)
上使用索引,我们跳转到y=42
的桶,并在该桶中查找x=0
的项
但是如果想处理WHERE x <> 0 AND y = 42
子句,这就有很大的不同了:
- 如果我们在
(x, y)
上使用索引,我们必须查看x=1
,x=2
,…x=99
;然后在每个桶中查找y=42
的记录 - 如果我们在
(y, x)
上使用索引,我们可以直接跳到y=42
的桶,跳过x=0
的项目,并返回桶的其余部分
这是DBMS中的查询规划器将评估的一种决策:根据有关数据的可用统计信息,哪种操作顺序最有可能产生最快的结果。
虽然这些查询规划器非常复杂,但您了解您的数据,以及您想要使用它的方式,这是他们所不知道的。即使您相信查询规划器永远不会选择错误的索引,添加更多索引也会增加存储成本,并且在每次INSERT、UPDATE和DELETE时都需要额外的处理。