PostgreSQL:偏移量0和1不起作用

bqf10yzr  于 2023-03-12  发布在  PostgreSQL
关注(0)|答案(1)|浏览(190)

我遇到了一个关于PostgreSQL查询的奇怪问题。如果我设置OFFSET 01,它会显示**等待查询完成...**永远。只要我改变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

dldeef67

dldeef671#

PostgreSQL相信如果只需要很少的行,那么以id顺序扫描markers并连接locations行直到找到足够的结果是一个可行的策略。显然优化器在这个假设上是错误的。
我不知道如何改进优化器的估计,但是您可以强制PostgreSQL避免缓慢的查询计划,方法是将ORDER BY条件改为

ORDER BY m.id + 0

因此PostgreSQL无法使用索引扫描来支持它。PostgreSQL只能在*some_expression*上存在索引时使用ORDER BY *some_expression*索引。

相关问题