我遇到了一个关于PostgreSQL查询的奇怪问题。如果我设置OFFSET 0
或1
,它会显示**等待查询完成...**永远。只要我改变OFFSET 2
或任何其他值,它就会正常工作。
下面是我的疑问:
SELECT
m.id,
l.uuid,
m.displacement,
m.total_displacement
FROM
locations l
INNER JOIN markers m ON l.id = m.location_id
WHERE
l.uuid = 42901 AND l.type_name = 'ascending'
ORDER BY m.id ASC
LIMIT 100 OFFSET 1
解释信息OFFSET 0
:
Limit (cost=0.85..127003.79 rows=100 width=28)
-> Nested Loop (cost=0.85..215537958.57 rows=169711 width=28)
Join Filter: (l.id = m.location_id)
-> Index Scan using markers_pkey on markers m (cost=0.57..209234879.46 rows=420204720 width=24)
-> Materialize (cost=0.28..8.30 rows=1 width=16)
-> Index Scan using locations_uuid_type_name_key on locations l (cost=0.28..8.30 rows=1 width=16)
" Index Cond: ((uuid = '4294967296001'::bigint) AND ((type_name)::text = 'ascending'::text))"
OFFSET 2
:
Limit (cost=127821.43..127821.68 rows=100 width=28)
-> Sort (cost=127821.43..128245.70 rows=169711 width=28)
Sort Key: m.id
-> Nested Loop (cost=0.57..121310.95 rows=169711 width=28)
-> Seq Scan on locations l (cost=0.00..124.14 rows=1 width=16)
" Filter: ((uuid = '4294967296001'::bigint) AND ((type_name)::text = 'ascending'::text))"
-> Index Scan using markers_location_id_idx on markers m (cost=0.57..118770.45 rows=241636 width=24)
Index Cond: (location_id = l.id)
OFFSET 0具有非常大的顶层开销。嵌套循环**(开销=0.85..215537958.57**
有人猜到问题所在吗?
Postgre版本:PostgreSQL语言13.7
1条答案
按热度按时间dldeef671#
PostgreSQL相信如果只需要很少的行,那么以
id
顺序扫描markers
并连接locations
行直到找到足够的结果是一个可行的策略。显然优化器在这个假设上是错误的。我不知道如何改进优化器的估计,但是您可以强制PostgreSQL避免缓慢的查询计划,方法是将
ORDER BY
条件改为因此PostgreSQL无法使用索引扫描来支持它。PostgreSQL只能在
*some_expression*
上存在索引时使用ORDER BY *some_expression*
索引。