関数の揮発性

Spanner では、組み込み SQL 関数やユーザー定義関数などの関数は、揮発性によって分類されます。揮発性のカテゴリは、同じ引数で関数を呼び出したときに同じ結果が返されるかどうかを示します。この分類は、クエリ オプティマイザが関数を処理する方法や、生成列式やインデックス定義など、関数を使用できる場所に影響します。関数の揮発性を理解すると、Spanner でより予測可能でパフォーマンスの高いクエリとスキーマを作成できます。

揮発性のカテゴリは 3 つあり、 PostgreSQLなどのシステムのコンセプトと似ています。

  • 不変: 同じ引数値を指定して呼び出したときに同じ結果を返す関数は、不変です。 この動作は、関数の結果が入力引数のみに依存し、データベースの状態、セッション設定、外部要因に依存しないことを意味します。ほとんどの数学関数は不変です。次の関数はその例です。

    • ABS

    • LENGTH

    • CONCATLOWER などの文字列操作関数

    • 明示的な入力を使用する日付と時刻の書式設定関数

    タイムゾーンなど、実行時に構成可能な設定に依存する関数は、データベースやセッションの構成によって結果が異なる可能性があるため、不変ではありません。

  • 安定: 1 つのステートメントの実行内で 同じ引数値を指定すると同じ結果を返す関数は、安定しています。ただし、SQL ステートメントが異なると、結果が異なる場合があります。 CURRENT_TIMESTAMPCURRENT_DATE などの時間ベースの関数は安定しています。たとえば、同じ SELECT ステートメント内で CURRENT_TIMESTAMP を複数回呼び出すと、同じタイムスタンプが生成されますが、後続のステートメントでは異なるタイムスタンプが生成される可能性があります。

  • 揮発性: 同じ引数を使用しても、 1 つのステートメントの実行内で値が変化する可能性がある関数は、揮発性です。たとえば、一意の ID を生成する GENERATE_UUID 関数は揮発性です。

揮発性の影響

関数の揮発性カテゴリによって、データベース スキーマで使用できる場所と、関数を含むクエリの最適化方法が決まります。

  • 生成列: 生成列を定義する式は不変である必要があります。これにより、保存される値が、行の他の列に基づいて決定論的になります。不変ではない式で生成列を定義しようとすると、Spanner はエラーを生成します。

  • インデックス作成: 揮発性関数を含む式にインデックスを作成することはできません。揮発性関数を含む式にインデックスを作成しようとすると、Spanner はエラーを生成します。

  • クエリの最適化: クエリ オプティマイザは、揮発性情報を使用して最適化を行います。たとえば、 クエリ オプティマイザは、定数引数を使用して不変関数を呼び出す処理を 事前に計算します。オプティマイザは、多くの場合、1 つのステートメントの実行の範囲内で安定した関数の結果をキャッシュに保存します。