复合索引中列的顺序
Order of columns in compound indexes
我在 table 上使用复合索引,记录超过 1300 万条。
index order is (center_code, created_on, status)
。 center_code 和状态都是 varchar(100) 而不是 NULL,created_on 是没有时区的时间戳。
我在某处读到,索引的顺序在复合索引中很重要。我们必须检查唯一值的数量,并将唯一值数量最多的那个放在复合索引的第一位。
- center_code 可以有 4000 个不同的值。
- 状态可以有 5 个不同的值。
- created_on 的最小值为
2017-12-12 02:00:49.465317+00
。
问题是 created_on 的唯一值的数量是多少?
我应该把它放在复合索引的第一位吗?
日期列的索引以日期、小时或秒为基础工作。
问题是:
一个简单的 SELECT 查询花费了 500 多毫秒,它只使用了这个复合索引,没有其他任何东西。
table 上的索引:
Indexes:
"pa_key" PRIMARY KEY, btree (id)
"pa_uniq" UNIQUE CONSTRAINT, btree (wbill)
"pa_center_code_created_on_status_idx_new" btree (center_code, created_on, status)
查询是:
EXPLAIN ANALYSE
SELECT "pa"."wbill"
FROM "pa"
WHERE ("pa"."center_code" = 'IND110030AAC'
AND "pa"."status" IN ('Scheduled')
AND "pa"."created_on" >= '2018-10-10T00:00:00+05:30'::timestamptz);
查询计划:
Index Scan using pa_center_code_created_on_status_idx_new on pa (cost=0.69..3769.18 rows=38 width=13) (actual time=5.592..15.526 rows=78 loops=1)
Index Cond: (((center_code)::text = 'IND110030AAC'::text) AND (created_on >= '2018-10-09 18:30:00+00'::timestamp with time zone) AND ((status)::text = 'Scheduled'::text))
Planning time: 1.156 ms
Execution time: 519.367 ms
非常感谢任何帮助。
索引扫描条件读取
(((center_code)::text = 'IND110030AAC'::text) AND
(created_on >= '2018-10-09 18:30:00+00'::timestamp with time zone) AND
((status)::text = 'Scheduled'::text))
但索引扫描本身仅在 (center_code, created_on)
之上,而 status
上的条件作为过滤器应用。
不幸的是,这在执行计划中是看不到的,但它遵循以下规则:
只有满足条件的行在索引中彼此相邻时,索引扫描才会使用条件。
让我们考虑这个例子(按索引顺序):
center_code | created_on | status
--------------+---------------------+-----------
IND110030AAC | 2018-10-09 00:00:00 | Scheduled
IND110030AAC | 2018-10-09 00:00:00 | Xtra
IND110030AAC | 2018-10-10 00:00:00 | New
IND110030AAC | 2018-10-10 00:00:00 | Scheduled
IND110030AAC | 2018-10-11 00:00:00 | New
IND110030AAC | 2018-10-11 00:00:00 | Scheduled
您会看到查询需要第 4 行和第 6 行。
PostgreSQL 无法扫描具有所有三个条件的索引,因为所需的行彼此不相邻。它只需要扫描前两个条件,因为满足这两个条件的所有行都彼此相邻。
你的多列索引规则是错误的。索引左侧的列必须是在条件中使用 =
作为比较运算符的列。
完美的索引应该是 (center_code, status, created_on)
。
我在 table 上使用复合索引,记录超过 1300 万条。
index order is (center_code, created_on, status)
。 center_code 和状态都是 varchar(100) 而不是 NULL,created_on 是没有时区的时间戳。
我在某处读到,索引的顺序在复合索引中很重要。我们必须检查唯一值的数量,并将唯一值数量最多的那个放在复合索引的第一位。
- center_code 可以有 4000 个不同的值。
- 状态可以有 5 个不同的值。
- created_on 的最小值为
2017-12-12 02:00:49.465317+00
。
问题是 created_on 的唯一值的数量是多少? 我应该把它放在复合索引的第一位吗?
日期列的索引以日期、小时或秒为基础工作。
问题是:
一个简单的 SELECT 查询花费了 500 多毫秒,它只使用了这个复合索引,没有其他任何东西。
table 上的索引:
Indexes:
"pa_key" PRIMARY KEY, btree (id)
"pa_uniq" UNIQUE CONSTRAINT, btree (wbill)
"pa_center_code_created_on_status_idx_new" btree (center_code, created_on, status)
查询是:
EXPLAIN ANALYSE
SELECT "pa"."wbill"
FROM "pa"
WHERE ("pa"."center_code" = 'IND110030AAC'
AND "pa"."status" IN ('Scheduled')
AND "pa"."created_on" >= '2018-10-10T00:00:00+05:30'::timestamptz);
查询计划:
Index Scan using pa_center_code_created_on_status_idx_new on pa (cost=0.69..3769.18 rows=38 width=13) (actual time=5.592..15.526 rows=78 loops=1)
Index Cond: (((center_code)::text = 'IND110030AAC'::text) AND (created_on >= '2018-10-09 18:30:00+00'::timestamp with time zone) AND ((status)::text = 'Scheduled'::text))
Planning time: 1.156 ms
Execution time: 519.367 ms
非常感谢任何帮助。
索引扫描条件读取
(((center_code)::text = 'IND110030AAC'::text) AND
(created_on >= '2018-10-09 18:30:00+00'::timestamp with time zone) AND
((status)::text = 'Scheduled'::text))
但索引扫描本身仅在 (center_code, created_on)
之上,而 status
上的条件作为过滤器应用。
不幸的是,这在执行计划中是看不到的,但它遵循以下规则:
只有满足条件的行在索引中彼此相邻时,索引扫描才会使用条件。
让我们考虑这个例子(按索引顺序):
center_code | created_on | status
--------------+---------------------+-----------
IND110030AAC | 2018-10-09 00:00:00 | Scheduled
IND110030AAC | 2018-10-09 00:00:00 | Xtra
IND110030AAC | 2018-10-10 00:00:00 | New
IND110030AAC | 2018-10-10 00:00:00 | Scheduled
IND110030AAC | 2018-10-11 00:00:00 | New
IND110030AAC | 2018-10-11 00:00:00 | Scheduled
您会看到查询需要第 4 行和第 6 行。
PostgreSQL 无法扫描具有所有三个条件的索引,因为所需的行彼此不相邻。它只需要扫描前两个条件,因为满足这两个条件的所有行都彼此相邻。
你的多列索引规则是错误的。索引左侧的列必须是在条件中使用 =
作为比较运算符的列。
完美的索引应该是 (center_code, status, created_on)
。