パフォーマンスとデータ整合性を両立させる MySQL 関数の DETERMINISTIC、NO SQL、READS SQL DATA 属性
MySQL 関数の DETERMINISTIC、NO SQL、READS SQL DATA 属性について
MySQL でストアドファンクションを作成する際、DETERMINISTIC
、NO SQL
、READS SQL DATA
のいずれかの属性を指定する必要があります。これらの属性は、関数がどのように動作し、バイナリログに記録されるかを決定します。
各属性の詳細
DETERMINISTIC
- 関数が常に同じ結果を返すことを意味します。つまり、同じ入力パラメータを与えれば、常に同じ出力を生成します。
- 外部ソース (ファイルシステム、ネットワークなど) からデータを読み取ったり、ランダム値を生成したりする関数は、DETERMINISTIC 属性を持つことができません。
- DETERMINISTIC 属性を持つ関数は、バイナリログに確実に記録されます。
NO SQL
- 関数が SQL データを読み取ったり書き換えたりしないことを意味します。
- 許可されるのは、計算や文字列操作などの操作のみです。
- NO SQL 属性を持つ関数は、バイナリログに記録されません。
READS SQL DATA
- データの書き換えは許可されません。
- READS SQL DATA 属性を持つ関数は、バイナリログに記録されるかどうかは、
log_bin_trust_function_creators
サーバ変数の設定によって異なります。
設定方法
- 関数作成時に、
DETERMINISTIC
、NO SQL
、READS SQL DATA
属性を指定できます。 - 例:
CREATE FUNCTION my_function() RETURNS INT
DETERMINISTIC
BEGIN
RETURN 1 + 1;
END;
注意事項
- DETERMINISTIC 属性を持つ関数は、常に同じ結果を返す必要があるため、外部ソースからのデータ読み取りやランダム値生成は避けてください。
- NO SQL 属性を持つ関数は、SQL データへのアクセスを行わないため、データの整合性に関する問題が発生する可能性があります。
- READS SQL DATA 属性を持つ関数は、データを読み取るため、パフォーマンスに影響を与える可能性があります。
補足
- 上記の属性は、MySQL 5.6 以降で利用可能です。
- バイナリログは、データベースの復元やレプリケーションに使用されます。
CREATE FUNCTION my_function(x INT) RETURNS INT
DETERMINISTIC
BEGIN
RETURN x + 1;
END;
SELECT my_function(1); -- 2 を返す
SELECT my_function(2); -- 3 を返す
CREATE FUNCTION my_function() RETURNS VARCHAR(255)
NO SQL
BEGIN
RETURN CONCAT('Hello, ', CURRENT_USER());
END;
SELECT my_function(); -- 'Hello, ユーザ名' を返す
CREATE FUNCTION my_function(x INT) RETURNS INT
READS SQL DATA
BEGIN
RETURN (SELECT COUNT(*) FROM table WHERE id = x);
END;
SELECT my_function(1); -- テーブル 'table' の id が 1 のレコードの数を返す
これらのサンプルコードは、各属性の動作を理解するのに役立ちます。
DETERMINISTIC
属性: MD5 ハッシュ関数などNO SQL
属性: 文字列操作関数など
MySQL 関数の DETERMINISTIC、NO SQL、READS SQL DATA 属性の代替方法
-
代替方法として、以下の方法が考えられます。
- 関数内部でランダム値生成や外部ソースからのデータ読み取りを行わないようにする。
- 関数の実行前に、必要なデータをすべてキャッシュする。
-
- 関数内部で SQL データへのアクセスを行わないようにする。
- データベース接続を必要としない別の言語で関数を記述する。
-
- 関数内部で読み取るデータを最小限に抑える。
- 読み取ったデータをキャッシュして再利用する。
その他の代替方法
- 状況によっては、別の関数やストアドプロシージャを使用することで、これらの属性を回避できる場合があります。
- 例えば、
RAND()
関数ではなく、UUID()
関数を使用してランダム値を生成することができます。
以下の点を考慮する必要があります。
- 関数の目的
- パフォーマンス要件
- データ整合性
mysql database deterministic