postgresql,查询运行缓慢

Posted

技术标签:

【中文标题】postgresql,查询运行缓慢【英文标题】:postgresql, query running slow 【发布时间】:2020-05-02 04:29:34 【问题描述】:

这张桌子相当大(与我拥有的其他桌子相比)。 似乎有索引可以帮助对查询中的每一列进行排序。

如何加快查询速度?

(我唯一能想到的就是创建一个包含行子集的视图,因为我只需要使用最近的数据)

解释 SELECT "rating_ratinghistory"."id", "rating_ratinghistory"."user_id", "rating_ratinghistory"."content_type_id", "rating_ratinghistory"."object_id", "rating_ratinghistory"."rating_type", "rating_ratinghistory"."time_stamp", "rating_ratinghistory"."score", "rating_ratinghistory"."extra" FROM "rating_ratinghistory" WHERE ("rating_ratinghistory"."content_type_id" = 97 AND "rating_ratinghistory"."object_id" = 2876) 排序方式 "rating_ratinghistory"."id" DESC LIMIT 100;

                                                            QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=6708.03..6708.28 rows=100 width=58)
   ->  Sort  (cost=6708.03..6709.99 rows=783 width=58)
         Sort Key: id DESC
         ->  Bitmap Heap Scan on rating_ratinghistory  (cost=46.34..6678.11 rows=783 width=58)
               Recheck Cond: (object_id = 2876)
               Filter: (content_type_id = 97)
               ->  Bitmap Index Scan on rating_ratinghistory_object_id_7bce52873f671c64_uniq  (cost=0.00..46.14 rows=1827 width=0)
                     Index Cond: (object_id = 2876)
(8 rows)



littlehome_db=# \d+ rating_ratinghistory;
                                                             Table "public.rating_ratinghistory"
     Column      |           Type           | Collation | Nullable |                     Default                      | Storage  | Stats target | Description
-----------------+--------------------------+-----------+----------+--------------------------------------------------+----------+--------------+-------------
 id              | integer                  |           | not null | nextval('rating_ratinghistory_id_seq'::regclass) | plain    |              |
 user_id         | integer                  |           | not null |                                                  | plain    |              |
 content_type_id | integer                  |           | not null |                                                  | plain    |              |
 object_id       | integer                  |           | not null |                                                  | plain    |              |
 rating_type     | smallint                 |           | not null |                                                  | plain    |              |
 score           | smallint                 |           |          |                                                  | plain    |              |
 time_stamp      | timestamp with time zone |           | not null |                                                  | plain    |              |
 extra           | jsonb                    |           |          |                                                  | extended |              |
Indexes:
    "rating_ratinghistory_pkey" PRIMARY KEY, btree (id)
    "rating_ratinghistory_content_type_id" btree (content_type_id)
    "rating_ratinghistory_object_id_7bce52873f671c64_uniq" btree (object_id)
    "rating_ratinghistory_rating_type_5cf76626ba8bfa19_uniq" btree (rating_type)
    "rating_ratinghistory_time_stamp_60ddba37d740eb52_uniq" btree (time_stamp)
    "rating_ratinghistory_user_id" btree (user_id)
Check constraints:
    "rating_ratinghistory_object_id_check" CHECK (object_id >= 0)
Foreign-key constraints:
    "content_type_id_refs_id_47e22c61" FOREIGN KEY (content_type_id) REFERENCES django_content_type(id) DEFERRABLE INITIALLY DEFERRED
    "user_id_refs_id_d2d9be0d" FOREIGN KEY (user_id) REFERENCES custom_auth_customuser(id) DEFERRABLE INITIALLY DEFERRED
Referenced by:
    TABLE "rating_ratinghistoryarchive" CONSTRAINT "rating_ratinghistory_ratinghistory_ptr_id_7ee35035_fk_rating_ra" FOREIGN KEY (ratinghistory_ptr_id) REFERENCES rating_ratinghistory(id) DEFERRABLE INITIALLY DEFERRED
Options: autovacuum_vacuum_scale_factor=0.0, autovacuum_analyze_scale_factor=0.0, autovacuum_vacuum_threshold=10000


# SELECT reltuples::bigint AS estimate FROM pg_class where relname='rating_ratinghistory';
 estimate
----------
 16845244
(1 row)


# select * from rating_ratinghistory limit 10;
    id    | user_id | content_type_id | object_id | rating_type | score |          time_stamp           | extra
----------+---------+-----------------+-----------+-------------+-------+-------------------------------+-------
 22846739 |   20298 |             103 |     31111 |          20 |       | 2019-09-15 18:49:49.572748+00 |
 17771225 |  253926 |              97 |      4062 |          40 |    10 | 2019-01-11 05:44:37.224198+00 |
 17771315 |      26 |             103 |     29050 |          20 |       | 2019-02-10 18:41:17.184759+00 |
 17771314 |  253399 |             103 |     29688 |          20 |       | 2019-02-10 18:41:17.187224+00 |
 17771312 |  173965 |             103 |     26608 |          20 |       | 2019-02-10 18:41:17.191079+00 |
 17771311 |  173965 |              97 |      3453 |          20 |       | 2019-02-10 18:41:17.1934+00   |
 17771310 |  251131 |             103 |     25990 |          20 |       | 2019-02-10 18:41:17.195314+00 |
 17771309 |  173965 |             103 |     28727 |          20 |       | 2019-02-10 18:41:17.198409+00 |
 17771308 |  173965 |              97 |      4839 |          20 |       | 2019-02-10 18:41:17.204428+00 |
 17771307 |  251131 |              97 |      2986 |          20 |       | 2019-02-10 18:41:17.207107+00 |

【问题讨论】:

希望你现在能看得更清楚,我添加了示例数据@TimBiegeleisen 【参考方案1】:

我并没有试图混淆整个解释计划,但这里是我为您的查询建议的复合索引:

CREATE INDEX idx ON rating_ratinghistory (content_type_id, object_id, id DESC);

这涵盖了WHERE 子句,包括出现在那里的两列,还包括出现在ORDER BY 中的id 列。

我在查看您当前的索引时看到的主要问题是它们都不是复合的。

【讨论】:

谢谢,既然我使用了ORDER BY "rating_ratinghistory"."id" DESC ,我应该使用(content_type_id, object_id, id desc) 吗? @eugene 在索引中使用id DESC。请注意,Postgres 可能仍然能够使用id ASC,因为它可能能够反向扫描。 哇,它从 4000 毫秒降到了 40 毫秒,我并不是完全不知道复合索引...我应该阅读它 实际上我很惊讶您以前的任何索引都被使用了; Postgres 优化器开始变得非常好。要了解我在回答中的建议,只需了解如何使用 B 树即可。 我以为我知道 b-tree 是如何工作的,我记得它在“单”列上工作,所以我猜复合索引在多个索引上使用 b-tree,我想我必须重新 -访问 b-tree..

以上是关于postgresql,查询运行缓慢的主要内容,如果未能解决你的问题,请参考以下文章

Postgres 运行缓慢的删除查询

postgresql,查询运行缓慢

Postgres 选择查询在使用 JDBC 时运行缓慢,但在从同一服务器在 PSQL 中运行时快速

更新查询 Postgresql 更新缓慢

Postgres 进程显示 100% CPU 但实际使用率为 6%,导致查询响应缓慢

Postgresql 通过网络非常缓慢地发送查询结果