我有以下SQL(简化和匿名,以便更容易理解)
select max(db.tableA."id")
from db.tableA
left outer join db.tableB
on (db.tableB.column1 = db.tableA.column1
and db.tableB.column2 = db.tableA.column2
and db.tableB.column3 = db.tableA.column3
and db.tableB.column4 = db.tableA.column4)
where (db.tableA.column1 = 'SOME_VALUE'
and db.tableA.column2 in ('some', 'list', 'of', 'values')
and db.tableB.column2 is null)
由于某些原因,这个SQL有时甚至运行20秒。当我使用EXPLAIN ANALYZE
时,我看到一些我不太理解的东西。
-> Partial Aggregate (cost=11704.05..11704.06 rows=1 width=8) (actual time=62.069..62.110 rows=1 loops=5)
-> Hash Anti Join (cost=34.58..11679.12 rows=9970 width=8) (actual time=62.064..62.105 rows=0 loops=5)
Hash Cond: ((_hyper_1_11005_chunk.column1= tableB.column1) AND (_hyper_1_11005_chunk.column2= tableB.column2) AND (_hyper_1_11005_chunk.column3= tableB.column3) AND (_hyper_1_11005_chunk.column4= tableB.column4))
-> Parallel Append (cost=0.02..11369.08 rows=11389 width=29) (actual time=0.038..47.278 rows=11262 loops=5)
-> Parallel Seq Scan on _hyper_1_11005_chunk (cost=0.02..462.20 rows=1667 width=29) (actual time=0.041..13.213 rows=2834 loops=1)
" Filter: ((column1= 'SOME_VALUE'::text) AND (column2= ANY ('{'some', 'list', 'of', 'values'}'::text[])))"
此列表还包含大量Parallel Seq Scan
步骤(每个步骤都具有相同的条件,只是在另一个块上)
包含上述SQL中任何列的表的索引为(为简单起见,省略了主键的索引)
表A
- (第1栏、第2栏、第3栏、第4栏)
表B - (第一栏、第二栏)
我可能丢失了一些索引或其他东西,因为我认为这个SQL运行几秒钟并不复杂,但我不知道我丢失了什么,有人能帮我理解为什么PostgreSQL使用多个顺序扫描将这些表连接在一起吗?
PostgreSQL版本为14.5
**编辑:**根据要求,详细分析结果、设置、缓冲区如下所示(由于长度为Explain result,通过pastebin粘贴)
1条答案
按热度按时间6mzjoqzu1#
正如我所写的,如果clomun2总是有值,您可以尝试
如果这样做还不够快的话,您可以将IN子句与
SELECT
s和UNION ALL
分开,这样就可以避免完整扫描,当然只有在列表很小时才可以这样做