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

时间:2018-03-12 16:38:14

标签: sql postgresql left-join query-optimization

我的应用程序中有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

当我对此查询运行explain analyze时,我看到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以及我还需要哪些索引?此外,如果我必须多次运行此连接,视图会更好吗?感谢

1 个答案:

答案 0 :(得分:1)

10 mins可能会让优化人员感到困难。

一种选择是使用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

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