Что лучше создать индекс перед заполнением таблицы данными или после того, как данные будут на месте?

87

У меня есть таблица из примерно 100 миллионов строк, которую я собираюсь скопировать, чтобы изменить, добавив индекс. Меня не слишком беспокоит время, необходимое для создания новой таблицы, но будет ли созданный индекс более эффективным, если я изменю таблицу перед вставкой каких-либо данных или сначала вставлю данные, а затем добавлю индекс?

Дрю Стивенс
источник

Ответы:

113

Создание индекса после вставки данных является более эффективным способом (даже часто рекомендуется удалить индекс перед пакетным импортом и после импорта воссоздать его).

Пример Syntetic (PostgreSQL 9.1, машина для медленной разработки, миллион строк):

CREATE TABLE test1(id serial, x integer);
INSERT INTO test1(id, x) SELECT x.id, x.id*100 FROM generate_series(1,1000000) AS x(id);
-- Time: 7816.561 ms
CREATE INDEX test1_x ON test1 (x);
-- Time: 4183.614 ms

Вставить, а затем создать индекс - около 12 секунд

CREATE TABLE test2(id serial, x integer);
CREATE INDEX test2_x ON test2 (x);
-- Time: 2.315 ms
INSERT INTO test2(id, x) SELECT x.id, x.id*100 FROM generate_series(1,1000000) AS x(id);
-- Time: 25399.460 ms

Создайте индекс, а затем вставьте - около 25,5 секунд (более чем в два раза медленнее)

Володзка
источник
5
+1, индексы заметно замедлят операцию, включающую задачу вставки 100 миллионов строк, поэтому лучше отбросить их и создать заново.
code4life
10

Вероятно, лучше создать индекс после добавления строк. Мало того, что это будет быстрее, но и балансировка деревьев, вероятно, будет лучше.

Править "балансировка", вероятно, здесь не лучший выбор терминов. В случае b-дерева оно сбалансировано по определению. Но это не означает, что b-дерево имеет оптимальную компоновку. Распределение дочерних узлов внутри родителей может быть неравномерным (что приведет к увеличению затрат в будущих обновлениях), а глубина дерева может оказаться глубже, чем это необходимо, если балансировка не выполняется тщательно во время обновлений. Если индекс создается после добавления строк, он, скорее всего, будет лучше распределен. Кроме того, после создания индекса страницы индекса на диске могут иметь меньшую фрагментацию. Немного больше информации здесь

Марк Уилкинс
источник
2

Это не имеет значения для данной проблемы, потому что:

  1. Если вы сначала добавляете данные в таблицу, а потом добавляете index. Время создания индекса будет O(n*log(N))больше (там, где nдобавлены строки). Поскольку время создания дерева - это O(N*log(N))тогда, если вы разделите его на старые данные и новые данные, которые вы получите, O((X+n)*log(N))их можно просто преобразовать в, O(X*log(N) + n*log(N))и в этом формате вы можете просто увидеть, что вы будете ждать дополнительно.
  2. Если вы добавляете index и после него помещаете data. Каждую строку (у вас есть nновые строки) вы получаете больше, вставляйте дополнительное время, O(log(N))необходимое для восстановления структуры дерева после добавления в него нового элемента (столбец индекса из новой строки, поскольку индекс уже существует и была добавлена ​​новая строка, тогда индекс должен быть регенерирован для сбалансированного структура, эта стоимость, O(log(P))где P- степень индекса [элементы в индексе] ). У вас есть nновые строки , а затем , наконец , у вас есть n * O(log(N))то O(n*log(N))сводное дополнительное время.
Svisstack
источник
1

Индексы, созданные после этого, в большинстве случаев выполняются намного быстрее. Показательный пример: 20 миллионов строк с полным текстом в varchar (255) - (Business Name) Index на месте при импорте строк - сопоставление с тем, что в худшем случае занимает до 20 секунд. Отбросить индекс и воссоздать - сопоставить, не занимая менее 1 секунды каждый раз

Майк Кросс
источник
-2

Я не уверен, что это действительно имеет значение для эффективности индекса, поскольку в обоих случаях вы вставляете в индекс новые данные. В принципе, сервер не будет знать, насколько несбалансированным будет индекс, пока он не будет построен. По скорости, очевидно, вставки без индекса.

ГрандмастерB
источник