Следует ли Postgres COPY FROM обновлять индекс BRIN? - PullRequest
0 голосов
/ 29 мая 2020

Представьте себе таблицу вроде ...

create table study_value (
    id serial primary key,
    study_id int not null references study (id),
    category text not null,
    subcategory int not null,
    p_value double precision not null
);

Я знал, что в ней будет 25+ миллионов строк, и они должны быть быстро запрошены родительским исследованием, а также, необязательно, по категории и подкатегории, поэтому я решил добавить к нему BRIN.

create index study_value_idx
    on study_value using brin (study_id, category, subcategory);

Все данные для данного исследования (1 миллион + строк) были вставлены в массовом порядке (упорядочены по категориям / подкатегориям) из буфера через ...

    copy study_value from stdin with (format csv, header false);

Данные этого исследования были загружены последовательно в порядке идентификаторов исследования, поэтому порядок вставки полностью соответствовал порядку столбцов BRIN.

Проблема, с которой я сталкиваюсь, заключается в том, что запрашивает эту таблицу при условиях, которым удовлетворяет BRIN, например. select count(*) from study_value where study_id = 3;, выполняет полное сканирование и занимает более 30 секунд. Размер самого BRIN составляет 48 кб.

Однако если я reindex index study_value_idx, запросы теперь занимают ~ 100 мс, а размер индекса превышает 100 кб.

Все, что я читал (в документации PG, на SO, et c.) указывает, что нужно только переиндексировать в очень специфических c ситуациях (например, повреждение данных или невозможность построения индексов).

Мне не нужно было отбрасывать индекс перед загрузкой данных и заново создавать его после этого, потому что копирование 1 миллиона записей в таблицу заняло всего 10 секунд.

Я что-то делаю не так? Есть ли лучший способ сделать это?

Изменить:

Я забыл упомянуть, что до запуска reindex я запускал analyze study_value и не видел изменений.

1 Ответ

0 голосов
/ 29 мая 2020

Ага, моя ошибка. Мне нужно было VACUUM ANALYZE на комментарий @ a_horse_with_no_name.

Я заново создал таблицу и повторно импортировал данные. При загрузке fre sh размер индекса снова составляет 48 КБ, а запрос возвращается к ~ 30 секундам. Я неправильно прочитал план запроса - он действительно использует индекс, фактические строки сильно отличаются от ожидаемых.

Aggregate  (cost=231550.86..231550.87 rows=1 width=8) (actual time=32233.141..32233.156 rows=1 loops=1)
->  Bitmap Heap Scan on study_value  (cost=6226.26..229546.26 rows=801840 width=0) (actual time=6555.954..27253.035 rows=781580 loops=1)
     Recheck Cond: (study_id = 920)
     Rows Removed by Index Recheck: 22027434
     Heap Blocks: lossy=213169
     ->  Bitmap Index Scan on study_value_idx  (cost=0.00..6025.80 rows=801840 width=0) (actual time=16.345..16.352 rows=2132480 loops=1)
           Index Cond: (study_id = 920)
Planning time: 0.941 ms
Execution time: 32233.266 ms

После analyze study_value (3 se c) idx по-прежнему составляет 48 КБ, а план запроса:

Aggregate  (cost=231360.49..231360.50 rows=1 width=8) (actual time=25468.247..25468.259 rows=1 loops=1)
->  Bitmap Heap Scan on study_value  (cost=6161.41..229376.81 rows=793472 width=0) (actual time=2740.866..20419.470 rows=781580 loops=1)
     Recheck Cond: (study_id = 920)
     Rows Removed by Index Recheck: 22027434
     Heap Blocks: lossy=213169
     ->  Bitmap Index Scan on study_value_idx  (cost=0.00..5963.04 rows=793472 width=0) (actual time=17.301..17.306 rows=2132480 loops=1)
           Index Cond: (study_id = 920)
Planning time: 0.101 ms
Execution time: 25468.389 ms

После vacuum analyze study_value (20 se c) теперь idx составляет 112 КБ, а план запроса - ..

Aggregate  (cost=231496.34..231496.35 rows=1 width=8) (actual time=10038.873..10038.884 rows=1 loops=1)
->  Bitmap Heap Scan on study_value  (cost=6228.78..229501.25 rows=798037 width=0) (actual time=12.303..5133.281 rows=781580 loops=1)
     Recheck Cond: (study_id = 920)
     Rows Removed by Index Recheck: 17962
     Heap Blocks: lossy=7473
     ->  Bitmap Index Scan on study_value_idx  (cost=0.00..6029.27 rows=798037 width=0) (actual time=1.644..1.650 rows=75520 loops=1)
           Index Cond: (study_id = 920)
Planning time: 0.511 ms
Execution time: 10038.993 ms

Выполнение более подробного запроса (ie. Включая категорию / подкатегорию) выполняется намного быстрее, возможно, ~ 400 мс.

...