如何在postgresql 10.3中优化使用seqscan的查询?

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

我的应用程序中有2个表

独特的提醒

asset_id (primary key)
current_price

警报

id (primary key)
userid
asset_id (may appear more than once)
alert_price
direction (contains true or false)

我的警报表有100万行,独特的警报表有40000行,我希望找到所有触发的警报

select * from unique_alerts u
INNER JOIN alerts a
ON u.asset_id=a.asset_id
WHERE u.current_price > a.alert_price 
AND a.direction=true
OR u.current_price <= a.alert_price 
AND a.direction=false

当我对这个查询运行解析分析时,我看到2个顺序扫描,我在a.asset_id上定义了一个索引,它没有被使用

"Hash Join  (cost=1248.49..34977.79 rows=270686 width=72) (actual time=37.698..713.334 rows=21825 loops=1)"
"  Hash Cond: ((a.pair)::text = (u._id)::text)"
"  Join Filter: (((u.current_price > a.alert_price) AND a.direction) OR ((u.current_price <= a.alert_price) AND (NOT a.direction)))"
"  Rows Removed by Join Filter: 857192"
"  ->  Seq Scan on alerts a  (cost=0.00..20490.00 rows=751170 width=52) (actual time=0.014..158.984 rows=1000000 loops=1)"
"        Filter: (direction OR (NOT direction))"
"  ->  Hash  (cost=711.55..711.55 rows=42955 width=20) (actual time=37.528..37.528 rows=42955 loops=1)"
"        Buckets: 65536  Batches: 1  Memory Usage: 2766kB"
"        ->  Seq Scan on unique_alerts u  (cost=0.00..711.55 rows=42955 width=20) (actual time=0.007..4.891 rows=42955 loops=1)"
"Planning time: 0.781 ms"
"Execution time: 714.892 ms"

我如何确保使用索引a.asset_id以及我需要哪些索引?此外,如果我必须多次运行此连接,视图会更好吗?谢谢

sql postgresql left-join query-optimization
1个回答
1
投票

OR可能会让优化者感到困难。

一种选择是使用UNION ALL来允许两个查询计划......

SELECT * FROM unique_alerts u
INNER JOIN alerts a
ON u.asset_id=a.asset_id
WHERE u.current_price > a.alert_price AND a.direction=true

UNION ALL

SELECT * FROM unique_alerts u
INNER JOIN alerts a
ON u.asset_id=a.asset_id
WHERE u.current_price <= a.alert_price AND a.direction=false

如果您打算这样做,我会建议在alerts上使用复合索引:(direction, asset_id, alert_price)

这样的索引可以更容易地缩小适当的行范围。

© www.soinside.com 2019 - 2024. All rights reserved.