Sql 具有整数时间戳的Json数据的理想Postgres索引

Sql 具有整数时间戳的Json数据的理想Postgres索引,sql,postgresql,sql-execution-plan,query-planner,Sql,Postgresql,Sql Execution Plan,Query Planner,我使用Amazon Aurora Postgres 10.7在该表中记录了数百万条记录: create table "somedb"."sometable" ( id varchar(4096) not null constraint "sometable_pkey" primary key, tag varchar(255) not null, json jsonb not null ); 示例行: {“id”:“abc”,“ts”:1580879910,“数据”:“

我使用Amazon Aurora Postgres 10.7在该表中记录了数百万条记录:

create table "somedb"."sometable"
(
    id varchar(4096) not null constraint "sometable_pkey" primary key,
    tag varchar(255) not null,
    json jsonb not null
);
示例行:

{“id”:“abc”,“ts”:1580879910,“数据”:“我的东西”}

我的这些查询需要几十秒钟:

SELECT jsonData->'data'
WHERE (jsonData->>'ts' >= '1576000473')
ORDER BY jsonData->>'ts' ASC LIMIT 100 OFFSET 50000;
我试图在这里提高性能,这些都是我尝试过的索引,但最多只能在查询计划中进行索引扫描

create index "sometable_ts"
on "somedb"."sometable" ((jsondata -> 'ts'::text));

create index "sometable_ts-int" 
on "somedb"."sometable" using btree (((jsondata ->> 'ts')::integer));
我还将查询调整为:
orderby(jsonData->'ts')::integer
,但没有

最佳计划:

Limit  (cost=613080.18..613149.46 rows=100 width=356) (actual time=24934.492..24937.344 rows=100 loops=1)
    ->  Index Scan using "sometable_ts-int" on "sometable"  (cost=0.43..3891408.61 rows=5616736 width=356) (actual time=0.068..24889.459 rows=885000 loops=1)
        Index Cond: (((jsondata ->> 'ts'::text))::integer >= 1576000473)
Planning time: 0.145 ms
Execution time: 24937.381 ms
有人能推荐一种方法来调整索引或查询以使其更快吗?谢谢

像这样

您应该使用键集分页:

创建此索引:

CREATE INDEX ON somedb.sometable (id, (jsonData->>'ts'));
然后,要分页,您的第一个查询是:

SELECT jsonData->'data'
FROM somedb.sometable
WHERE jsonData->>'ts' >= '1576000473'
ORDER BY jsonData->>'ts', id
LIMIT 100;
请记住
jsonData->'ts'
id
来自您在
last\u ts
last\u id
中获得的最后一个结果行

您的下一页将在中找到

SELECT jsonData->'data'
FROM somedb.sometable
WHERE (jsonData->>'ts', id) > (last_ts, last_id)
ORDER BY jsonData->>'ts', id
LIMIT 100;

继续这样做,检索第500页的速度将与检索第一页的速度一样快。

@jarlh该站点非常棒,但我之所以要问,是因为这是JSON,从我的尝试来看,典型的索引技术对我不起作用。@jarlh你的意思是,对吗?@LaurenzAlbe,没错!顺便说一下,
varchar(4096)
对于主键列来说是一个糟糕的选择。很长的值将使索引失败。我的ID不是单调递增的。它们是UUID。我想我可以创建一个列。这是无关的。重要的是它们是独一无二的。那么这部分是如何工作的呢<代码>>(最后一个,最后一个id)好的,谢谢。其思想是,该解决方案使用行值语法/比较,谢天谢地,这在Postgres中完全可用,但其他数据库很少。请注意将来阅读此解决方案的人。