Postgresql 如何防止Postgres内联子查询?

Postgresql 如何防止Postgres内联子查询?,postgresql,indexing,subquery,inlining,Postgresql,Indexing,Subquery,Inlining,这里是一个关于Postgres 9.1.6的慢速查询,尽管最大计数为2,两行都已经由主键标识:(4.5秒) 嗯,如果我先只使用主键部分进行子查询…:(不,仍然是4.5秒以上) 如何防止Postgres内联子查询 背景:我有一个Postgres 9.1表格,上面有和。显然有一个:(0.223ms!) 技巧是子查询中的OFFSET 0。我认为OFFSET 0是更好的方法,因为它更明显地表明正在发生一些奇怪的事情,我们不太可能改变OFFSET 0周围的乐观行为。。。当CTE在某个时刻成为可内联时,CT

这里是一个关于Postgres 9.1.6的慢速查询,尽管最大计数为2,两行都已经由主键标识:(4.5秒)

嗯,如果我先只使用主键部分进行子查询…:(不,仍然是4.5秒以上)

如何防止Postgres内联子查询

背景:我有一个Postgres 9.1表格,上面有和。

显然有一个:(0.223ms!)


技巧是子查询中的
OFFSET 0

我认为
OFFSET 0
是更好的方法,因为它更明显地表明正在发生一些奇怪的事情,我们不太可能改变
OFFSET 0
周围的乐观行为。。。当CTE在某个时刻成为可内联时,CTE在PostgreSQL 12中默认为可内联。以下解释是为了完整起见;用西莫斯的答案

对于不相关的子查询,您可以利用PostgreSQL 11和更早版本拒绝使用查询术语内联
,将您的查询改写为:

WITH t AS (
    SELECT * FROM tbl WHERE id IN ('6d48fc431d21', 'd9e659e756ad')
)
SELECT COUNT(*) 
FROM t 
WHERE data ? 'building_floorspace' 
AND data ?| ARRAY['elec_mean_monthly_use', 'gas_mean_monthly_use'];
这与
OFFSET 0
hack的效果差不多,就像
OFFSET 0
hack利用Pg优化器中的怪癖,人们用它来绕过Pg缺少查询提示的问题。。。将它们用作查询提示


但是
OFFSET 0
hack在某种程度上得到了官方的认可,而在PostgreSQL 12中,CTE滥用不再起作用。(耶!)。

。。。但是PostgreSQL没有查询提示。不,真的我也有类似的问题,但对于单个查询,postgres决定进行全表扫描,而不是索引扫描,从而导致数据库死机。而且它只是偶尔这样做。返回的行数设置为10,即使没有要返回的行数,也会失败。每当它选择索引时——速度极快,选择使用表扫描——行扫描数百万条记录。我想知道当这不是子查询时,
OFFSET 0
是否有帮助?扫描gist索引的成本估算似乎非常错误(4.09,低于访问主键的索引)。你可以检查一下你是否可以做些什么,比如确保新的统计数据和/或增加。我将目标增加到9999,并运行了
VACUUM ANALYZE
。。。仍然得到相同的成本估算与实际差异。不过,谢谢你的建议!从v12开始的Postgres默认内联CTE。我不明白偏移量0的作用。我有一个限制为10的查询(没有子查询),在选取索引时运行得非常快。但同一数据集上的同一查询有时使用索引,有时不导致对10m记录的行扫描。向这样的查询中添加
OFFSET 0
是否有助于它始终选择索引?如果是,原因是什么?@KamilDziedzic这是一种阻止PostgreSQL跨子查询边界内联的方法。
EXPLAIN ANALYZE SELECT COUNT(*) FROM (  SELECT * FROM tbl WHERE id IN ('6d48fc431d21', 'd9e659e756ad')  ) AS t WHERE data ? 'building_floorspace' AND data ?| ARRAY['elec_mean_monthly_use', 'gas_mean_monthly_use'];
                                                                     QUERY PLAN                                                                     
----------------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=4.09..4.09 rows=1 width=0) (actual time=4854.170..4854.171 rows=1 loops=1)
   ->  Index Scan using idx_tbl_on_data_gist on tbl  (cost=0.00..4.09 rows=1 width=0) (actual time=4854.165..4854.165 rows=0 loops=1)
         Index Cond: ((data ? 'building_floorspace'::text) AND (data ?| '{elec_mean_monthly_use,gas_mean_monthly_use}'::text[]))
         Filter: ((id)::text = ANY ('{6d48fc431d21,d9e659e756ad}'::text[]))
 Total runtime: 4854.220 ms
(5 rows)
EXPLAIN ANALYZE SELECT COUNT(*) FROM (  SELECT * FROM tbl WHERE id IN ('6d48fc431d21', 'd9e659e756ad') OFFSET 0 ) AS t WHERE data ? 'building_floorspace' AND data ?| ARRAY['elec_mean_monthly_use', 'gas_mean_monthly_use'];
                                                                QUERY PLAN                                                                
------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=8.14..8.15 rows=1 width=0) (actual time=0.165..0.166 rows=1 loops=1)
   ->  Subquery Scan on t  (cost=4.14..8.14 rows=1 width=0) (actual time=0.160..0.160 rows=0 loops=1)
         Filter: ((t.data ? 'building_floorspace'::text) AND (t.data ?| '{elec_mean_monthly_use,gas_mean_monthly_use}'::text[]))
         ->  Limit  (cost=4.14..8.13 rows=2 width=496) (actual time=0.086..0.092 rows=2 loops=1)
               ->  Bitmap Heap Scan on tbl  (cost=4.14..8.13 rows=2 width=496) (actual time=0.083..0.086 rows=2 loops=1)
                     Recheck Cond: ((id)::text = ANY ('{6d48fc431d21,d9e659e756ad}'::text[]))
                     ->  Bitmap Index Scan on tbl_pkey  (cost=0.00..4.14 rows=2 width=0) (actual time=0.068..0.068 rows=2 loops=1)
                           Index Cond: ((id)::text = ANY ('{6d48fc431d21,d9e659e756ad}'::text[]))
 Total runtime: 0.223 ms
(9 rows)
WITH t AS (
    SELECT * FROM tbl WHERE id IN ('6d48fc431d21', 'd9e659e756ad')
)
SELECT COUNT(*) 
FROM t 
WHERE data ? 'building_floorspace' 
AND data ?| ARRAY['elec_mean_monthly_use', 'gas_mean_monthly_use'];