È l'ottimizzazione prematura aggiungere indici di database?

61

Un mio collega oggi ha suggerito di esaminare tutte le domande della nostra applicazione e di aggiungere gli indici di conseguenza.

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

Qual è il consenso generale nella progettazione del tuo database, dovresti aggiungere un indice corrispondente ogni volta che scrivi una nuova query? O è meglio solo monitorare e vedere come va?

    
posta Marco de Jongh 24.02.2015 - 12:57
fonte

10 risposte

132

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

A volte è una linea difficile da disegnare, ma direi che non aggiungere alcun indice prima di andare in diretta è ottimizzazione troppo tardi ; ciò punirà gli early adopter - i tuoi utenti più desiderosi e più importanti - e darà loro una visione negativa del tuo prodotto, che poi diffonderanno tra recensioni, discussioni, ecc. Le query di monitoraggio per trovare punti critici che necessitano di indicizzazione sono buona idea, ma farei in modo di farlo non più tardi della beta.

    
risposta data 24.02.2015 - 13:05
fonte
48

monitor for slow queries once we go live

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 indicizzati già perché ciò che potrebbe non essere evidente in un ambiente live può diventare rapidamente evidente quando il carico oi dati memorizzati aumentano. Quello che non vuoi fare quando succede è sbattere gli indici su ogni query "lenta", finirai con un indice su tutto.

    
risposta data 24.02.2015 - 13:06
fonte
26

"L'ottimizzazione prematura", nel suo senso dispregiativo, significa ottimizzazione costosa che potrebbe non essere necessaria. non significa tutta l'ottimizzazione implementata prima dell'ultimo punto possibile per prevenire il fallimento!

In particolare, è legittimo ottimizzarlo in base ai test delle prestazioni prima di andare in diretta, per assicurarti di soddisfare alcuni requisiti ragionevoli (anche se approssimativi) affinché l'app non venga completamente risucchiata.

Ad un minimo assoluto dovresti caricare il tuo database con una quantità plausibile di dati di test e verificare la reattività della tua app. Questo non è prematuro, dal momento che sai che sta per accadere, e catturerà tutte le query che innescano scansioni assurdamente lente. Come una E dice in un commento:

Use indexes to avoid a full table scan for any query which the end-user will commonly be doing in real-time

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

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

    
risposta data 24.02.2015 - 15:12
fonte
20

I feel this is premature optimisation because our application is not even released yet. I suggested to monitor for slow queries once we go live and then add indices accordingly.

Non puoi trattare i tuoi utenti finali e l'ambiente di produzione come la garanzia della qualità. In altre parole, stai dicendo che lo capirai in produzione. Non penso che sia il modo giusto e vedo che quell'approccio diventa orribilmente sbagliato ogni giorno .

Devi tenere a mente una cosa, dato che 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 costituiscono il 98% del tuo carico di lavoro (abbastanza comune, che ci crediate o meno), la mia raccomandazione sarebbe una analisi approfondita prima della produzione . Con dati realistici e rappresentativi, assicurati che quelle 10 query siano le migliori possibili ( perfect è uno spreco di tempo prezioso, e quasi impossibile da ottenere).

Per le altre 200 query che costituiscono il 2% del carico di lavoro , quelle che molto probabilmente non valgono un sacco di sforzi e costituiranno la soluzione perfetta per la risoluzione dei problemi dei casi d'angolo stranezze in produzione. Anche questa è una realtà, e non è una cosa terribilmente brutta. Ma ciò non significa ignorare le best practice sull'indicizzazione o fare supposizioni sul recupero dei dati.

È normale e buona pratica calcolare le prestazioni del database prima della produzione. In effetti, esiste una posizione relativamente comune per questo tipo di cosa chiamata a sviluppo DBA .

Ma ...

Alcuni lo prendono troppo lontano e impazziscono aggiungendo indici "nel caso in cui". Qualcuno raccomanda che questo sia un indice mancante? Aggiungilo e altre quattro varianti. Anche una cattiva idea. Non devi solo pensare al tuo recupero dei dati, ma per quanto riguarda la modifica dei dati? Più indici hai su una tabella, generalmente più sovraccarico hai quando modifichi i dati.

Come molte altre cose, c'è un equilibrio salutare.

Una piccola nota divertente ... La pluralizzazione di "Index"

"Indici" sono per gli operatori finanziari

"Gli indici" sono per noi

    
risposta data 24.02.2015 - 19:09
fonte
4

No, non è l'ottimizzazione prematura, ma deve essere eseguita correttamente come dovrebbe essere qualsiasi ottimizzazione.

Ecco cosa farei:

  1. Carica 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 un numero sufficiente di dati. Una tabella ha una quantità fissa di dati? Caricarlo Hai una tabella che contiene molti dati, ad es. Qualunque tabella contenga domande su questo sito? Carica alcuni milioni di record anche se solo dati fittizi.
  2. Attiva il profilo nel server del database.
  3. Sconfiggi l'applicazione utilizzando una combinazione di script automatici (fornisce volume) e utenti reali (sanno come rompere le cose).
  4. Controlla i dati di profilazione. Le query specifiche sono lente? Controlla i piani di spiegazione e verifica se il server di 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 servono a misurare le prestazioni prima e dopo l'ottimizzazione e consentono al database di dirti di cosa ha bisogno .

    
risposta data 24.02.2015 - 20:31
fonte
3

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

Detto questo, gli indici non sono sempre un business semplice. Spesso è difficile sapere in fase di progettazione quali indici dipendono dal traffico e quali saranno i colli di bottiglia delle operazioni di scrittura. Quindi, argomenterei per sfruttare alcune "evidenti" best practice di progettazione dello schema (usare i PK appropriati per i modelli di lettura / scrittura progettati e gli indici FK); ma, non mettere un indice su qualsiasi altra cosa fino a quando il tuo stress test lo richiede.

    
risposta data 24.02.2015 - 16:24
fonte
2

Quando la tua applicazione viene rilasciata, è troppo tardi.

Ma qualsiasi processo di sviluppo appropriato dovrebbe includere il test delle prestazioni.

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

    
risposta data 24.02.2015 - 15:24
fonte
1

Sebbene non ritenga che ogni query debba essere ottimizzata, gli indici sono una parte di RDBMS che devono essere presi in considerazione prima di essere rilasciati. Quando esegui una query, a differenza di altre forme di programmazione, non stai dicendo al sistema come eseguirlo. Sviluppano i propri piani e quasi sempre basano sulla disponibilità di un indice. Il trucco e il volume dei dati saranno considerati anche in tempi successivi.

Ecco alcune cose che prenderei in considerazione:

  1. Ci sono alcune domande che dovresti identificare nei tuoi primi sviluppi che sai che saranno usate frequentemente. Concentrati su di loro.
  2. Ci saranno richieste lente. Indicandoli prima, è quindi possibile determinare se le prestazioni non sono ancora abbastanza veloci e quindi prendere in considerazione una riprogettazione (Denormalizing potrebbe essere prematuro). 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 ostacolano la modifica dei dati.
  4. Molti sistemi hanno strumenti per analizzare le tue query, quindi non aver paura di usarle.

Dopo la tua recensione iniziale, dovresti seguirlo con alcune considerazioni su quando dovresti riesaminarlo di nuovo e 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. Mettendo questo fuori mano, puoi determinare se ci sono altre aree che causano problemi di prestazioni.

    
risposta data 04.03.2015 - 19:06
fonte
0

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

In generale, vorrei ottimizzare le aree che mi aspetto che l'utente colpisca maggiormente. Quindi mi piacerebbe mettere a punto tutto ciò che è lento dal punto di vista dell'esperienza utente. Ogni volta che l'utente deve aspettare qualcosa, ottiene un'esperienza negativa e potrebbe essere rifiutato. Non va bene!

    
risposta data 24.02.2015 - 20:17
fonte
0

È una buona pratica identificare quali colonne necessitano sicuramente di un indice con alcune analisi iniziali. Esiste il rischio reale di un degrado graduale o imprevisto delle prestazioni in produzione con l'aumento delle dimensioni del database se non si dispone di alcun indice. La situazione che si desidera evitare è quella in cui una query di esecuzione comune richiede la scansione di un numero elevato di righe della tabella. Non è l'ottimizzazione prematura di aggiungere indici a colonne critiche poiché si dispone di molte delle informazioni necessarie disponibili e le potenziali differenze di prestazioni sono significative (ordini di grandezza). Ci sono anche situazioni in cui il beneficio degli indici è meno chiaro o più dipendente dai dati: probabilmente è possibile rinviare la decisione per alcuni di questi casi.

Alcune domande che devi porre sono:

  • Quali sono i limiti di progettazione per le dimensioni di ogni tabella?

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 da 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 rigidi (ad esempio generazione di report) e il numero di righe non è elevato, è probabilmente abbastanza sicuro posticipare l'aggiunta di indici. Ancora una volta, l'esperienza o la misurazione può aiutare a capire se sarà vantaggioso.

  • La query richiede di cercare sul tavolo qualcosa oltre alla chiave primaria? Per esempio. filtrando per intervallo di date, unendosi a una chiave esterna?

Se queste query vengono eseguite frequentemente e si toccano tabelle con molte righe, è necessario prendere seriamente in considerazione 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à di dati realistica, quindi consulta il piano di query.

    
risposta data 04.03.2015 - 19:49
fonte

Leggi altre domande sui tag