MySQL Query Optimizerはどこからインデックス統計を読み取りますか?


14

MySQLオプティマイザーがクエリのコストを推定(準備)するときに、テーブルで使用可能なインデックスのリストを取得する場所を特定しようとしています。


開発者とDBAは一時停止し、インデックス統計のコンパイル方法と保存方法について考える必要があるため、この良い質問に+1を付けてください。
-RolandoMySQLDBA

参考のために、mysqlのドキュメントWebサイトから:< dev.mysql.com/doc/refman/5.0/en/innodb-restrictions.html >> ANALYZE TABLEインデックスのカーディナリティ(SHOW INDEX出力の[ カーディナリティ]列に表示される)をそれぞれ8回のランダムダイブを実行して決定しますインデックスツリーの更新とそれに応じたインデックスカーディナリティの推定の更新。これらは推定値にすぎないため、ANALYZE TABLEを繰り返し実行すると異なる数値が生成される場合があります。これはANALYZE TABLEInnoDBテーブルで高速になりますが、すべての行を考慮しないため、100%正確ではありません。
陳謝

回答:


6

これに対する直接的な答えは

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)

あなたはそのテーブルからSELECTできます

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

または以下を実行して統計を表示します

mydb.mytableからインデックスを表示します。

このテーブルは、書き込みが多い環境では必ずしも正確ではないことに注意してください。頻繁に更新されるすべてのMyISAMテーブルに対して定期的にANALYZE TABLEを実行する必要があります。そうしないと、information_schema.statisticsに依存するMySQL Query Optimizerが、クエリのEXPLAINプランを開発する際に間違った選択をする場合があります。インデックス統計は可能な限り最新でなければなりません。

ANALYZE TABLEはInnoDBテーブルに対してまったく効果がありません。InnoDBのすべてのインデックス統計は、BTREEページへのダイブによってオンデマンドで計算されます。したがって、InnoDBテーブルに対してSHOW INDEXES FROMを実行すると、表示されるカーディナリティは常に近似値になります。

更新2011-06-21 12:17 EDT

ANALYZE TABLEを明確にするために、言い替えさせてください。InnoDBテーブルでANALYZE TABLEを実行することはまったく役に立ちません。InnoDBテーブルでANALYZE TABLEを実行した場合でも、InnoDBストレージエンジンはカーディナリティー近似のインデックスへのダイブを繰り返し実行するため、コンパイルしばかりの統計が破壊されます。実際、PerconaはANALYZE TABLEでいくつかのテストを実行し、同様にその結論に達しました。


5

Re:ANALYZE TABLEはInnoDBテーブルに対してまったく効果がありません。

この声明が真実かどうかはわかりません。innodbテーブルを頻繁に読み書きしています。mysqlオプティマイザーが不適切な選択をすると、クエリのExplain出力が不適切な戦略を示します。また、InnodbテーブルのSHOW INDEXESは、カーディナリティ値に非常に大きな違いを示しています。ただし、これらのinnodbテーブルでANALYZEコマンドを実行すると、説明プランが修正され、カーディナリティの分散動作もなくなります。InnodbテーブルのANALYZEテーブルコマンドが常に役立つかどうかはわかりませんが、私たちのケースでは、約99%を助けました。

クエリに「STRAIGHT_JOIN」を含めることで、mysqlオプティマイザーの不適切な選択を完全に排除しました。これにより、mysqlオプティマイザーは間違った選択や選択をせずに、クエリで定義したもののJOIN条件をそのまま従います。


InnoDBテーブルでANALYZE TABLEが役に立たないことを強調するために、回答を更新しました。
RolandoMySQLDBA

カーディナリティの違いについて言及したときの回答に同意します。それはまさに、カーディナリティー近似を言ったときに言っていたことです。
-RolandoMySQLDBA

また、クエリでヒントを使用することは、MySQLクエリオプティマイザーが時々それらを削除する傾向がある場合に行うべき最善のことではないことにも言及する必要がありました。クエリプランの一部で実際にデータを非表示にすることができるクエリの内部で行われることへのリンクを次に示し
questions

2

ANALYZE TABLE for MyISAMはテーブル全体をスキャンし、統計を再構築します。統計は.MYIファイルに保存されます(と思います)。ほとんど必要ありません。

ANALYZE TABLE for InnoDB 何かをます-それは言及された急降下をします。問題は、それが助けになるかもしれないし、事態を悪化させるかもしれないし、(ほとんどの場合)目に見える違いをもたらさないかもしれないということです(カーディナリティを除く)。

新しいバージョンでは、8つのそれほどランダムではないプローブを(1)よりランダムに変更し、(2)「8」を変更できます(これには賛否両論あります!)。

結論:InnoDBはまだ「正しい」とは言えません。気になったら分析しますが、息を止めないでください。

更新

再フレーズに... ANALYZE TABLE持っている一時的な InnoDBテーブルの最適化に影響を(おそらく有益な、おそらくありません)。

「新しいバージョン」:5.6.6(2012)およびMariaDB 10.1(2014)から、統計の処理が大幅に改善され、ANALYZE(1)必要性が減り、(2)より永続的になりました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.