2010-09-10 1 views

risposta

70

Creazione dell'indice dopo l'inserimento dei dati è un modo più efficiente (spesso consigliato anche per rilasciare l'indice prima dell'importazione batch e dopo l'importazione per ricrearlo).

esempio

sintetico (PostgreSQL 9.1, macchina lenta di sviluppo, 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 creare l'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 quindi inserire - circa 25.5 sec (più di due volte più lento)

+3

+1, gli indici rallenteranno notevolmente un'operazione che coinvolge l'attività di inserimento di righe di 100M, quindi meglio lasciarli e ricrearli. – code4life

7

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

Modifica "bilanciamento" probabilmente non è la scelta migliore di termini qui. Nel caso di un albero b, è equilibrato per definizione. Ma ciò non significa che il b-tree abbia il layout ottimale. La distribuzione del nodo figlio all'interno dei genitori può essere irregolare (il che comporta maggiori costi negli aggiornamenti futuri) e la profondità dell'albero può risultare più profonda del necessario se il bilanciamento non viene eseguito con attenzione durante gli aggiornamenti. Se l'indice viene creato dopo l'aggiunta delle righe, è più probabile che abbia una distribuzione migliore. Inoltre, le pagine indice sul disco potrebbero presentare una minore frammentazione dopo la creazione dell'indice. A bit more information here

1

Non importa su questo problema perché:

  1. Se si aggiungono prima i dati alla tabella e dopo si aggiunge l'indice. Il tempo di generazione dell'indice sarà O(n*log(N)) più lungo (dove n è una riga aggiunta). Poiché il tempo di gerarchia degli alberi è O(N*log(N)), se dividi questo in dati vecchi e nuovi dati ottieni O((X+n)*log(N)), questo può essere semplicemente convertito in O(X*log(N) + n*log(N)) e in questo formato puoi semplicemente vedere che cosa attendi.
  2. Se si aggiunge indice e dopo aver inserito i dati. Ogni riga (hai n nuove righe) si allunga il tempo addizionale 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à e la nuova riga è stata aggiunta, quindi l'indice deve essere rigenerato a struttura equilibrata, questo costo O(log(P)) dove P è un indice di potenza [elementi nell'indice]). Hai n nuove righe e infine hai n * O(log(N)) quindi il tempo di sintesi aggiuntivo O(n*log(N)).
-1

Non sono sicuro che sarà davvero importante per l'efficienza dell'indice, poiché in entrambi i casi si stanno inserendo nuovi dati nell'indice. Il server non saprebbe come un indice sarebbe sbilanciato fino a dopo la sua costruzione, in pratica. Sinceramente, ovviamente, fai gli inserti senza l'indice.

0

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) - (Nome commerciale) Indice in vigore durante l'importazione di righe: una corrispondenza contro l'assunzione di fino a 20 secondi nei casi peggiori. Rilasciare e ricreare - abbinare meno di 1 secondo ogni volta