英文:
PostgreSQL: OFFSET 0 and 1 is not working
问题
I am facing a weird issue with PostgreSQL query. If I set OFFSET 0
or 1
it shows Waiting for the query to complete... forever. As soon as I change OFFSET 2
or any other value it works fine.
Here is my query:
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
EXPLAIN information for 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 has very heavy top-level costs.
Nested Loop (cost=0.85..215537958.57
Does anyone guess the issue?
PostgreSQL version: PostgreSQL 13.7
英文:
I am facing a weird issue with PostgreSQL query. If I set OFFSET 0
or 1
it shows Waiting for the query to complete... forever. As soon as I change OFFSET 2
or any other value it works fine.
Here is my query:
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
EXPLAIN information for
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 has very heavy top-level costs.
Nested Loop (cost=0.85..215537958.57
Does anyone guess the issue?
Postgre version: PostgreSQL 13.7
答案1
得分: 1
PostgreSQL认为按id
顺序扫描markers
并在找到足够的结果之前加入locations
行是一种可行的策略,如果只需要很少的行。显然,优化器在这个假设上是错误的。
我不知道如何改进优化器的估计,但您可以通过将ORDER BY
条件更改为
ORDER BY m.id + 0
来强制PostgreSQL避免慢查询计划,这样PostgreSQL不能使用索引扫描来支持它。只有当索引在some_expression
上时,PostgreSQL才能用索引来进行ORDER BY some_expression
。
英文:
PostgreSQL believes that scanning markers
in id
order and joining locations
rows until it has found enough results is a viable strategy if few rows are needed. Obviously the optimizer is wrong in this assumption.
I have no idea how to improve the optimizer's estimates here, but you can force PostgreSQL to avoid the slow query plan by changing the ORDER BY
condition to
ORDER BY m.id + 0
so that PostgreSQL cannot use an index scan to support it. PostgreSQL can only use an index for <code>ORDER BY some_expression</code> if there is an index on <code>some_expression</code>.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论