有没有办法优化这样的查询:
SELECT count(*) FROM mytable
WHERE
indexed_field IN ('v1', 'v2', ..., 'v2000')
AND NOT regular_field='something'
AND other_regular_field='something_else';
Run Code Online (Sandbox Code Playgroud)
这个查询“有效”。问题是它非常慢(1分钟以上)。我认为使用IN定义的列表来使用表达式就可以了,但事实证明并不是那么好。
我正在使用 Postgresql 9.6。
我的表有310K。
查询解释:
QUERY PLAN
Aggregate (cost=396158.70..396158.71 rows=1 width=8) (actual time=8630.558..8630.559 rows=1 loops=1)
-> Seq Scan on mytable (cost=0.00..396156.77 rows=772 width=0) (actual time=7853.840..8630.478 rows=916 loops=1)
Filter: (((non_indexed_field)::text <> 'value1'::text) AND ((non_indexed_field)::text = 'value2'::text) AND ((indexed_field)::text = ANY ('{lots and lots of values....}'::text[])))
Rows Removed by Filter: 306768
Planning time: 2.543 ms
Execution time: 8630.770 ms
Run Code Online (Sandbox Code Playgroud)
通过分析、缓冲:
Aggregate (cost=396158.70..396158.71 rows=1 width=8) (actual time=9278.560..9278.560 rows=1 loops=1)
Buffers: shared hit=14244
-> Seq Scan on mytable (cost=0.00..396156.77 rows=772 width=0) (actual time=8584.520..9278.431 rows=916 loops=1)
Filter: (((non_indexed_field)::text <> 'value1'::text) AND ((non_indexed_field)::text = 'value2'::text) AND ((indexed_field)::text = ANY ('{lots and lots of values}'::text[])))
Rows Removed by Filter: 306768
Buffers: shared hit=14244
Planning time: 1.293 ms
Execution time: 9278.646 ms
(8 rows)
Run Code Online (Sandbox Code Playgroud)
小智 7
很多时候加入 aaVALUES子句会更有效:
SELECT count(*)
FROM mytable
JOIN (
values ('v1'), ('v2'), (...), ('v2000')
) as lookup(value) on lookup.value = mytable.some_column
WHERE NOT other_column = 'something'
AND another_column = 'something_else';
Run Code Online (Sandbox Code Playgroud)
注意“列表”的格式。在values子句中,每个值都需要括在括号中。('v1'), ('v2'), ...代替('v1', 'v2', ...)
在线示例: http: //rextester.com/UUWVG71217
请注意,如果与值进行比较的列确实是数字(例如整数),则不应使用单引号指定值,例如values (1),(2),(3),...(2000)