use*_*521 5 postgresql limits offset-fetch postgresql-9.4
表jtest
有 200k 行,每行包含 jsonb { id: "<uuid>", key: <index> }
(<index>
每行递增 1-200k 的整数)。上还有btree索引data->'key'
。
create extension if not exists pgcrypto;
create table jtest (data jsonb not null default '{}');
insert into jtest (data)
select json_build_object('id', gen_random_uuid(), 'key', i)::jsonb
FROM generate_series(1,200000) i;
create index jtest_key on jtest ((data->'key'));
Run Code Online (Sandbox Code Playgroud)
第一个查询(快速):
EXPLAIN ANALYZE
select j.data
from jtest j
order by j.data->'key'
limit 20;
-- "Limit (cost=0.42..1.43 rows=20 width=74) (actual time=0.023..0.044 rows=20 loops=1)"
-- " -> Index Scan using jtest_key on jtest j (cost=0.42..10150.42 rows=200000 width=74) (actual time=0.023..0.039 rows=20 loops=1)"
-- "Planning time: 0.082 ms"
-- "Execution time: 0.066 ms"
Run Code Online (Sandbox Code Playgroud)
第二个具有大偏移量的查询(慢):
EXPLAIN ANALYZE
select j.data
from jtest j
order by j.data->'key'
offset 100000
limit 20;
-- "Limit (cost=5075.42..5076.44 rows=20 width=74) (actual time=112.861..112.896 rows=20 loops=1)"
-- " -> Index Scan using jtest_key on jtest j (cost=0.42..10150.42 rows=200000 width=74) (actual time=0.027..106.378 rows=100020 loops=1)"
-- "Planning time: 0.105 ms"
-- "Execution time: 112.931 ms"
Run Code Online (Sandbox Code Playgroud)
在 PG 文档中我发现:
OFFSET 子句跳过的行仍然必须在服务器内部计算;因此,大的 OFFSET 可能效率低下。
但他们没有说明如何处理大偏移量。我如何改进这个查询?这种行为(大偏移量效率低下)对于所有 RDMS 还是只是 PG(使用 9.4)都很常见?
小智 0
为什么不尝试使用 where 子句呢?如果你索引j.data->'key'
, awhere
将只是一个 log(n) 。
另一个原因可能order by j.data->'key'
是计算速度慢。对此进行索引也可以提高您的订单量(但其好处远不如 where 子句本身带来的好处那么明显)。
本文可能有助于更好地回答您的问题: https ://use-the-index-luke.com/sql/partial-results/fetch-next-page
归档时间: |
|
查看次数: |
8164 次 |
最近记录: |