Da dove MySQL Query Optimizer legge le statistiche dell'indice?


14

Sto cercando di determinare da dove l'ottimizzatore MySQL ottiene l'elenco di indici disponibili per una tabella quando stima il costo di (prepara) una query.


+1 per questa buona domanda perché gli sviluppatori e i DBA dovrebbero mettere in pausa e pensare a come vengono compilate e memorizzate le statistiche sugli indici.
RolandoMySQLDBA,

Per riferimento, dal sito Web della documentazione di mysql: < dev.mysql.com/doc/refman/5.0/en/innodb-rest restrizioni.html >> ANALYZE TABLEdetermina la cardinalità dell'indice (come visualizzato nella colonna Cardinalità SHOW INDEXdell'output) effettuando otto immersioni casuali per ciascuna degli alberi indice e di conseguenza aggiornare le stime della cardinalità dell'indice. Poiché si tratta solo di stime, ripetute esecuzioni di TABELLA ANALISI possono produrre numeri diversi. Questo rende ANALYZE TABLEveloce sulle tabelle InnoDB ma non è preciso al 100% perché non tiene conto di tutte le righe.
Chen Xie,

Risposte:


6

La risposta diretta per questo sarebbe

information_schema.statistics

mysql> desc information_schema.statistics;
+---------------+---------------+------+-----+---------+-------+
| Field         | Type          | Null | Key | Default | Extra |
+---------------+---------------+------+-----+---------+-------+
| TABLE_CATALOG | varchar(512)  | NO   |     |         |       |
| TABLE_SCHEMA  | varchar(64)   | NO   |     |         |       |
| TABLE_NAME    | varchar(64)   | NO   |     |         |       |
| NON_UNIQUE    | bigint(1)     | NO   |     | 0       |       |
| INDEX_SCHEMA  | varchar(64)   | NO   |     |         |       |
| INDEX_NAME    | varchar(64)   | NO   |     |         |       |
| SEQ_IN_INDEX  | bigint(2)     | NO   |     | 0       |       |
| COLUMN_NAME   | varchar(64)   | NO   |     |         |       |
| COLLATION     | varchar(1)    | YES  |     | NULL    |       |
| CARDINALITY   | bigint(21)    | YES  |     | NULL    |       |
| SUB_PART      | bigint(3)     | YES  |     | NULL    |       |
| PACKED        | varchar(10)   | YES  |     | NULL    |       |
| NULLABLE      | varchar(3)    | NO   |     |         |       |
| INDEX_TYPE    | varchar(16)   | NO   |     |         |       |
| COMMENT       | varchar(16)   | YES  |     | NULL    |       |
| INDEX_COMMENT | varchar(1024) | NO   |     |         |       |
+---------------+---------------+------+-----+---------+-------+
16 rows in set (0.01 sec)

Puoi SELEZIONARE da quella tabella con

SELECT * FROM information_schema.statistics
WHERE table_schema='mydb' AND table_name='mytable';

o vedere le statistiche facendo

VISUALIZZA INDICI DA mydb.mytable;

Si prega di tenere presente che questa tabella non è sempre accurata in un ambiente pesante per la scrittura. Periodicamente dovrai eseguire ANALYZE TABLE su tutte le tabelle MyISAM che vengono aggiornate frequentemente. Altrimenti, MySQL Query Optimizer, che si basa su information_schema.statistics, a volte può fare scelte sbagliate durante lo sviluppo di piani EXPLAIN per le query. Le statistiche dell'indice devono essere il più aggiornate possibile.

ANALYZE TABLE non ha ASSOLUTAMENTE NESSUN EFFETTO contro le tabelle InnoDB. Tutte le statistiche dell'indice per InnoDB sono calcolate su richiesta mediante immersioni nelle pagine BTREE. Pertanto, quando si esegue SHOW INDEXES FROM su una tabella InnoDB, le cardinalità visualizzate sono sempre approssimazioni.

AGGIORNAMENTO 2011-06-21 12:17 EDT

Per chiarimenti su ANALYZE TABLE, lasciami riformulare. L'esecuzione di ANALYZE TABLE su tabelle InnoDB è completamente inutile. Anche se hai eseguito ANALYZE TABLE su una tabella InnoDB, il motore di archiviazione InnoDB esegue ripetutamente immersioni nell'indice per approssimazioni di cardinalità, eliminando così le statistiche appena compilate . In effetti, Percona ha eseguito alcuni test su ANALYZE TABLE e ha raggiunto anche questa conclusione.


5

Ri: ANALYZE TABLE non ha ASSOLUTAMENTE NESSUN EFFETTO contro le tabelle InnoDB.

Non sono sicuro che questa affermazione sia vera. Abbiamo pesantemente letto e scritto tabelle innodb e quando mysql optimizer fa la scelta sbagliata, l'output di spiegazione della query mostra una strategia sbagliata. e anche MOSTRA INDICI da una tabella Innodb mostra tanta varianza nei loro valori di cardinalità. Ma eseguire un comando ANALYZE su quelle tabelle innodb corregge il piano esplicativo e toglie anche il comportamento di varianza della cardinalità. Non so se il comando ANALYZE table sulle tabelle Innodb sia sempre utile o meno, ma nel nostro caso, ha aiutato circa il 99% delle volte.

Abbiamo eliminato completamente la cattiva scelta dell'ottimizzatore mysql includendo "STRAIGHT_JOIN" nelle nostre query. Questo ottimizzatore mysql forzato non ha fatto scelte sbagliate o scelte, ma ha semplicemente seguito le condizioni JOIN di ciò che abbiamo definito nella query.


Ho aggiornato la mia risposta per evidenziare l'inutilità di ANALYZE TABLE sulle tabelle InnoDB.
RolandoMySQLDBA

Sono d'accordo con la tua risposta quando hai menzionato la varianza nella cardinalità. Questo è esattamente quello che stavo dicendo quando ho detto approssimazioni di cardinalità.
RolandoMySQLDBA,

Avevo anche bisogno di menzionare che l'uso di suggerimenti nelle query non è sempre la cosa migliore da fare quando MySQL Query Optimizer tende a eliminarli a volte. Ecco un link a ciò che accade internamente alle query che possono effettivamente far scomparire i dati in parti dei piani di query: dba.stackexchange.com/questions/1371/…
RolandoMySQLDBA

2

ANALYZE TABLE per MyISAM esegue la scansione dell'intero tavolo e ricostruisce le statistiche, che viene salvato nel file (credo) .MYI. Raramente è necessario.

ANALYZE TABLE per InnoDB fa qualcosa - fa l'immersione menzionata. Il problema è che può aiutare, può peggiorare le cose o (molto probabilmente) non fare alcuna differenza visibile (tranne nelle cardinalità).

Le versioni più recenti promettono di consentire la modifica delle 8 sonde non casuali in (1) più casuali, (2) permettendoti di cambiare gli "8" (ci sono pro e contro di questo!) E (3) salvare attraverso i riavvii.

Bottom line: InnoDB non ha ancora ottenuto 'giusto'. ANALIZZA quando ne hai voglia, ma non trattenere il respiro.

Aggiornare

La riformulazione ... ANALYZE TABLEha un effetto temporaneo (forse utile, forse no) sulle ottimizzazioni delle tabelle InnoDB.

"Versione più recente": a partire da 5.6.6 (2012) e MariaDB 10.1 (2014), le statistiche sono gestite molto meglio e ANALYZEora sono (1) meno spesso necessarie e (2) più permanenti.

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.