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` = ?))