Идеальный Postgres индекс для Json данных с целочисленной временной меткой - PullRequest
0 голосов
/ 10 февраля 2020

У меня есть миллионы записей в этой таблице с использованием 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, "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

Может кто-нибудь порекомендовать способ корректировки индексов или запросы, чтобы они стали быстрее? Спасибо!

1 Ответ

1 голос
/ 10 февраля 2020

Использование OFFSET как это будет всегда вызывать плохую производительность .

Вы должны использовать нумерацию клавиш набора:

Создайте этот индекс:

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_ts и last_id.

Ваша следующая страница найдена с

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

Продолжайте так, и получение 500-й страницы будет таким же быстрым, как и получение первой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...