Quanti indici di database sono troppi?


109

Sto lavorando a un progetto con un database Oracle piuttosto grande (anche se la mia domanda si applica ugualmente bene ad altri database). Abbiamo un'interfaccia web che consente agli utenti di cercare in quasi tutte le possibili combinazioni di campi.

Per velocizzare queste ricerche, stiamo aggiungendo indici ai campi e combinazioni di campi in cui crediamo che gli utenti effettueranno comunemente ricerche. Tuttavia, poiché non sappiamo realmente come i nostri clienti utilizzeranno questo software, è difficile stabilire quali indici creare.

Lo spazio non è un problema; abbiamo un drive RAID da 4 terabyte di cui stiamo usando solo una piccola parte. Tuttavia, sono preoccupato per le possibili penalizzazioni sulle prestazioni derivanti dall'avere troppi indici. Poiché questi indici devono essere aggiornati ogni volta che una riga viene aggiunta, eliminata o modificata, immagino che sarebbe una cattiva idea avere dozzine di indici su una singola tabella.

Quindi quanti indici sono considerati troppi? 10? 25? 50? O dovrei solo coprire i casi davvero, davvero comuni e ovvi e ignorare tutto il resto?

Risposte:


87

Dipende dalle operazioni che avvengono sul tavolo.

Se ci sono molti SELECT e pochissime modifiche, indicizza tutto ciò che ti piace ... questi accelereranno (potenzialmente) le istruzioni SELECT.

Se la tabella è pesantemente colpita da UPDATE, INSERT + DELETE ... questi saranno molto lenti con molti indici poiché devono essere tutti modificati ogni volta che viene eseguita una di queste operazioni

Detto questo, puoi chiaramente aggiungere molti indici inutili a una tabella che non farà nulla. L'aggiunta di indici B-Tree a una colonna con 2 valori distinti sarà inutile poiché non aggiunge nulla in termini di ricerca dei dati. Quanto più univoci sono i valori in una colonna, tanto più beneficerà di un indice.


1
Giusto per chiarire, l'indice su 2 valori potrebbe non essere inutile in casi specifici, quando un valore si verifica raramente e si desidera cercarlo. Quindi non si tratta di quanto siano unici i valori, ma di quanto sia selettivo l'indice.
charlie_pl

44

Di solito procedo in questo modo.

  1. Ottieni un registro del reale query eseguite sui dati in una giornata tipica.
  2. Aggiungi indici in modo che le query più importanti raggiungano gli indici nel loro piano di esecuzione.
  3. Cerca di evitare di indicizzare i campi che hanno molti aggiornamenti o inserimenti
  4. Dopo alcuni indici, ottieni un nuovo registro e ripeti.

Come per tutte le ottimizzazioni, mi fermo quando viene raggiunta la prestazione richiesta (questo ovviamente implica che il punto 0. sarebbe ottenere requisiti prestazionali specifici).


26

Tutti gli altri ti hanno dato ottimi consigli. Ho un suggerimento in più per te mentre vai avanti. Ad un certo punto devi prendere una decisione sulla migliore strategia di indicizzazione. Alla fine, però, la migliore strategia di indicizzazione PIANIFICATA può ancora finire per creare indici che non finiscono per essere utilizzati. Una strategia che ti consente di trovare gli indici che non vengono utilizzati è monitorare l'utilizzo degli indici. Puoi farlo come segue: -

alter index my_index_name monitoring usage;

È quindi possibile monitorare se l'indice viene utilizzato o meno da quel punto in avanti interrogando v $ object_usage. Informazioni in merito sono disponibili nella Guida dell'amministratore del database Oracle® .

Ricorda solo che se hai una strategia di magazzino che prevede di eliminare gli indici prima di aggiornare una tabella, quindi di ricrearli, dovrai impostare nuovamente l'indice per il monitoraggio e perderai la cronologia di monitoraggio per quell'indice.


14

Nel data warehousing è molto comune avere un numero elevato di indici. Ho lavorato con tabelle dei fatti con duecento colonne e 190 di esse indicizzate.

Sebbene ci sia un sovraccarico in questo, deve essere compreso nel contesto che in un data warehouse generalmente inseriamo solo una riga una volta, non la aggiorniamo mai, ma può quindi partecipare a migliaia di query SELECT che potrebbero trarre vantaggio dall'indicizzazione su uno qualsiasi dei le colonne.

Per la massima flessibilità, un data warehouse generalmente utilizza indici bitmap a colonna singola tranne che su colonne ad alta cardinalità, dove è possibile utilizzare indici btree (compressi).

Il sovraccarico sulla manutenzione dell'indice è per lo più associato alla spesa di scrittura su un gran numero di blocchi e il blocco si divide quando vengono aggiunte nuove righe con valori che si trovano "nel mezzo" degli intervalli di valori esistenti per quella colonna. Questo può essere mitigato partizionando e avendo i nuovi caricamenti di dati allineati con lo schema di partizionamento e utilizzando inserimenti di percorso diretti.

Per rispondere alla tua domanda in modo più diretto, penso che all'inizio sia probabilmente corretto indicizzare l'ovvio, ma non aver paura di aggiungere altri indici se le query contro la tabella ne trarrebbero vantaggio.


Così tanti su un fatto? Avrei immaginato che stessi per dire dimensione. Questo è un caso d'uso piuttosto bizzarro. Ma sei un DBA, quindi dirò che ovviamente mi manca qualcosa.
Stephanie Page

@Stephanie, abbiamo più o meno lo stesso scenario .. David ha menzionato quelli sono indici bitmap. Usiamo anche indici BITMAP JOIN. Sì, sui fatti. Oracle può eseguire operazioni AND molto efficienti sugli indici bitmap. Ad esempio, potresti avere la clausola WHERE con 5 attributi a bassa cardinalità, ognuno dei quali ha un indice bitmap. Se guardi il piano di esecuzione, avrebbe una bitmap AND operazioni (fondamentalmente una bitmap e un'operazione efficienti), quindi nel piano di esecuzione vedrai la conversione bitmap in rowid. È davvero veloce.
Tagar

12

In una parafrasi di Einstein sulla semplicità, aggiungi tutti gli indici di cui hai bisogno e non di più.

Seriamente, tuttavia, ogni indice aggiunto richiede manutenzione ogni volta che i dati vengono aggiunti alla tabella. Nelle tabelle che sono principalmente di sola lettura, molti indici sono una buona cosa. Su tabelle altamente dinamiche, meno è meglio.

Il mio consiglio è di coprire i casi comuni e ovvi e quindi, quando si incontrano problemi in cui è necessaria più velocità nell'ottenere dati da tabelle specifiche, valutare e aggiungere indici a quel punto.

Inoltre, è una buona idea rivalutare i tuoi schemi di indicizzazione ogni pochi mesi, solo per vedere se c'è qualcosa di nuovo che necessita di indicizzazione o qualsiasi indice che hai creato che non viene utilizzato per nulla e dovrebbe essere eliminato .


1
Sono d'accordo sulla rivalutazione. Una buona amministrazione non è mai un compito "impostalo e dimenticalo". Modifiche al software. Cambiano i requisiti. Modifiche all'utilizzo. Una nuova funzionalità apparentemente banale introdotta un giorno potrebbe rapidamente diventare il tuo più grande collo di bottiglia e il codice fondamentale di ieri potrebbe diventare grasso dormiente e inutile che si limita a consumare risorse. Sono anche d'accordo con un approccio iterativo. Se fai troppo in una volta, non saprai cosa ha funzionato.
durette

6

Oltre ai punti sollevati da tutti gli altri, l'ottimizzatore basato sui costi sostiene un costo durante la creazione di un piano per un'istruzione SQL se ci sono più indici perché ci sono più combinazioni da considerare. È possibile ridurlo utilizzando correttamente le variabili di associazione in modo che le istruzioni SQL rimangano nella cache SQL. Oracle può quindi eseguire un'analisi soft e riutilizzare il piano trovato l'ultima volta.

Come sempre, niente è semplice. Se sono coinvolte colonne e istogrammi inclinati, questa può essere una cattiva idea.

Nelle nostre applicazioni web tendiamo a limitare le combinazioni di ricerche che consentiamo. Altrimenti dovresti testare letteralmente ogni combinazione per le prestazioni per assicurarti di non avere un problema in agguato che qualcuno troverà un giorno. Abbiamo anche implementato limiti di risorse per impedire che ciò causi problemi in altre parti dell'applicazione nel caso in cui qualcosa dovesse andare storto.


Ho votato a favore ma ... direi che il tempo di analisi extra, sebbene interessante e accademico, non influenzerebbe mai la mia scelta per il numero corretto di indici. essere d'accordo?
Stephanie Page

@StephaniePage Non ho fatto un esperimento per dimostrare nulla. Tuttavia ho visto un progetto che creava ingenuamente un indice a colonna singola su ogni colonna. Se alcune tabelle hanno 80 colonne, immagino che potrebbe iniziare ad avere un impatto. Oracle sembra considerare il costo di accesso per ogni indice. Ma sì, sono d'accordo, ci sono cose più importanti da considerare di questo.
WW.

Mmm ... credo che ci sia una quantità massima di tempo che Oracle impiegherà in un'analisi difficile ... considera un SQL con più di poche tabelle, diciamo 7 o 8, la scelta dell'ordine di join da sola potrebbe generare centinaia di possibili percorsi di accesso.
Stephanie Page

6

Ho fatto dei semplici test sul mio progetto reale e sul database MySql reale. Ho già risposto in questo argomento: Qual è il costo dell'indicizzazione di più colonne db?

Ma penso che sarebbe meglio se lo cito qui:

Ho fatto dei semplici test utilizzando il mio progetto reale e il database MySql reale.

I miei risultati sono: l'aggiunta di un indice medio (1-3 colonne in un indice) a una tabella - rallenta gli inserimenti del 2,1%. Quindi, se aggiungi 20 indici, i tuoi inserti saranno più lenti del 40-50%. Ma le tue selezioni saranno 10-100 volte più veloci.

Quindi va bene aggiungere molti indici? - Dipende :) Ti ho dato i miei risultati - Decidi tu!


Questo non dovrebbe essere preso come una profezia senza tutti i dettagli. Soprattutto perché non puoi moltiplicare il guadagno / la perdita di prestazioni da un'azione all'altra. La base rimane la stessa: aggiungi più indici e gli inserti alla fine saranno più lenti a causa della ricreazione dell'indice.
SovietFrontier

3

In definitiva, il numero di indici necessari dipende dal comportamento delle applicazioni che si trovano sul server del database.

In generale, più inserimenti fai, più dolorosi diventano i tuoi indici. Ogni volta che si esegue un inserimento, tutti gli indici che includono quella tabella devono essere aggiornati.

Ora, se la tua applicazione ha una discreta quantità di lettura, o anche di più se è quasi tutta in lettura, gli indici sono la strada da percorrere poiché ci saranno importanti miglioramenti delle prestazioni a un costo molto basso.


3

Non c'è una risposta statica secondo me, questo genere di cose rientra nella "messa a punto delle prestazioni".

Potrebbe essere che tutto ciò che fa la tua app venga cercato da una chiave primaria, oppure potrebbe essere l'opposto in quanto le query vengono eseguite su combinazioni di campi non riservate e ognuna in particolare potrebbe essere utilizzata in un dato momento.

Oltre alla semplice indicizzazione, c'è la riorganizzazione del database per includere campi di ricerca calcolati, tabelle di divisione, ecc. - Dipende davvero dalle forme di carico e dai parametri di query, dalla quantità / quale dati "realmente" devono essere ritirati da una query.

Se l'intero DB è fronteggiato da facciate a procedura memorizzata, la rotazione diventa un po 'più semplice, poiché non devi preoccuparti di ogni query ad-hoc. Oppure potresti avere una profonda conoscenza del tipo di query che raggiungeranno il tuo DB e puoi limitare la messa a punto a quelle.

Per SQL Server ho trovato utile l'advisor di ottimizzazione del motore di database: si impostano carichi di lavoro "tipici" e può fornire consigli sull'aggiunta / rimozione di indici e statistiche. Sono sicuro che altri DB hanno strumenti simili, "ufficiali" o di terze parti.


3

Questa è davvero una domanda più teorica che pratica. L'impatto degli indici sulle tue prestazioni dipende dall'hardware che hai, dalla versione di Oracle, dai tipi di indice, ecc. Ieri ho sentito Oracle ha annunciato uno storage dedicato, realizzato da HP, che dovrebbe funzionare 10 volte più velocemente con il database 11g. Per quanto riguarda il tuo caso, ci possono essere diverse soluzioni: 1. Avere una grande quantità di indici (> 20) e ricostruirli ogni giorno (ogni notte). Ciò sarebbe particolarmente utile se la tabella riceve migliaia di aggiornamenti / eliminazioni ogni giorno. 2. Partizionare la tabella (se si applica il modello di dati). 3. Utilizzare una tabella separata per i dati nuovi / aggiornati ed eseguire un processo notturno che combina i dati insieme. Ciò richiederebbe una modifica nella logica dell'applicazione. 4. Passa a IOT (tabella organizzata con indice), se i tuoi dati lo supportano.

Ovviamente potrebbero esserci molte altre soluzioni per questo caso. Il mio primo suggerimento per te sarebbe di clonare il DB in un ambiente di sviluppo ed eseguire alcuni stress test su di esso.


Non capisco come sarebbe utile ricostruire gli indici o come sarebbe utile un IOT.
David Aldridge,

IOT: se è possibile riprogettare l'applicazione, in modo che venga utilizzato un nuovo tipo di dati definito dall'utente, IOT salverà l'overhead relativo all'indicizzazione della tabella. questo potrebbe non essere il caso qui. dipende davvero. ricostruire l'indice - nel caso in cui ci siano molti indici e i nuovi dati non siano indicizzati.
Moshe

Un IOT è ancora una struttura di indice, con più overhead sulle suddivisioni dei blocchi rispetto a un indice normale. "ricostruire l'indice - nel caso ci siano molti indici e i nuovi dati non siano indicizzati" ... di quale RDBMS stai parlando che non mantiene automaticamente gli indici per le nuove voci?
David Aldridge,

David - hai ragione ovviamente. L'ho combinato con la capacità di SQL Server di indicizzare la ricerca full-text solo su richiesta. Vorrei che Oracle lo avesse, dal momento che potrebbe essere utile in questo caso. Consiglierei di attenermi agli altri due suggerimenti.
Moshe,

2

Se esegui principalmente letture (e pochi aggiornamenti), non c'è davvero alcun motivo per non indicizzare tutto ciò di cui avrai bisogno. Se aggiorni spesso, potresti dover essere cauto sul numero di indici che hai. Non esiste un numero fisso, ma noterai quando le cose iniziano a rallentare. Assicurati che il tuo indice cluster sia quello che ha più senso in base ai dati.


2

Una cosa che potresti considerare è la creazione di indici per scegliere come target una combinazione standard di ricerche. Se la ricerca nella colonna1 viene comunemente eseguita e la colonna2 viene spesso utilizzata con essa e la colonna3 viene talvolta utilizzata con la colonna2 e la colonna1, è possibile utilizzare un indice su colonna1, colonna2 e colonna3 in quell'ordine per ognuna di queste tre circostanze, sebbene lo sia solo un indice che deve essere mantenuto.


2

Un indice impone un costo quando la tabella sottostante viene aggiornata. Un indice fornisce un vantaggio quando viene utilizzato per accelerare una query. Per ogni indice, è necessario bilanciare il costo con il vantaggio. Quanto più lentamente viene eseguita la query senza l'indice? Quanto di un vantaggio sta funzionando più velocemente? Voi oi vostri utenti potete tollerare la bassa velocità quando manca l'indice?

Riesci a tollerare il tempo aggiuntivo necessario per completare un aggiornamento?

È necessario confrontare costi e benefici. È particolare per la tua situazione. Non esiste un numero magico di indici che superi la soglia di "troppi".

C'è anche il costo dello spazio necessario per memorizzare l'indice, ma hai detto che nella tua situazione non è un problema. Lo stesso vale nella maggior parte delle situazioni, dato quanto è diventato economico lo spazio su disco.


1

Quante colonne ci sono? Mi è sempre stato detto di creare indici a colonna singola, non indici a più colonne. Quindi non più indici della quantità di colonne, IMHO.


1

Ciò a cui si riduce davvero è non aggiungere un indice a meno che non si sappia (e questo spesso significa raccogliere statistiche sull'utilizzo) che verrà utilizzato molto più spesso di quanto non venga aggiornato.

Qualsiasi indice che non soddisfa tali criteri ti costerà di più per la ricostruzione rispetto alla penalizzazione delle prestazioni di non averlo nel caso dispari è stato utilizzato.


1

Il server SQL ti offre alcuni buoni strumenti che ti consentono di vedere quali indici vengono effettivamente utilizzati. Questo articolo, http://www.mssqltips.com/tip.asp?tip=1239 , fornisce alcune query che consentono di ottenere una visione migliore di quanto viene utilizzato un indice anziché di quanto viene aggiornato.


0

È totalmente basato sulle colonne che vengono utilizzate in Where Clause. E come Thumb of Rule, dobbiamo avere indici sulle colonne di chiavi esterne per evitare DEADLOCK. Il rapporto AWR dovrebbe analizzare periodicamente per comprendere la necessità degli indici.


2
Indici su colonne di chiavi esterne per evitare deadlock? Hai un riferimento che spieghi perché e come questo è il caso?
Jay Sullivan
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.