Разное время создания индекса в PostgreSQL для одного и того же типа данных - PullRequest
0 голосов
/ 03 января 2019

У меня есть таблица с тремя столбцами A, B, C, все типа bytea.В таблице около 180 000 000 строк.A, B и C имеют ровно 20 байтов данных, C иногда содержит NULL

. При создании индексов для всех столбцов с

CREATE INDEX index_A ON transactions USING hash (A);
CREATE INDEX index_B ON transactions USING hash (B);
CREATE INDEX index_C ON transactions USING hash (C);

index_A создается примерно за 10 минут, а B иC берут более 10 часов, после чего я их прервал.Я запускал каждый CREATE INDEX самостоятельно, поэтому никакие индексы не создавались параллельно.В базе данных также нет других запросов.При запуске

SELECT * FROM pg_stat_activity;

wait_event_type и wait_event оба имеют значение NULL, state - active .

Почему создание второго индекса занимает так много времени,и я могу сделать что-нибудь, чтобы ускорить их?

1 Ответ

0 голосов
/ 03 января 2019

Убедитесь, что статистика в вашей таблице обновлена.
Затем выполните следующий запрос:

SELECT attname, n_distinct, correlation
from pg_stats
where tablename = '<Your table name here>'

По сути, в базе данных будет больше работы для создания индексов, когда:

  • Количество различных значений увеличивается.
  • Корреляция (= значения в поле физически сохраняются в порядке) близка к 0.

Я подозреваю, что вы увидите, что поле A отличается с точки зрения различных значений и / или более высокой корреляции , чем другие 2 поля.

Edit :В основном, создание индекса = FULL SCAN таблицы и создание записей в индексе по мере продвижения.С приведенной ниже статистикой это означает:

  • Столбец A: он был обнаружен как уникальный
    Достаточно одного сканирования, поскольку БД знает 1 запись = 1 запись индекса.
  • Столбцы B & C: было обнаружено, что оно имеет очень мало различных значений + abs(correlation) очень мало.
    Каждая запись индекса занимает целую FULL SCAN таблицы.

Примечание: описание упрощено, чтобы выделить разницу.


Решение 1 :
Не создавать индексы для B и C.
Itможет показаться глупым, но на самом деле и, как объяснено здесь , небольшая корреляция означает, что индексы, вероятно, не будут использоваться (индекс полезен, только если записи не разбросаны по всем блокам таблицы).


Решение 2 :
Упорядочить записи на диске.
Инициализация будет выглядеть примерно так:

CREATE TABLE Transactions_order as SELECT * FROM Transactions;
TRUNCATE TABLE Transactions;
INSERT INTO Transactions SELECT * FROM Transactions_order ORDER BY B,C,A;
DROP TABLE Transactions_order;

Сложная задача:вставлять / обновлять / удалять записи, вам нужно отслеживать корреляцию ипока он не падает слишком сильно.
Если вы не можете этого гарантировать, придерживайтесь решения 1.


Solution3 : создайте разделов инаслаждайтесь сокращением разделов.
В последнее время в postgresql делается много усилий для разделения разделов.Возможно, стоит взглянуть на это.

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