Sql 一致获取特定查询的postgres查询计划以使用索引而不是扫描

Sql 一致获取特定查询的postgres查询计划以使用索引而不是扫描,sql,database,performance,postgresql,database-performance,Sql,Database,Performance,Postgresql,Database Performance,一段时间以来,我一直在努力想办法让查询计划变得更聪明一点,但现在却没有成功。我与同事和朋友们混在一起,运行了大量的vacumm analyze并尝试用order by更改查询。我已经用不同的偏移量包含了相同查询的3次运行。我的印象是,这个查询的性能并没有达到预期的水平。有什么想法吗 以防万一,它不会跳到您身上——以下查询之间唯一的变化是偏移量 bloomapi=# explain analyze SELECT * FROM npis WHERE provider_last_name_legal_

一段时间以来,我一直在努力想办法让查询计划变得更聪明一点,但现在却没有成功。我与同事和朋友们混在一起,运行了大量的
vacumm analyze
并尝试用
order by
更改查询。我已经用不同的偏移量包含了相同查询的3次运行。我的印象是,这个查询的性能并没有达到预期的水平。有什么想法吗

以防万一,它不会跳到您身上——以下查询之间唯一的变化是
偏移量

bloomapi=# explain analyze SELECT * FROM npis WHERE provider_last_name_legal_name = 'THOMPSON' offset 250 limit 10;
                                                                             QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=965.13..998.97 rows=10 width=2589) (actual time=568.458..577.507 rows=10 loops=1)
   ->  Bitmap Heap Scan on npis  (cost=119.15..20382.11 rows=5988 width=2589) (actual time=58.140..577.027 rows=260 loops=1)
         Recheck Cond: ((provider_last_name_legal_name)::text = 'THOMPSON'::text)
         ->  Bitmap Index Scan on npis_temp_provider_last_name_legal_name_idx1  (cost=0.00..117.65 rows=5988 width=0) (actual time=36.819..36.819 rows=5423 loops=1)
               Index Cond: ((provider_last_name_legal_name)::text = 'THOMPSON'::text)
 Total runtime: 578.301 ms
(6 rows)

bloomapi=# explain analyze SELECT * FROM npis WHERE provider_last_name_legal_name = 'THOMPSON' offset 100 limit 10;
                                                                             QUERY PLAN
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=395.81..435.40 rows=10 width=2589) (actual time=0.397..0.440 rows=10 loops=1)
   ->  Index Scan using npis_temp_provider_last_name_legal_name_idx1 on npis  (cost=0.00..23701.38 rows=5988 width=2589) (actual time=0.063..0.293 rows=110 loops=1)
         Index Cond: ((provider_last_name_legal_name)::text = 'THOMPSON'::text)
 Total runtime: 0.952 ms
(4 rows)

bloomapi=# explain analyze SELECT * FROM npis WHERE provider_last_name_legal_name = 'THOMPSON' offset 4100 limit 10;
                                                                            QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=13993.25..14027.09 rows=10 width=2589) (actual time=9356.723..9400.021 rows=10 loops=1)
   ->  Bitmap Heap Scan on npis  (cost=119.15..20382.11 rows=5988 width=2589) (actual time=2.968..9393.327 rows=4110 loops=1)
         Recheck Cond: ((provider_last_name_legal_name)::text = 'THOMPSON'::text)
         ->  Bitmap Index Scan on npis_temp_provider_last_name_legal_name_idx1  (cost=0.00..117.65 rows=5988 width=0) (actual time=1.943..1.943 rows=5423 loops=1)
               Index Cond: ((provider_last_name_legal_name)::text = 'THOMPSON'::text)
 Total runtime: 9400.426 ms
(6 rows)
一些相关说明:

  • 在运行第一个查询之前,我清除了系统上的共享内存,因此第一个查询的一些实际时间可能会受到索引加载的影响
  • 数据很宽且稀疏——329列,其中许多是空字符(30ish)
  • 数据实际上是只读的——每周用另外15k行更新一次
  • 当ubuntu ppa附带了默认的db设置时,对于相同的查询,这些查询的性能实际上更高(我目前没有这些查询计划,但如果没有明显的异常情况,可以深入研究它们)。已从默认值更改的参数:共享缓冲区=256MB,有效缓存大小=512MB,检查点分段=64,检查点完成目标=0.9,默认统计目标=500
  • 实际数据约400万行/1.29GB对于表本身,提供程序\u last\u name\u legal\u name是btree索引的——索引大小为95mb。大约有3/4的行在此列中有一个非空值,整个表有488k个不同的值

我有根据地猜测,大的偏移量触发了这些计划。即使将结果限制为十行,PostgreSQL也必须考虑所有前面的行。我怀疑当您删除
偏移量
(例如,在第一个查询中使用
limit 260
)时,您将看到类似的运行时

可以使用禁用某些计划类型,直到查询共享类似的计划。这可能会帮助您了解为什么一个计划比另一个更好

set enable_bitmapscan = false;

您是否尝试将
random\u page\u cost
设置为较低的值(~1.5)?顺便问一下:你的
工作记忆设置是什么?
另外:
有效缓存大小=512M
似乎很低;你的1.3GB表应该(几乎)适合核心,至少是索引。顺便说一句:我不赞成没有订单的限制/偏移量。在似乎也要编制索引的文本列上。
提供者的姓氏法律名称的基数是多少?最后:1.2G大小/4mrrows:=300字节/行,这似乎有点高。顺便说一句:如何将329列放入300字节?@wildplasser将随机页面成本设置得更低确实会使规划器估计索引扫描速度更快,以获得更高的偏移量,但规划器仍在700左右切换,随机页面成本=1.5。这就是说,即使是索引扫描性能也会受到很大的影响。要回答将329列调整为300字节的问题,大多数列都是空的/表非常稀疏。@wildplasser同样,基数也不是超高/超低的——在4M行中的3M行上有488k不同的值(最后1M行是空的)。这是一张美国人姓氏表,所以它的频率分布可能与我知道的幂律分布相似。但坏消息是,给定300多列,您可能会遇到数据建模问题。(就我个人而言,我甚至无法想象300多个列是完全独立/正交的。这种事情可能发生在高等数学中。甚至在物理中也不会发生)谢谢!虽然这并没有解决我的性能问题,但它确实回答了我的问题/帮助我调试并发现正在使用的查询计划并不是那么愚蠢。高偏移量的索引扫描也很慢。在切换正确的地方有一个更高的偏移量——但总体上偏移量似乎只是低性能操作(参见上Tom Lane-2的回复)。我可能需要找到一种更具创造性的查询方式,或者对这种类型的查询性能要求较低。