Json 具有整数时间戳的数据的理想 Postgres 索引
Ideal Postgres Index For Json Data With Integer Timestamp
我使用 Amazon Aurora Postgres 10.7 在 table 中有数百万条记录:
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, "data": "my stuff"}
我有这些需要几十秒的查询:
SELECT jsonData->'data'
WHERE (jsonData->>'ts' >= '1576000473')
ORDER BY jsonData->>'ts' ASC LIMIT 100 OFFSET 50000;
我在这里尝试提高性能,这些都是我尝试过的索引,但我最多在查询计划中得到一个 INDEX SCAN。
create index "sometable_ts"
on "somedb"."sometable" ((jsondata -> 'ts'::text));
create index "sometable_ts-int"
on "somedb"."sometable" using btree (((jsondata ->> 'ts')::integer));
我也将查询调整为:ORDER BY (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
任何人都可以推荐一种方法来调整索引或查询以使它们变得更快吗?谢谢!
Using OFFSET
like this will always cause bad performance.
您应该使用键集分页:
创建这个索引:
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;
记住您在 last_ts
和 last_id
.
中得到的最后一行结果中的 jsonData->>'ts'
和 id
您的下一页是
SELECT jsonData->'data'
FROM somedb.sometable
WHERE (jsonData->>'ts', id) > (last_ts, last_id)
ORDER BY jsonData->>'ts', id
LIMIT 100;
继续这样下去,检索第 500 页将与检索第 1 页一样快。
我使用 Amazon Aurora Postgres 10.7 在 table 中有数百万条记录:
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, "data": "my stuff"}
我有这些需要几十秒的查询:
SELECT jsonData->'data'
WHERE (jsonData->>'ts' >= '1576000473')
ORDER BY jsonData->>'ts' ASC LIMIT 100 OFFSET 50000;
我在这里尝试提高性能,这些都是我尝试过的索引,但我最多在查询计划中得到一个 INDEX SCAN。
create index "sometable_ts"
on "somedb"."sometable" ((jsondata -> 'ts'::text));
create index "sometable_ts-int"
on "somedb"."sometable" using btree (((jsondata ->> 'ts')::integer));
我也将查询调整为:ORDER BY (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
任何人都可以推荐一种方法来调整索引或查询以使它们变得更快吗?谢谢!
Using OFFSET
like this will always cause bad performance.
您应该使用键集分页:
创建这个索引:
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;
记住您在 last_ts
和 last_id
.
jsonData->>'ts'
和 id
您的下一页是
SELECT jsonData->'data'
FROM somedb.sometable
WHERE (jsonData->>'ts', id) > (last_ts, last_id)
ORDER BY jsonData->>'ts', id
LIMIT 100;
继续这样下去,检索第 500 页将与检索第 1 页一样快。