Postgres 优化器对于同一 SQl 查询中的不同值给出不同的结果

问题描述 投票:0回答:1

我有一个 SQL 查询,当语言选择从“英语,葡萄牙语”更改为“荷兰语,葡萄牙语”时,它给出 2 个不同的执行计划。选择“荷兰语,葡萄牙语”效果很好,但不适用于“英语,葡萄牙语”。我可以看到优化器已为“英语,葡萄牙语”选择了哈希连接,甚至为两种不同的情况选择了不同的索引。请建议是否有解决办法。

针对性能不佳的查询“英语,葡萄牙语”的查询计划

---------------------------------------------------------
Hash Join (cost=17528.25..38211.18 rows=36 width=88) (actual time=199235.583..199237.334 rows=1 loops=1)
Hash Cond: (("PC0".Referencekey)::text = ("Case".Primarykey)::text)
-> Index Scan using bulkprocessfrombasket on TAB1 "PC0" (cost=0.68..20630.90 rows=20078 width=113) (actual time=0.023..237.373 rows=22012 loops=1)
Index Cond: ((OpId)::text = 'CustomerService2ndLine'::text)
Filter: ((ObjType)::text = 'Assign-WorkBasket'::text)
-> Hash (cost=17288.84..17288.84 rows=19099 width=35) (actual time=198974.541..198974.542 rows=178642 loops=1)
Buckets: 262144 (originally 32768) Batches: 1 (originally 1) Memory Usage: 14450kB
-> Index Scan using Laguageindex on tip_cs_work "Case" (cost=0.43..17288.84 rows=19099 width=35) (actual time=0.050..198698.998 rows=178642 loops=1)
Index Cond: (((Laguage)::text = ANY ('{English,Portuguese}'::text[])) AND ((Laguage)::text = 'Portuguese'::text))
Filter: ((ObjType)::text ~~ 'Tran-TIP-CS-Work%'::text)
Planning Time: 4.292 ms
Execution Time: 199237.660 ms
(12 rows)

可接受的“荷兰语、葡萄牙语”执行查询的查询计划

-----------------------------------------------------------------
Gather (cost=1001.24..42048.70 rows=46 width=88) (actual time=1563.109..1570.671 rows=1 loops=1)
Workers Planned: 2
Workers Launched: 2
-> Nested Loop (cost=1.24..41044.10 rows=19 width=88) (actual time=1525.785..1547.967 rows=0 loops=3)
-> Parallel Index Scan using bulkprocessfrombasket on TAB1 "PC0" (cost=0.68..20475.40 rows=8362 width=113) (actual time=5.513..1021.457 rows=7342 loops=3)
Index Cond: ((OpId)::text = 'CustomerService2ndLine'::text)
Filter: ((ObjType)::text = 'Assign-WorkBasket'::text)
-> Index Scan using pca_work_pk1 on tip_cs_work "Case" (cost=0.56..2.46 rows=1 width=35) (actual time=0.070..0.070 rows=0 loops=22025)
Index Cond: ((Primarykey)::text = ("PC0".Referencekey)::text)
Filter: (((ObjType)::text ~~ 'Tran-TIP-CS-Work%'::text) AND ((Laguage)::text = ANY ('{Dutch,Portuguese}'::text[])) AND ((Laguage)::text = 'Portuguese'::text))
Rows Removed by Filter: 0
Planning Time: 1.117 ms
Execution Time: 1570.740 ms
(13 rows)
postgresql performance indexing hash explain
1个回答
0
投票

这个糟糕的计划有一些愚蠢的地方:

(((语言)::text = ANY ('{英语,葡萄牙语}'::text[])) AND ((语言)::text = '葡萄牙语'::text))

大概这或多或少直接来自您的查询。如果 laguage 等于 'Portuguese',显然它也是 =ANY('{English,Portuguese}')。规划者可以检测并忽略一些冗余,但这个不行。它将独立估计每个条件并将它们相乘,导致估计行数太低(我们确实看到,估计=19099实际=178642)。如果这个问题得到解决,它可能会选择一个更好的计划,但我们无法根据手头的信息确定这一点。

为什么其他情况下的类似愚蠢行为不会导致一个糟糕的计划?据推测,这种情况下的行估计是不同的,但我们无法在您的计划中真正看到它,因为备用计划中从未报告该特定的行估计。

如果您想进一步深入研究这一点,您可能会提出一个计划,该计划将为我们提供我们需要通过执行以下操作看到的估计和实际行数:

EXPLAIN (ANALYZE) 
select * from tip_cs_work where Laguage =ANY ('{Dutch,Portuguese}'::text[]) AND Laguage = 'Portuguese'
© www.soinside.com 2019 - 2024. All rights reserved.