É melhor criar um índice antes de preencher uma tabela com dados ou depois que os dados estiverem no lugar?

87

Tenho uma tabela de cerca de 100 milhões de linhas que vou copiar para alterar, adicionando um índice. Não estou tão preocupado com o tempo que leva para criar a nova tabela, mas o índice criado será mais eficiente se eu alterar a tabela antes de inserir quaisquer dados ou inserir os dados primeiro e depois adicionar o índice?

Drew Stephens
fonte

Respostas:

113

A criação de índice após a inserção de dados é a maneira mais eficiente (até frequentemente recomendado descartar o índice antes da importação em lote e, após a importação, recriá-lo).

Exemplo sintético (PostgreSQL 9.1, máquina de desenvolvimento lento, um milhão de linhas):

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

Insira e crie o índice - cerca de 12 segundos

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

Crie o índice e insira - cerca de 25,5 segundos (mais de duas vezes mais lento)

Valodzka
fonte
5
+1, os índices irão desacelerar significativamente uma operação envolvendo tarefa de inserção de 100 milhões de linhas, então é melhor eliminá-los e recriá-los.
code4life
10

Provavelmente, é melhor criar o índice depois que as linhas forem adicionadas. Não só será mais rápido, mas o equilíbrio da árvore provavelmente será melhor.

Editar "balanceamento" provavelmente não é a melhor escolha de termos aqui. No caso de uma árvore b, ela é balanceada por definição. Mas isso não significa que a árvore b tenha o layout ideal. A distribuição do nó filho dentro dos pais pode ser desigual (levando a mais custos em atualizações futuras) e a profundidade da árvore pode acabar sendo mais profunda do que o necessário se o balanceamento não for executado com cuidado durante as atualizações. Se o índice for criado após a adição das linhas, é mais provável que tenha uma distribuição melhor. Além disso, as páginas de índice no disco podem ter menos fragmentação após a criação do índice. Um pouco mais de informação aqui

Mark Wilkins
fonte
2

Isso não importa neste problema porque:

  1. Se você adicionar dados primeiro à tabela e depois disso, você adiciona o índice. Seu tempo de geração de índice será O(n*log(N))maior (onde nsão adicionadas linhas). Porque o tempo de geração da árvore é O(N*log(N))então, se você dividir isso em dados antigos e novos dados, você O((X+n)*log(N))pode simplesmente converter para O(X*log(N) + n*log(N))e neste formato, você pode simplesmente ver o que você vai esperar adicional.
  2. Se você adicionar índice e depois colocar dados. Cada linha (você tem nnovas linhas) você obtém mais tempo O(log(N))para inserir o tempo adicional necessário para regenerar a estrutura da árvore após adicionar um novo elemento nela (coluna de índice da nova linha, porque o índice já existe e uma nova linha foi adicionada, então o índice deve ser regenerado para balanceado estrutura, este custo O(log(P))onde Pé uma potência de índice [elementos no índice] ). Você tem nnovas linhas, em seguida, finalmente, você tem n * O(log(N))então O(n*log(N))resumo tempo adicional.
Svisstack
fonte
1

Os índices criados depois são muito mais rápidos na maioria dos casos. Caso em questão: 20 milhões de linhas com texto completo em varchar (255) - (Nome da empresa) Índice em vigor durante a importação de linhas - uma correspondência contra levar até 20 segundos nos piores casos. Abandone o índice e recrie - compara levando menos de 1 segundo a cada vez

Mike Cross
fonte
-2

Não tenho certeza se isso realmente importará para a eficiência do índice, pois em ambos os casos você está inserindo novos dados no índice. O servidor não saberia o quão desequilibrado um índice estaria até depois de sua construção, basicamente. Em termos de velocidade, obviamente, faça as inserções sem o índice.

Grande Mestre B
fonte