È l'ottimizzazione prematura per aggiungere indici di database?


61

Un mio collega oggi ha suggerito di passare attraverso tutte le query nella nostra applicazione e di aggiungere gli indici di conseguenza.

Ritengo sia un'ottimizzazione prematura perché la nostra applicazione non è stata ancora rilasciata. Ho suggerito di monitorare le query lente una volta che siamo online e quindi aggiungere gli indici di conseguenza.

Qual è il consenso generale durante la progettazione del database, è necessario aggiungere un indice corrispondente ogni volta che si scrive una nuova query? O è meglio semplicemente monitorare e vedere come va?


32
Potrebbe essere una questione di opinione, tuttavia ritengo che alcuni indici potrebbero essere aggiunti a priori.
Basile Starynkevitch,

2
@BasileStarynkevitch Sono assolutamente d'accordo sul fatto che abbiamo già indici chiave primari e le opere. Ma dove hai disegnato la linea?
Marco de Jongh,

1
I miei due centesimi per esperienza: stavo testando alcune delle mie prime ricerche su un sottoinsieme del nostro database. I test che ho eseguito andavano benissimo sulla mia copia locale. Ho quindi trasferito l'applicazione nell'area di gestione temporanea che ospita il database completo. I miei test sono stati eseguiti in <500 ms , mentre il sistema di gestione temporanea ha richiesto diversi minuti per risolversi. Il mio capo era completamente confuso sul motivo per cui l'app non si stava caricando. Spiega le operazioni di tipo sono i tuoi amici ... Almeno cerca scansioni sequenziali su tavoli di grandi dimensioni, almeno!
Chris Cirefice,

2
Non aggiungere indici è come usare bubblesort. Molto spesso non troverai alcun problema quando lo provi, ma una volta che il tuo programma inizia a scalare dal vivo, ci sono molti problemi. E gli indici possono facilmente fare un fattore 100 nella differenza di velocità.
Pieter B,

3
Ricorda sempre: un indice non è una cosa magica che accelera le tue domande. Un indice comporterà costi sulla maggior parte delle operazioni DML e, a seconda del tipo, può portare a molte attese quando molte persone aggiornano la stessa tabella. Per le query: ci sono molte query che non beneficiano affatto di un indice, in cui un FTS è il più veloce o in cui il partizionamento fa tutto il lavoro per te. - Aggiungi indice solo dove SAPI che saranno utili!
Falco,

Risposte:


132

L'ottimizzazione prematura sta "ottimizzando" qualcosa a causa di un senso vago e intuitivo che, sai, probabilmente sarà lento, soprattutto a scapito della leggibilità e della manutenibilità del codice . Ciò non significa intenzionalmente non seguire buone prassi consolidate in materia di prestazioni.

A volte è una linea difficile da tracciare, ma direi sicuramente che non aggiungere alcun indice prima di andare in diretta è un'ottimizzazione troppo tardi ; questo punirà i primi utenti - i tuoi utenti più desiderosi e più importanti - e darà loro una visione negativa del tuo prodotto, che poi diffonderanno in recensioni, discussioni, ecc. Monitorare le domande per trovare punti dolenti che necessitano di indicizzazione è un buona idea, ma mi assicurerei di farlo entro e non oltre la beta.


11
Sì, dovrebbe essere fatto nella fase di test del carico
Alvaro,

152
L'ottimizzazione prima di sapere dove sono le parti lente è l'ottimizzazione prematura. Rilasciare la cosa prima di sapere dove sono le parti lente è un rilascio prematuro !
MathematicalOrchid,

4
@MathematicalOrchid: è un grande fraseggio! Posso prenderlo in prestito altrove?
Pieter Geerkens,

3
@PieterGeerkens Certo, buttati fuori! ;-) Sono solo triste che 91+ voti non mi facciano guadagnare rep ... eh.
MathematicalOrchid,

3
@MathematicalOrchid avrebbe dovuto essere una risposta. Potrebbe essere la risposta "più piccola al punto giusto" di sempre.
Mindwin,

48

monitorare le query lente una volta che siamo attivi

perché nulla dice qualità come far soffrire i tuoi utenti per mancanza di design!

Dovresti sapere quali query necessitano di indici quando progetti le tabelle, sai su quali colonne vengono interrogate in dove clausole e join. Questi dovrebbero essere già indicizzati perché ciò che potrebbe non essere evidente in un ambiente live potrebbe diventare rapidamente evidente quando aumenta il carico o i dati memorizzati. Quello che non vuoi fare quando succede è schiaffeggiare gli indici su ogni query "lenta", finirai con un indice su tutto.


10
Giusto. Considerare gli indici come parte del progetto del database. Utilizzare gli indici per evitare una scansione completa della tabella per qualsiasi query che l'utente finale eseguirà normalmente in tempo reale.
AE

1
@DocBrown Non ne sono così sicuro, quando progetti un tavolo hai (o dovresti) capire un po 'come verrà usato. Una tabella persona verrà interrogata da ID o eventualmente cognome. Se qualcuno inizia ad accedere tramite DoB, indirizzo o numero di telefono, allora aggiungerai indici per ogni campo - e dove finisce ?!
gbjbaanb,

4
@gbjbaanb: termina quando le persone smettono di aggiungere funzionalità al prodotto, che potrebbe non essere "mai" a seconda della tua metodologia.
Steve Jessop,

1
@SteveJessop Intendo indicizzare in base alle colonne primarie a cui si desidera accedere. Per una tabella persona, potresti avere una funzione di ricerca (se dimentichi il tuo nome utente potresti cercare ad esempio nell'e-mail) ma in seguito usi sempre l'ID. Quindi l'ID è l'unico che necessita di indicizzazione. Se fai molte ricerche su altri campi potresti voler un indice, questo verrà fuori in tempo, ma generalmente non vuoi indicizzare ogni colonna solo perché qualcuno prima o poi ha deciso di scrivere una query non standard, ma potresti utilizzare un meccanismo diverso per questi casi "una tantum".
gbjbaanb,

2
@gbjbaanb: certo, le persone non dovrebbero cercare ripetutamente lo stesso cognome in una tabella perché è una maniglia leggermente più comoda da tenere rispetto alla chiave corretta per la tabella. Direi che è il caso che la tabella sia indicizzata sul cognome o no, in effetti, dal momento che c'è qualcosa di molto sospetto in un tratto di codice che presuppone che tutto funzioni sullo "stesso utente", ma non riesce proprio a esprimerlo nel codice ricordando l'ID :-) Stavo immaginando casi in cui la necessità di una ricerca inversa non era anticipata fino a quando il cliente non l'ha menzionato ...
Steve Jessop,

26

"Ottimizzazione precoce", in senso spregiativo, significa costosa ottimizzazione che potrebbe non essere necessaria. Esso non significa che tutti i ottimizzazione attuate prima l'ultimo punto possibile per evitare il fallimento!

In particolare, è legittimo eseguire l'ottimizzazione in base ai test delle prestazioni prima di andare in diretta, per garantire che sia possibile soddisfare alcuni requisiti sensibili (anche se approssimativi) affinché l'app non si schifhi completamente.

Come minimo, è necessario caricare il database con una quantità plausibile di dati di test e verificare la reattività dell'app. Questo non è prematuro, poiché sai che accadrà e prenderà tutte le domande che innescano scansioni assurdamente lente. Come dice AE in un commento:

Utilizzare gli indici per evitare una scansione completa della tabella per qualsiasi query che l'utente finale eseguirà normalmente in tempo reale

Almeno, per le tabelle che sono pianificate per crescere in uso.

Quindi come scorciatoia a questo, se hai una significativa esperienza con il motore di database e hai già pianificato i test quando scrivi il primo taglio del codice, allora spesso saprai senza nemmeno eseguirlo che la query che stai la scrittura sarà troppo lenta senza un indice. Ovviamente sei libero di far finta di non sapere, e guardare il test fallire prima di aggiungere l'indice per farlo passare, ma non c'è motivo per il codice difettoso noto (perché non risponde) per diventare attivo.


20

Ritengo sia un'ottimizzazione prematura perché la nostra applicazione non è stata ancora rilasciata. Ho suggerito di monitorare le query lente una volta che siamo online e quindi aggiungere gli indici di conseguenza.

Non è possibile trattare gli utenti finali e l'ambiente di produzione come garanzia di qualità. In altre parole, stai dicendo che lo scoprirai in produzione. Non penso che sia la strada giusta e vedo che questo approccio va orribilmente storto ogni giorno .

Devi tenere a mente una cosa, poiché non puoi dipingerla con un pennello largo.

Qual è il tuo carico di lavoro comune ?

Potrebbe sembrare ovvio o noioso, ma è significativo nella pratica. Se hai 10 query che rappresentano il 98% del tuo carico di lavoro (abbastanza comune, che ci crediate o no), la mia raccomandazione sarebbe una dura analisi prima della produzione . Con dati realistici e rappresentativi, assicurati che queste 10 query siano le migliori possibili (la perfetta è una perdita di tempo prezioso e quasi non realizzabile).

Per le altre 200 query che rappresentano il 2% del carico di lavoro , quelle sono quelle che molto probabilmente non valgono una tonnellata di sforzi e compenseranno le stranezze nella risoluzione dei problemi di angolo nella produzione. Anche questa è una realtà, e non una cosa terribilmente negativa. Ma ciò non significa ignorare le migliori pratiche di indicizzazione o fare ipotesi stimate sul recupero dei dati.

È prassi comune e buona norma calcolare le prestazioni del database prima della produzione. In effetti, esiste una posizione relativamente comune per questo tipo di cose chiamata DBA di sviluppo .

Ma...

Alcuni lo spingono troppo in là e impazziscono aggiungendo indici "per ogni evenienza". Qualcuno consiglia questo è un indice mancante? Aggiungilo e altre quattro varianti. Anche una cattiva idea. Devi pensare non solo al recupero dei tuoi dati, ma alla modifica dei dati? Più indici hai su una tabella, generalmente parlando più overhead hai quando modifichi i dati.

Come la maggior parte delle cose, c'è un sano equilibrio.

Come una piccola nota divertente ... La pluralizzazione di "Index"

Gli "indici" sono per i finanziari

Gli "indici" sono per noi


2
Ciò richiede più voti. Non potrei essere più d'accordo.
RubberDuck,

+1 per il bit "just in case" ( sarebbe un'ottimizzazione prematura). Se potessi, aggiungerei nuovamente il voto per il bit "carico di lavoro comune".
David,

Spero che tu sappia in anticipo quali 10 query appartengono al 98% e quali no.
Paŭlo Ebermann,

@ PaŭloEbermann La maggior parte dei DBMS ha la capacità di acquisire tali informazioni abbastanza rapidamente e facilmente. In questo caso, non ci sono scuse per non sapere.
Thomas Stringer,

@ThomasStringer Naturalmente, questo funziona solo se i casi di test prima di passare alla produzione sono in qualche modo correlati a ciò che viene fatto dagli utenti reali in produzione.
Paŭlo Ebermann,

4

No, non si tratta di ottimizzazione prematura, ma deve essere eseguita correttamente come dovrebbe essere qualsiasi ottimizzazione.

Ecco cosa farei:

  1. Caricare il database con dati di test sufficienti per simulare un carico di produzione. Non è possibile ottenere questo preciso al 100% ma va bene: basta inserire abbastanza dati. Una tabella ha una quantità fissa di dati? Caricalo. Hai una tabella che contiene molti dati, ad es. Quale tabella contiene domande su questo sito? Carica alcuni milioni di record anche se solo dati fittizi.
  2. Attiva la profilazione nel tuo server di database.
  3. Bang via all'applicazione utilizzando una combinazione di script automatici (fornisce volume) e utenti reali (sanno come rompere le cose).
  4. Rivedi i dati di profilazione. Le query specifiche sono lente? Controllare i piani di spiegazione e vedere se il server database ti sta dicendo che vuole un indice ma non esiste.

I server di database sono software complessi e intelligenti. Possono dirti come ottimizzarli se sai come ascoltare.

Le chiavi sono misurare le prestazioni prima e dopo l'ottimizzazione e lasciare che il database ti dica di cosa ha bisogno .


3

Seguire schemi comprovati per problemi noti (come trovare un record con il suo ID) non è nulla di prematuro. È solo ragionevole.

Detto questo, gli indici non sono sempre un affare semplice. Durante la fase di progettazione è spesso difficile sapere da quali indici dipenderà il tuo traffico e quali strozzature per le operazioni di scrittura. Quindi, direi di sfruttare alcune best practice "ovvie" per la progettazione di schemi (utilizzare gli appropriati di PK per i modelli di lettura / scrittura progettati e l'indice di FK); ma, non mettere un indice su nient'altro fino a quando lo stress test non lo richiede.


Trascorrere altri 30 secondi per fare qualcosa che è quasi certo di migliorare le prestazioni e che molto probabilmente non danneggerà non è "ottimizzazione prematura". Se il 90% delle operazioni su una tabella utilizza una determinata colonna come chiave, l'indicizzazione migliorerà le prestazioni o le prestazioni non saranno mai abbastanza lente da importare e l'aggiunta di codice per creare l'indice potrebbe richiedere meno tempo rispetto a determinare se si tratta veramente necessario.
supercat,

@supercat "never" ... Fino a quando non inizi a vedere deadlock nel tuo ambiente di produzione ...
svidgen

Quali tipi di scenari realistici immagini che sarebbero coerenti con il 90% delle operazioni che utilizzano una colonna come chiave e in cui l'aggiunta di un indice causerebbe deadlock?
supercat,

@supercat Non sono sicuro di aver compreso appieno le tue ricerche. In termini di un'applicazione attiva, quasi ogni aumento del tempo di esecuzione o del numero di iOS ha il potenziale per introdurre deadlock. ... Ma, più precisamente, la presenza o l'assenza di un indice nella maggior parte delle applicazioni è trascurabile fino a quando il database non raggiunge una dimensione critica e / o un livello di concorrenza. Ad esempio, quando tutti i tuoi indici non rientrano più nella memoria ...
svidgen,

1
Il punto è che è difficile sapere qual è il trucco delle query fino a quando i casi d'uso tipici non vengono sottoposti a uno stress test (o fino a quando non si riscontrano problemi con comportamenti imprevisti dell'utente in produzione). Se hai una pagina che si stacca da tablex.fieldy, ma viene colpita solo una volta ogni mille inserimenti ... L'indice può causare un degrado netto.
svidgen,

2

Quando l'applicazione viene rilasciata, è troppo tardi.

Ma qualsiasi processo di sviluppo adeguato dovrebbe includere test delle prestazioni.

Utilizzare i risultati dei test delle prestazioni per decidere quali indici aggiungere e verificarne l'efficacia ripetendo i test delle prestazioni.


Quando viene rilasciata un'applicazione è davvero un buon momento per modificare gli indici. Guarda questo sito, stachexchange, puoi scommettere sul tuo cappello che gli indici sono cambiati molto tempo dopo che è andato in diretta.
LosManos,

@LosManos: nessuno paga per utilizzare Stack Exchange.
Lightness Races con Monica il

@LightnessRacesinOrbit: O contraire, gli inserzionisti pagano per utilizzare Stack Exchange.

@JonofAllTrades: a loro non importa se abbiamo qualche ora di scarso rendimento a causa di un indice mancante. Il mio punto è che un grande sito web orientato alla comunità e gratuito con un ciclo di distribuzione perpetua è molto diverso da un prodotto commerciale periodico e autonomo. Pertanto, SE non è un buon esempio.
Lightness Races con Monica il

1

Anche se non credo che ogni query debba essere ottimizzata, gli indici fanno così tanto parte di RDBMS che devono essere presi in considerazione prima di rilasciarli. Quando esegui una query, a differenza di altre forme di programmazione non stai dicendo al sistema come eseguirla. Sviluppano i propri piani e quasi sempre lo basano sulla disponibilità di un indice. La composizione e il volume dei dati saranno considerati anche in tempi successivi.

Ecco alcune cose che vorrei prendere in considerazione:

  1. Ci sono alcune domande che dovresti identificare nel tuo primo sviluppo che sai solo che verranno usate frequentemente. Concentrati su di loro.
  2. Ci saranno domande lente. Indicizzandoli prima, puoi quindi determinare se le prestazioni non sono ancora abbastanza veloci e quindi prendere in considerazione una riprogettazione (la denormalizzazione può essere prematura). Preferirei farlo prima di un rilascio. Nessuno vuole un sistema in cui ci vogliono 10 minuti per trovare qualcosa nell'inventario.
  3. Gli indici possono migliorare le prestazioni delle query ma non devono ostacolare la modifica dei dati.
  4. Molti sistemi dispongono di strumenti per analizzare le tue query, quindi non aver paura di usarle.

Dopo la tua revisione iniziale, dovresti dare seguito ad alcune considerazioni su quando dovresti rivederlo di nuovo e su come sarai in grado di raccogliere le informazioni per farlo (monitorare l'utilizzo, ottenere copie dei dati del cliente, ecc.).

Mi rendo conto che non vuoi ottimizzare prematuramente, ma è quasi certo che avrai scarse prestazioni senza indicizzare il tuo database. Togliendolo di mezzo, puoi determinare se ci sono altre aree che causano problemi di prestazioni.


0

Dipende anche da quanti utenti ti aspetti. Dovresti assolutamente fare alcuni test di carico e assicurarti che il tuo database possa tenere il passo con richieste da 10 a 100 a 1000 di richieste simultanee. Ancora una volta, dipende da quanto traffico ti aspetti e da quali aree ti aspetti di essere utilizzate più di altre.

In generale, vorrei mettere a punto le aree in cui mi aspetto che l'utente colpisca per primo. Quindi metterei a punto tutto ciò che è lento dal punto di vista dell'esperienza dell'utente. Ogni volta che l'utente deve aspettare qualcosa, può avere una brutta esperienza e potrebbe essere rifiutato. Non bene!


0

È buona norma identificare quali colonne necessitano sicuramente di un indice mediante alcune analisi iniziali. Esiste un rischio reale di degrado graduale o imprevisto delle prestazioni nella produzione poiché le dimensioni del database aumentano se non si dispone di indici. La situazione che si desidera evitare è quando una query comunemente eseguita richiede la scansione di un numero elevato di righe di tabella. Non è un'ottimizzazione prematura aggiungere indici alle colonne critiche poiché hai a disposizione gran parte delle informazioni necessarie e le potenziali differenze di prestazioni sono significative (ordini di grandezza). Ci sono anche situazioni in cui il vantaggio degli indici è meno chiaro o più dipendente dai dati - probabilmente puoi rimandare la decisione per alcuni di questi casi.

Alcune domande che devi porre sono:

  • Quali saranno i limiti di progettazione per le dimensioni di ogni tavolo?

Se le tabelle saranno sempre piccole (diciamo <100 righe), non è un disastro se il database deve eseguire la scansione dell'intera tabella. Potrebbe essere utile aggiungere un indice, ma ciò richiede un po 'più di esperienza o misurazione per determinare.

  • Con quale frequenza verrà eseguita ciascuna query e qual è il tempo di risposta richiesto?

Se la query viene eseguita di rado e non ha requisiti di tempo di risposta rigorosi (ad es. Generazione di report) e il numero di righe non è enorme, è probabilmente sicuro rinviare l'aggiunta di indici. Ancora una volta, l'esperienza o la misurazione possono aiutare a capire se sarà utile.

  • La query richiede di cercare la tabella con qualcosa a parte la chiave primaria? Ad esempio, filtrando per intervallo di date, unendo una chiave esterna?

Se queste query vengono eseguite frequentemente e toccano le tabelle con più righe, è necessario considerare seriamente l'aggiunta preventiva di un indice. Se non sei sicuro che questo sia il caso di una query, puoi popolare il database con una quantità realistica di dati, quindi guarda il piano di query.

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.