非公式MySQL 8.0オプティマイザガイド

View the Project on GitHub

  1. はじめに
  2. サーバーアーキテクチャー
  3. B+ツリー インデックス
  4. Explain
  5. オプティマイザ トレース
  6. 論理変換
  7. コストベース最適化
  8. ヒント
  9. プランの比較
  10. 複合インデックス
  11. カバリングインデックス
  12. Visual Explain
  13. 変わりゆく実行計画(Transient Plans)
  14. サブクエリー
  15. 共通テーブル式(CTE)とビュー
  16. 結合
  17. 集約
  18. ソート
  19. パーティショニング
  20. クエリーリライト
  21. 不可視インデックス
  22. クエリープロファイリング
  23. JSONと生成列
  24. 文字セット

変わりゆく実行計画(Transient Plans)

原文URL: http://www.unofficialmysqlguide.com/transient-plans.html
翻訳者: taka-h (@takaidohigasi)

同じようにみえるクエリーも全く違った実行計画となることがあります。これまでpopulationの述部を修正することによって確認してきました。例8では、population > 500M(5億)を指定することで population >5M(500万)を指定した場合と異なったインデックスが選択されました。

クエリーの一部がユーザー入力から生成される本番環境では、このようなことはとても良く発生します1。例としては、

これは予期された挙動で、統計収集(「メタデータと統計」の章で言及済み)の結果です。次の表は、populationcontinent が変わった際にインデックスの相対的コストがどの程度変化するかを示しています。

  p>5M,c=’Asia’ p>5M,c=’Antarctica’ p>50M, c=’Asia’ p>50M,c=’Antarctica’ p>500M, c=’Asia’ p>500M,c=’Antarctica’
p 152.21 152.21 34.61 34.61 3.81 3.81
c 28.20 6.00 28.20 6.00 28.20 6.00
c,p 24.83 2.41 16.41 2.41 3.81 2.41
p,c 152.21 152.21 34.61 34.61 3.81 3.81
テーブルスキャン 53.80 53.80 53.80 53.80 53.80 53.80

これは視覚的にも表すことが出来ます。continentへのテーブルスキャンおよびrefアクセスは一定コストであり、(Continent, Population)への複合インデックスがcontinentへのrefアクセスと同一コストで始まり、このときpopulationの選択性は高くありません。populationが大きくなるに連れて選択性が増します。

複合インデックスが効果的でなければ、個々のインデックス(pupulationまたはcontinent)と近いコストになるでしょう。最後にpopulation > 3M(300万)の国はすべてアジアにあるため、選択性はpopulationへのインデックスを利用したときとほとんど変わりません。

cost-as-afunction-of-p

次の可視化はインデックスpを強制的に利用させ、populationを(WHERE population > 1M(100万)からWHERE population > 500M(5億)まで)変えて100回実行した際の実行時間の中央値を示しています。実行時間はperformance_schema.events_statements_history_longから取得し、マイクロ秒(μs)に変換しています。データセットが小規模で、人口が少ない国がとても少ないため、同一のページがアクセスされたと思われる実行時間のクラスターがみられるのではないかと思います。 しかしながらいくらかの相関がみられます。 execution-time-vs-cost

Tips
この可視化の結果はデータ分布に強く依存します。サンプルのデータセットを確認すれば、不正確なところがあることが分かるでしょう。データはStatistics Finland(1990年代)のもので均一に更新されていません
  1. クエリーの分布によっては、これらの例の両方のケースでインデックスを生成するより、パーティショニングした方がうまく動作するかもしれません。