【问题标题】:Postges - Multi Column Index - Leading (leftmost) columnPostgres - 多列索引 - 前导(最左边)列
【发布时间】:2021-01-19 14:57:51
【问题描述】:

我很好奇多列索引的前导列的概念。

我正在使用这个示例dvdrental db。

这是查询:

SELECT
  title,
  length,
  rating,
  replacement_cost,
  rental_rate
FROM film
WHERE length BETWEEN 60 AND 70
  AND rating = 'G';

我有两个正在使用的索引:

#1

CREATE INDEX IF NOT EXISTS film_idx_length_rating
  ON film(length, rating);

#2

CREATE INDEX IF NOT EXISTS film_idx_rating_length
  ON film(rating, length);

在创建两个索引后,使用规划器选择的索引进行规划:

QUERY PLAN
Bitmap Heap Scan on film  (cost=4.47..39.34 rows=15 width=34) (actual time=0.020..0.033 rows=18 loops=1)
  Recheck Cond: ((rating = 'G'::mpaa_rating) AND (length >= 60) AND (length <= 70))
  Heap Blocks: exact=14
  ->  Bitmap Index Scan on film_idx_rating_length  (cost=0.00..4.46 rows=15 width=0) (actual time=0.015..0.015 rows=18 loops=1)
        Index Cond: ((rating = 'G'::mpaa_rating) AND (length >= 60) AND (length <= 70))
Planning Time: 0.202 ms
Execution Time: 0.065 ms

在执行了查询计划EXPLAIN ANALYZE 之后,规划器选择了第二个查询,但是来自两个索引的查询计划实际上并没有任何显着差异,只有规划器选择的索引。 这是为什么?为什么当rating 用作前导列时,它会被选中而不是length 作为前导列?

来自docs 有这个:

多列 B 树索引可用于涉及索引列的任何子集的查询条件,但当前导(最左侧)列存在约束时,索引效率最高。确切的规则是,前导列上的等式约束,加上没有等式约束的第一列上的任何不等式约束,将用于限制扫描的索引部分。

但我不是很明白,也许有人可以给我一个例子?

谢谢!

【问题讨论】:

  • 是的,已编辑后

标签: postgresql


【解决方案1】:

在开始看到有意义的差异之前,您可能需要使表格比该链接处的表格大几千倍。

对于以相等列开头的索引,它可以跳转到索引内的'G'部分,然后可以跳转到长度为60,并向前读取直到超过70。然后所有这些行都会满足两种资格。

但是对于其他索引,不能直接跳到60,再跳到G段,因为没有一个单独的G段。 60 到 70 之间的每个不同值都有一个 G 部分。所以它最终会扫描从 60 到 70 的所有行,分别过滤掉不是 G 的行。

事实证明,差异并没有那么大,因为大部分时间都花在访问表堆以从表中获取所需的数据,在这种情况下,任一索引都需要访问同一组行。

【讨论】:

  • 简而言之,使用第二个索引,这两个条件都可以用来限制索引中必须扫描的索引条目的数量,而使用第一个索引,只能满足一个条件用于限制扫描的索引条目。另一个条件从表中提取行之前过滤掉扫描条目的结果。
  • 谢谢!我将进一步解决它,但这个解释现在对我来说非常清楚。
猜你喜欢
  • 1970-01-01
  • 2018-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-24
  • 1970-01-01
  • 2012-02-09
相关资源
最近更新 更多