heroku 为什么索引扫描成本太高?

dldeef67  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(126)

我在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,希望它能改进查询,但它还是一样。

zd287kbt

zd287kbt1#

成本是一个估计。高成本并不会导致查询变慢,它只是反映了查询变慢的预期。如果计划器正确地估计出您将过滤掉如此多的行,那么就有充分的理由认为它会很慢。
如果你在(external_id, email)(external_id, uuid)上都有单独的索引,那么你应该能够得到一个非常有效的BitmapOr操作。显然,您已经在(external_id, email, uuid)上有了一个索引,所以第一个索引已经覆盖,您只需添加第二个索引。

相关问题