更新 postgres 后,我注意到我正在使用的查询之一变得慢得多。运行后,EXPLAIN ANALYZE
我看到它现在在同一个查询上使用不同的索引。
在其他列中,我的表有一applicationid
列是外键BIGINT
,我有一attributes
列是jsonb
键/值映射。
表中的描述coupons
是(省略了一些不相关的部分):
+------------------------+--------------------------+-------------------------------------------------------+
| Column | Type | Modifiers |
|------------------------+--------------------------+-------------------------------------------------------|
| id | integer | not null default nextval('coupons_id_seq'::regclass) |
| created | timestamp with time zone | not null default now() |
| campaignid | bigint | |
| value | text | |
| expirydate | timestamp with time zone | |
| startdate | timestamp with time zone | |
| attributes | jsonb | not null default '{}'::jsonb |
| applicationid | bigint | |
| deleted | timestamp with time zone | |
| deleted_changelogid | bigint | not null default 0 |
| accountid | bigint | not null |
| recipientintegrationid | text | |
+------------------------+--------------------------+-------------------------------------------------------+
Indexes:
"coupons_applicationid_value_idx" UNIQUE, btree (applicationid, value) WHERE deleted IS NULL
"coupons_attrs_index" gin (attributes)
"coupons_recipientintegrationid_idx" btree (recipientintegrationid)
"coupons_value_trgm_idx" gin (value gin_trgm_ops)
我正在运行的查询是(省略了一些不相关的部分):
EXPLAIN ANALYZE SELECT
*,
COUNT(*) OVER () AS total_rows
FROM
coupons
WHERE
deleted IS NULL
AND coupons.applicationid = 2
AND coupons.attributes @> '{"SessionId":"1070695459"}'
ORDER BY
id ASC
LIMIT 1000;
applicationid
对我们帮助不大。之前使用的索引是coupons_attrs_index
(超过attributes
列),它产生了非常好的结果。
然而,在更新之后,查询规划coupons_applicationid_value_idx
器出于某种原因开始偏爱索引!
这是输出EXPLAIN ANALYZE
(省略了一些不相关的部分):
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| QUERY PLAN |
|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| -> Sort (cost=64.09..64.10 rows=1 width=237) (actual time=3068.996..3068.996 rows=0 loops=1) |
| Sort Key: coupons.id |
| Sort Method: quicksort Memory: 25kB |
| -> WindowAgg (cost=0.86..64.08 rows=1 width=237) (actual time=3068.988..3068.988 rows=0 loops=1) |
| -> Nested Loop (cost=0.86..64.07 rows=1 width=229) (actual time=3068.985..3068.985 rows=0 loops=1) |
| -> Index Scan using coupons_applicationid_value_idx on coupons (cost=0.43..61.61 rows=1 width=213) (actual time=3068.984..3068.984 rows=0 loops=1) |
| Index Cond: (applicationid = 2) |
| Filter: (attributes @> '{"SessionId": "1070695459"}'::jsonb) |
| Rows Removed by Filter: 2344013 |
| Planning Time: 0.531 ms |
| Execution Time: 3069.076 ms |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
EXPLAIN
Time: 3.159s (3 seconds), executed in: 3.102s (3 seconds)
谁能帮我理解为什么查询计划器在更新后使用效率较低的索引(coupons_applicationid_value_idx
而不是coupons_attrs_index
)?
在该索引上添加混合(BTREE + GIN)索引后(applicationid, attributes)
,选择有效地解决了该问题。我仍然想了解发生了什么来预测未来这样的问题。
[编辑 31-01-20 11:02]:问题在 24 小时后返回。计划者再次选择了错误的索引,查询变得很慢。运行一个简单的analyze
解决了它。还是很奇怪,更新到 PG 11 之后才开始发生。