PostgreSQL: OFFSET 0 and 1 is not working

huangapple go评论54阅读模式
英文:

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>.

huangapple
  • 本文由 发表于 2023年3月9日 18:06:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/75683078.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定