非公式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. 文字セット

クエリーリライト

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

MySQLはサーバーサイドでステートメントを書き換える機能を提供しています。これはあるパターンに合致するステートメントを新しいパターンに書き換えられるサーバーサイドの正規表現のようなものであると考えることができます。

この機能の設計のゴールはデータベース管理者がクエリーヒントをステートメントに挿入できるようにすることでした。これはORMを利用していたり、アプリケーションがプロプライエタリであったりして、アプリケーション自体を修正できない場合に状況を改善する手段を提供するものです。

クエリーリライトは正規表現と似たものであると述べましたが、内部的にははるかに効率的なものであることはお伝えしておく必要があります。ステートメントがパースされる際に、ダイジェスト(プリペアードステートメントという形でも知られています)が内部のハッシュテーブルの書き換えるべき値と比較されます。ステートメントが「書き換えが必要である」と判断されれば、サーバーはこのクエリー書き換えのステップを実行し再度クエリーをパースします。書き換えの必要のないクエリーにもわずかなオーバーヘッドが発生し、書き換えの必要なクエリーは簡単にいうと2回パースする必要があります。

例33: クエリーリライトでサーバーサイドのクエリーを変更する

# コマンドラインからクエリーリライトをインストールします
mysql -u root -p < install_rewriter.sql

# MySQLサーバーでリライトルールを追加し、フラッシュします
INSERT INTO query_rewrite.rewrite_rules(pattern_database, pattern, replacement) VALUES (
"world",
"SELECT * FROM Country WHERE population > ? AND continent=?",
"SELECT * FROM Country WHERE population > ? AND continent=? LIMIT 1"
);
CALL query_rewrite.flush_rewrite_rules();

# クエリーリライトはリライトが発生するとき毎回warningを発生させます
SELECT * FROM Country WHERE population > 5000000 AND continent='Asia';
SHOW WARNINGS;
Query 'SELECT * FROM Country WHERE population > 5000000 AND continent='Asia'' rewritten to 'SELECT * FROM Country WHERE population > 5000000 AND continent='Asia' LIMIT 1' by a query rewrite plugin

SELECT * FROM query_rewrite.rewrite_rules\G
*************************** 1. row ***************************
                id: 2
           pattern: SELECT * FROM Country WHERE population > ? AND continent=?
  pattern_database: world
       replacement: SELECT * FROM Country WHERE population > ? AND continent=? LIMIT 1
           enabled: YES
           message: NULL
    pattern_digest: 88876bbb502cef6efddcc661cce77deb
normalized_pattern: select `*` from `world`.`Country` where ((`population` > ?) and (`continent` = ?))
Tips
MySQLサーバーは各種Query Rewriteプラグインをサポートしています。ここで示される例では、MySQLサーバーディストリビューション同梱のポストパース クエリーリライトプラグイン(通称Rewriter)を利用しています。クエリーによってはプレパースプラグインを利用する必要があるかもしれません。詳細については次のMySQLのマニュアルを御覧ください。 https://dev.mysql.com/doc/refman/5.7/en/rewriter-query-rewrite-plugin.html