1

更新 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 之后才开始发生。

4

0 回答 0