Dari mana Pengoptimal Kueri MySQL membaca statistik indeks?


14

Saya mencoba untuk menentukan dari mana pengoptimal MySQL mendapatkan daftar indeks yang tersedia untuk sebuah tabel ketika memperkirakan biaya (menyiapkan) kueri dari.


+1 untuk pertanyaan yang bagus ini karena Pengembang dan DBA harus berhenti sejenak dan berpikir tentang bagaimana statistik indeks dikompilasi dan disimpan.
RolandoMySQLDBA

Untuk referensi, dari situs web dokumentasi mysql: < dev.mysql.com/doc/refman/5.0/en/innodb-restrictions.html >> ANALYZE TABLEmenentukan kardinalitas indeks (seperti yang ditampilkan di kolom kardinalitas SHOW INDEXkeluaran) dengan melakukan delapan penyelaman acak untuk masing-masing dari pohon indeks dan memperbarui perkiraan kardinalitas indeks yang sesuai. Karena ini hanya perkiraan, proses ANALYZE TABLE yang berulang dapat menghasilkan angka yang berbeda. Ini membuat ANALYZE TABLEcepat pada tabel InnoDB tetapi tidak 100% akurat karena tidak memperhitungkan semua baris.
Chen Xie

Jawaban:


6

Jawaban langsung untuk ini adalah

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)

Anda bisa PILIH dari tabel itu dengan

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

atau lihat statistik dengan melakukan

TAMPILKAN INDEKS DARI mydb.mytable;

Harap diingat bahwa tabel ini tidak selalu akurat dalam lingkungan yang berat. Secara berkala Anda harus menjalankan ANALYZE TABLE terhadap semua tabel MyISAM yang sering diperbarui. Jika tidak, Pengoptimal Permintaan MySQL, yang bergantung pada information_schema.statistics, kadang-kadang dapat membuat pilihan yang buruk ketika mengembangkan rencana EXPLAIN untuk permintaan. Statistik indeks harus selalu diperbarui.

TABEL ANALYZE TIDAK BENAR EFEKTIF terhadap tabel InnoDB. Semua statistik indeks untuk InnoDB dihitung berdasarkan permintaan dengan cara menyelam ke halaman BTREE. Oleh karena itu, ketika Anda menjalankan TAMPILKAN INDEKS DARI tabel InnoDB, kardinalitas yang ditampilkan selalu merupakan perkiraan.

UPDATE 2011-06-21 12:17 EDT

Untuk klarifikasi dari ANALYZE TABLE, izinkan saya ulangi. Menjalankan TABEL ANALISIS pada tabel InnoDB sama sekali tidak berguna. Bahkan jika Anda menjalankan ANALYZE TABLE pada tabel InnoDB, mesin penyimpanan InnoDB melakukan penyelaman ke dalam indeks untuk perkiraan kardinalitas berulang-ulang, sehingga menghancurkan statistik yang baru saja Anda kompilasi . Bahkan, Percona melakukan beberapa tes pada ANALYZE TABLE dan sampai pada kesimpulan itu juga.


5

Re: ANALYZE TABLE telah BENAR-BENAR TIDAK EFEK terhadap tabel InnoDB.

Saya tidak yakin apakah pernyataan ini benar. Kami memiliki banyak membaca & menulis tabel innodb dan ketika pengoptimal mysql membuat pilihan yang buruk, kueri menjelaskan output menunjukkan strategi yang buruk. dan juga MENUNJUKKAN INDEKS dari tabel Innodb menunjukkan begitu banyak perbedaan dalam nilai kardinalitas mereka. Tetapi menjalankan perintah ANALYZE pada tabel innodb memperbaiki rencana menjelaskan dan juga menghilangkan perilaku varians kardinalitas. Saya tidak tahu apakah perintah tabel ANALYZE pada tabel Innodb membantu sepanjang waktu atau tidak, tetapi dalam kasus kami, itu memang membantu sekitar 99% dari waktu.

Kami telah sepenuhnya menghilangkan pilihan buruk pengoptimal mysql dengan memasukkan "STRAIGHT_JOIN" di kueri kami. Ini memaksa pengoptimal mysql untuk tidak membuat pilihan yang buruk atau pilihan apa pun, tetapi ikuti saja kondisi GABUNG dari apa yang kami definisikan dalam kueri apa adanya.


Saya memperbarui jawaban saya untuk menyoroti kegunaan dari ANALYZE TABLE pada tabel InnoDB.
RolandoMySQLDBA

Saya setuju dengan jawaban Anda ketika Anda menyebutkan perbedaan dalam kardinalitas. Itulah tepatnya yang saya katakan ketika saya mengatakan perkiraan kardinalitas.
RolandoMySQLDBA

Saya juga perlu menyebutkan bahwa menggunakan petunjuk dalam kueri tidak selalu merupakan hal terbaik untuk dilakukan ketika MySQL Query Optimizer cenderung menghilangkannya di beberapa waktu. Berikut ini tautan ke apa yang terjadi secara internal pada kueri yang benar-benar dapat membuat data menghilang di bagian rencana kueri: dba.stackexchange.com/questions/1371/…
RolandoMySQLDBA

2

TABEL ANALISIS untuk MyISAM memindai seluruh tabel dan membangun kembali statistik, yang disimpan dalam (saya pikir) file .MYI. Ini jarang dibutuhkan.

TABEL ANALISIS untuk InnoDB tidak melakukan sesuatu - itu menyelam yang disebutkan. Masalahnya adalah itu dapat membantu, memperburuk keadaan, atau (kemungkinan besar) tidak akan membuat perbedaan yang terlihat (kecuali dalam kardinalitas).

Versi yang lebih baru berjanji untuk mengizinkan mengubah 8 probe yang tidak begitu acak menjadi (1) lebih acak, (2) membiarkan Anda mengubah "8" (ada pro dan kontra dari ini!), Dan (3) menyimpan di seluruh restart.

Intinya: InnoDB masih belum benar '. Lakukan analisis ketika Anda menginginkannya, tetapi jangan menahan nafas.

Memperbarui

Untuk ulang frase ... ANALYZE TABLEmemiliki sementara efek (mungkin bermanfaat, mungkin tidak) pada optimalisasi tabel InnoDB.

"Versi yang lebih baru": Dimulai dengan 5.6.6 (2012) dan MariaDB 10.1 (2014), statistik ditangani jauh lebih baik, dan ANALYZEsekarang (1) lebih jarang dibutuhkan, dan (2) lebih permanen.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.