在Postgres中,为什么有可能以不同的顺序索引同一组列?



在Postgres数据库中,我注意到我可以在同一组列上添加复合索引键,但顺序不同。例句:

创建索引index_1。A USING btree (x, y);创建索引index_2。A USING btree (y, x);

请注意,索引的不同之处在于被索引的列的顺序。

我希望Postgres将列列表视为无序集合。

这种添加两个相似索引的能力是否意味着WHERE和ON子句中条件的顺序对检索速度有影响?

我希望Postgres将列列表视为无序集合。

原因很简单:计算机内存不是多维的。

假设您有10个项目,每个项目都有xy的唯一组合。在纸上,你可以把它们画在一个网格上,x在一个轴上,y在另一个轴上。要查找特定x的所有值,可以沿着相应的行查找;对于特定y的所有值,请向下查找相应的列。如果你需要三个变量,就很难在纸上画出来,但你可以想象一个立方体;数学家将可视化高维的"超立方体"。

计算机内存(和存储)不是这样工作的;它只是一个记录的线性列表,一个接一个。所以你的双元素索引不是存储为一个网格,而是存储为一个排序列表。如果索引位于(x, y)上,则基本排列如下:

  • x
  • 排序
  • 在具有相同x的每个组中,按y对这些记录进行排序

(实际结构比列表更复杂,因此很容易跳转到正确的组,并且您不必在每次需要添加低值x时重写整个索引,但我认为一般原则对于当前的讨论来说已经足够好了。)

现在,如果您想找到具有特定x的所有元素,您可以跳转到该记录组,并返回它们。但是如果你想找到具有特定y的所有元素,你必须查看每个组,看看是否有。

这种添加两个相似索引的能力是否意味着WHERE和ON子句中条件的顺序对检索速度有影响?

它们在查询中出现的顺序通常无关紧要,因为查询定义的是逻辑结果,而不是执行顺序。重要的是DBMS想要检查它们的顺序以有效地返回该数据。

例如,假设我们知道xy0均匀分布到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时都需要额外的处理。

相关内容

  • 没有找到相关文章

最新更新