Manutenzione degli indici MySQL


12

Ho fatto molte ricerche su come mantenere gli indici in MySQL per prevenire la frammentazione e ottimizzare in qualche modo l'esecuzione di alcune query.

Conosco quella formula che calcola il rapporto tra lo spazio massimo disponibile per una tabella VS lo spazio utilizzato da dati e indici.

Tuttavia le mie domande principali sono ancora senza risposta. Forse questo è dovuto al fatto che ho familiarità con la manutenzione dell'indice in SQL Server e tendo a pensare che in MySQL dovrebbe essere in qualche modo simile.

In SQL Server, è possibile disporre di più indici e ognuno di essi può avere diversi livelli di frammentazione. Quindi puoi prenderne uno ed eseguire un'operazione 'RIORGANIZZA' o 'RICOSTRUISCI' in quel particolare indice, senza influire sul resto.

Per quanto ne so, non esiste una "frammentazione di tabelle" in quanto tale e SQL Server non fornisce alcun strumento per correggere la "frammentazione di tabelle". Ciò che fornisce sono strumenti per controllare la frammentazione dell'indice (intesa come il rapporto tra il numero di pagine utilizzate da un indice VS la pienezza di quella pagina e la contiguità), nonché la frammentazione interna ed esterna.

Tutto ciò è abbastanza semplice da capire, almeno per me.

Ora, quando arriva il turno di mantenere gli indici in MySQL, esiste solo il concetto di "frammentazione della tabella", come menzionato sopra.

Una tabella in MySQL può avere diversi indici, ma quando controllo il "rapporto di frammentazione" con quella formula famosa, non vedo la frammentazione di ciascun indice, ma la tabella nel suo insieme.

Quando voglio ottimizzare gli indici in MySQL, non scelgo un indice particolare su cui operare (come in SQL Server). Invece, eseguo un'operazione 'OTTIMIZZA' in tutta la tabella, che presumibilmente influenza tutti gli indici.

Quando la tabella è ottimizzata in MySQL, il rapporto tra lo spazio utilizzato da dati + indici VS lo spazio complessivo viene ridotto, il che suggerisce una sorta di riorganizzazione fisica nel disco rigido, che si traduce in una riduzione dello spazio fisico. Tuttavia, la frammentazione dell'indice non riguarda solo lo spazio fisico, ma la struttura dell'albero che è stata modificata nel tempo a causa di inserimenti e aggiornamenti.

Alla fine ho ottenuto un tavolo in InnoDB / MySQL. Quella tabella ha 3 milioni di record, 105 colonne e 55 indici. Sono 1,5 GB esclusi gli indici, che sono 2,1 GB.

Quella tabella viene colpita migliaia di volte ogni giorno per l'aggiornamento, l'inserimento (in realtà non eliminiamo i record).

Quella tabella è stata creata anni dopo e so con certezza che nessuno mantiene indici di sorta.

Mi aspettavo di trovare un'enorme frammentazione lì, ma quando eseguo il calcolo della frammentazione come prescritto

free_space / (data_length + index_length)

risulta che ho solo una frammentazione dello 0,2%. IMHO che è abbastanza irrealistico.

Quindi le grandi domande sono:

  1. Come posso verificare la frammentazione di un determinato indice in MySQL, non la tabella nel suo insieme
  2. OPTIMIZE TABLE risolve effettivamente la frammentazione interna / esterna di un indice come in SQL Server?
  3. Quando ottimizzo una tabella in MySQL, in realtà ricostruisce tutti gli indici sulla tabella?
  4. È realistico pensare che ridurre lo spazio fisico di un indice (senza ricostruire l'albero stesso) si traduca effettivamente in una prestazione migliore?

tabella di ottimizzazione sicuramente pulisce l'indice cluster su innodb

1
è un'ottima domanda, non solo di programmazione. Andranno spostati a cui appartiene:>

Risposte:


6

La frammentazione dell'indice è molto sopravvalutata. Non ti preoccupare di quello.

Due blocchi adiacenti, un po 'vuoti, vengono uniti da InnoDB come elaborazione naturale.

Le azioni casuali su un BTree lo fanno gravitare naturalmente verso una media del 69% pieno. Certo, questo non è al 100%, ma il sovraccarico del "fissaggio" non ne vale la pena.

SHOW TABLE STATUS fornisce alcune metriche, ma sono imperfette: "Data_free" include un certo spazio "libero", ma non altro spazio "libero".

C'è spazio inutilizzato in ogni blocco; blocchi da 16KB gratuiti; "estensioni" gratuite (blocchi di nMB); Righe MVCC in attesa di essere raccolte; i nodi non foglia hanno la loro frammentazione; eccetera.

Percona e Oracle hanno diversi modi di vedere quanto è grande (numero di blocchi) un indice. Non trovo nessuno dei due utile a causa della definizione limitata di "libero". Sembra che i blocchi (16 KB ciascuno) siano allocati in blocchi (diversi MB), portando così a credere che vi sia una sorta di frammentazione. In realtà, di solito è solo la maggior parte di uno di questi blocchi multi-MB. E OPTIMIZE TABLEnon recupera necessariamente nulla dello spazio.

Se SQL Server sta usando BTrees, allora sta mentendo dire che non c'è "nessuna frammentazione". Pensa a cosa succede in una "suddivisione in blocchi". O pensa al sovraccarico di deframmentare continuamente. Ad ogni modo, perdi.

Si noti inoltre che una tabella e un indice sono essenzialmente strutture identiche:

  • B + Tree, basato su alcuni indici
  • I "dati" si basano sul PRIMARY KEY; ogni indice secondario è un albero B + basato sul suo indice.
  • Il nodo foglia dei "dati" contiene tutte le colonne della tabella.
  • Il nodo foglia di un indice secondario contiene le colonne di quell'indice secondario, più le colonne del PRIMARY KEY.

Se hai innodb_file_per_table = ON, puoi vedere chiaramente il restringimento (se presente) dopo OTTIMIZE TABLE guardando le .ibddimensioni del file. Perché OFF, le informazioni sono sepolte in ibdata1, ma SHOW TABLE STATUSpossono essere ragionevolmente precise poiché tutto lo spazio "libero" appartiene a ogni tabella. Bene, ad eccezione dei pezzi pre-assegnati.

Si può notare che una tabella di file per tabella appena ottimizzata ha esattamente 4M, 5M, 6M o 7M di Data_free. Ancora una volta, questa è la pre-allocazione e l'incapacità di fornire dettagli dettagliati.

Ho lavorato con InnoDB per oltre un decennio; Ho lavorato con migliaia di tavoli diversi, grandi e piccoli. Dico che solo una tabella su mille ha davvero bisogno OPTIMIZE TABLE. Usarlo su altri tavoli è uno spreco.

105 colonne sono molte, ma forse non troppe.

Hai 55 indici su una tabella? Non va bene. Sono 55 gli aggiornamenti per INSERT. Discutiamolo ulteriormente. Tieni presente che INDEX(a)è inutile se hai anche INDEX(a,b). Ed INDEX(flag)è inutile a causa della bassa cardinalità. (Ma INDEX(flag, foo)può essere utile.)

D1: Non esiste un buon modo per verificare tutte le forme di frammentazione nei dati o negli indici secondari.

Q2, Q3: OPTIMIZE TABLEricostruisce la tabella con CREATEinguna nuova tabella e INSERTingtutte le righe, quindi RENAMEinge DROPping. Il reinserimento dei dati nell'ordine PK assicura che i dati siano ben deframmentati. Gli indici sono un'altra questione.

Q4: è possibile DROP e reCREATEogni indice per ripulirlo. Ma questo è un processo estremamente lento. 5.6 ha alcune accelerazioni, ma non so se aiutano con la deframmentazione.

È anche possibile ALTER TABLE ... DISABLE KEYS, quindi ENABLEloro. Questo potrebbe consentire una ricostruzione più efficiente di tutti gli indici secondari contemporaneamente.


Rick, intendevo campi "105", non file
Nicolas,

1

Come posso verificare la frammentazione di un determinato indice in MySQL, non la tabella nel suo insieme

Passaggio.

OPTIMIZE TABLE risolve effettivamente la frammentazione interna / esterna di un indice come in SQL Server?

Ricostruisce completamente la tabella e i suoi indici.

Quando ottimizzo una tabella in MySQL, in realtà ricostruisce tutti gli indici sulla tabella?

Questa è la stessa domanda con la stessa risposta.

È realistico pensare che ridurre lo spazio fisico di un indice (senza ricostruire l'albero stesso) si traduca effettivamente in una prestazione migliore?

Non è realistico pensare che potresti ridurre lo spazio senza ricostruire l'albero. Vanno insieme.


Per rispondere # 1: anche se non è molto preciso, ma SHOW TABLE STATUS LIKE 'mytable'darebbe un suggerimento nella data freecolonna. dev.mysql.com/doc/refman/5.6/en/show-table-status.html
Jehad Keriaki

Lo so, ma manca ancora lo spazio di un determinato indice
Nicolas,
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.