低限 LIMIT/高 OFFSET 的成本非常高

发布于 2024-10-12 19:57:04 字数 1090 浏览 0 评论 0原文

我有一张非常大的桌子,里面摆满了产品。我需要选择几种偏移量非常高的产品(如下例)。关于索引和性能的 Postgresql 手册建议在 ORDER BY + 最终条件使用的列上创建索引。一切都是桃色的,没有使用任何种类。但对于高偏移值,LIMIT 的成本非常高。任何人都知道这可能是什么原因?

以下查询可能会运行几分钟。

Indexes:
"product_slugs_pkey" PRIMARY KEY, btree (id)
"index_for_listing_by_default_active" btree (priority DESC, name, active)
"index_for_listing_by_name_active" btree (name, active)
"index_for_listing_by_price_active" btree (master_price, active)
"product_slugs_product_id" btree (product_id)

EXPLAIN SELECT * FROM "product_slugs" WHERE ("product_slugs"."active" = 1) ORDER BY product_slugs.name ASC LIMIT 10 OFFSET 14859;
                                                       QUERY PLAN                                                        
-------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=26571.55..26589.43 rows=10 width=1433)
   ->  Index Scan using index_for_listing_by_name_active on product_slugs  (cost=0.00..290770.61 rows=162601 width=1433)
         Index Cond: (active = 1)
(3 rows)

I'm having very large table with products. I need to select several products at very high offset (example below). Postgresql manual on indexes and performance suggests to create index on column that's used by ORDER BY + eventual conditions. Everything is peachy, no sort is used. but for high offset values LIMIT is very costly. Anyone have any idea what might be a cause for that?

Following query can run for minutes.

Indexes:
"product_slugs_pkey" PRIMARY KEY, btree (id)
"index_for_listing_by_default_active" btree (priority DESC, name, active)
"index_for_listing_by_name_active" btree (name, active)
"index_for_listing_by_price_active" btree (master_price, active)
"product_slugs_product_id" btree (product_id)

EXPLAIN SELECT * FROM "product_slugs" WHERE ("product_slugs"."active" = 1) ORDER BY product_slugs.name ASC LIMIT 10 OFFSET 14859;
                                                       QUERY PLAN                                                        
-------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=26571.55..26589.43 rows=10 width=1433)
   ->  Index Scan using index_for_listing_by_name_active on product_slugs  (cost=0.00..290770.61 rows=162601 width=1433)
         Index Cond: (active = 1)
(3 rows)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

且行且努力 2024-10-19 19:57:04

这里的 index_for_listing_by_name_active 索引不会有太大帮助,因为结果集中的产品不一定在索引中是连续的。尝试仅在那些处于活动状态的产品上按名称创建条件索引:

CREATE INDEX index_for_listing_active_by_name
  ON product_slugs (name)
  WHERE product_slugs.active = 1;

The index_for_listing_by_name_active index you have here isn't going to help much, since the products in the result set aren't necessarily going to be contiguous in the index. Try creating a conditional index by name on only those products which are active:

CREATE INDEX index_for_listing_active_by_name
  ON product_slugs (name)
  WHERE product_slugs.active = 1;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文