我在Heroku Postgres 12.16中查询一个大小为2 700 000行的表:
SELECT 1 AS one
FROM "users"
WHERE (
external_id = 18
AND (email = '[email protected]'
OR uuid = '779c7963-67b2-43ea-b19b-028759a146dc'))
LIMIT 1
执行时间为1497.968 ms。
对于EXPLAIN ANALYZE
,它返回以下内容:
"Limit (cost=1000.11..41646.06 rows=1 width=4) (actual time=491.141..1497.948 rows=1 loops=1)"
" -> Gather (cost=1000.11..82292.01 rows=2 width=4) (actual time=491.140..1497.946 rows=1 loops=1)"
" Workers Planned: 1"
" Workers Launched: 1"
" -> Parallel Index Only Scan using index_users_on_external_id_and_email_and_uuid on users (cost=0.11..81291.81 rows=1 width=4) (actual time=953.762..953.762 rows=0 loops=2)"
" Index Cond: (external_id = 18)"
" Filter: (((email)::text = '[email protected]'::text) OR ((uuid)::text = '779c7963-67b2-43ea-b19b-028759a146dc'::text))"
" Rows Removed by Filter: 1111474"
" Heap Fetches: 3238"
"Planning Time: 0.139 ms"
"Execution Time: 1497.968 ms"
我看到总成本太高(81291.81),我怀疑这是查询运行如此缓慢的原因。
总成本的原因是什么?我如何优化它?
我已经运行了VACCUUM ANALYZE users
,希望它能改进查询,但它还是一样。
1条答案
按热度按时间zd287kbt1#
成本是一个估计。高成本并不会导致查询变慢,它只是反映了查询变慢的预期。如果计划器正确地估计出您将过滤掉如此多的行,那么就有充分的理由认为它会很慢。
如果你在
(external_id, email)
和(external_id, uuid)
上都有单独的索引,那么你应该能够得到一个非常有效的BitmapOr操作。显然,您已经在(external_id, email, uuid)
上有了一个索引,所以第一个索引已经覆盖,您只需添加第二个索引。