È meglio creare un indice prima di riempire una tabella con i dati o dopo che i dati sono a posto?


92

Ho una tabella di circa 100 milioni di righe che copierò per modificarla, aggiungendo un indice. Non sono così preoccupato per il tempo necessario per creare la nuova tabella, ma l'indice creato sarà più efficiente se modifico la tabella prima di inserire dati o inserisco prima i dati e poi aggiungo l'indice?

Risposte:


117

La creazione dell'indice dopo l'inserimento dei dati è un modo più efficiente (spesso si consiglia anche di eliminare l'indice prima dell'importazione batch e dopo l'importazione ricrearlo).

Esempio sintetico (PostgreSQL 9.1, macchina a sviluppo lento, un milione di righe):

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

Inserisci e quindi crea indice - circa 12 sec

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

Crea indice e poi inserisci - circa 25,5 secondi (più di due volte più lento)


5
+1, gli indici rallenteranno notevolmente un'operazione che coinvolge un'attività di inserimento di righe da 100 milioni, quindi è meglio rilasciarli e ricrearli.
code4life

11

Probabilmente è meglio creare l'indice dopo che le righe sono state aggiunte. Non solo sarà più veloce, ma probabilmente il bilanciamento dell'albero sarà migliore.

Modifica "bilanciamento" probabilmente non è la migliore scelta di termini qui. Nel caso di un b-tree, è bilanciato per definizione. Ma questo non significa che il b-tree abbia il layout ottimale. La distribuzione dei nodi figlio all'interno dei genitori può essere irregolare (portando a un costo maggiore negli aggiornamenti futuri) e la profondità dell'albero può finire per essere più profonda del necessario se il bilanciamento non viene eseguito con attenzione durante gli aggiornamenti. Se l'indice viene creato dopo che le righe sono state aggiunte, è più probabile che avrà una distribuzione migliore. Inoltre, le pagine dell'indice sul disco potrebbero avere una minore frammentazione dopo la creazione dell'indice. Qualche informazione in più qui


2

Questo non ha importanza su questo problema perché:

  1. Se aggiungi prima i dati alla tabella e dopo aggiungi index. Il tempo di generazione dell'indice sarà O(n*log(N))più lungo (dove nviene aggiunta una riga). Perché il tempo di creazione degli alberi è O(N*log(N))quindi se lo dividi in vecchi dati e nuovi dati che ottieni O((X+n)*log(N))possono essere semplicemente convertiti O(X*log(N) + n*log(N))e in questo formato puoi semplicemente vedere cosa aspetterai in più.
  2. Se aggiungi index e dopo metti data. Ogni riga (hai nnuove righe) ottieni più tempo inserire ulteriore tempo O(log(N))necessario per rigenerare la struttura dell'albero dopo aver aggiunto un nuovo elemento (colonna dell'indice dalla nuova riga, perché l'indice esiste già ed è stata aggiunta una nuova riga, quindi l'indice deve essere rigenerato in bilanciato struttura, questo costo O(log(P))dove Pè un indice di potenza [elementi in indice] ). Hai nnuove righe poi finalmente si ha n * O(log(N))poi O(n*log(N))riassunto tempo supplementare.

1

Gli indici creati dopo sono molto più veloci nella maggior parte dei casi. Caso in questione: 20 milioni di righe con testo completo su varchar (255) - Indice (nome azienda) in posizione durante l'importazione di righe - una corrispondenza contro impiegare fino a 20 secondi nel peggiore dei casi. Rilascia l'indice e ricrea: abbina con meno di 1 secondo ogni volta


-2

Non sono sicuro che sarà davvero importante per il bene dell'efficienza dell'indice, poiché in entrambi i casi stai inserendo nuovi dati nell'indice. Il server non saprebbe quanto sarebbe sbilanciato un indice fino a dopo la sua creazione, in pratica. Per quanto riguarda la velocità, ovviamente, fai gli inserti senza l'indice.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.