SQL ビューから作成されたグラフの概要

このドキュメントでは、SQL ビューを使用してグラフを作成するメリットについて説明します。このドキュメントでは、ビューを使用してグラフを作成するメリット、要件、考慮事項について説明します。これらの情報を参考にして、テーブルまたはビューを使用してグラフを作成するかどうかを決定してください。

ビューからグラフを作成する方法については、SQL ビューからプロパティ グラフを作成するをご覧ください。

テーブルではなくビューを使用してグラフを作成するメリット

SQL ビューは、SQL クエリによって定義される仮想テーブルです。Spanner では、ビューを参照するクエリが実行されるたびに、ビューを定義するクエリが実行されます。Spanner ビューは、ビューを定義するクエリの結果をデータ ストレージに実際のテーブルとして格納しないため、マテリアライズド ビューではありません。詳細については、ビューの概要をご覧ください。SQL ビューからグラフ要素を作成できますが、グラフをクエリするビューは作成できません。

ビューは、テーブルとグラフスキーマ間の抽象化レイヤとして、テーブルを使用してグラフを作成する場合には利用できないいくつかの利点を提供します。

ビューを使用してグラフを作成するための要件

ビューを使用してグラフ要素を作成する場合は、次の要件に従う必要があります。

グラフ要素を指定する場合は、KEY 句を使用します。

ビューを使用してノードまたはエッジ要素を作成する場合は、グラフ要素を一意に識別する列を明示的に定義する必要があります。これを行うには、ノードまたはエッジ要素の定義で KEY 句を使用します。グラフ要素の作成時に KEY 句を使用する方法については、このドキュメントと SQL ビューから Spanner Graph を作成するのコード例をご覧ください。

ノードキーとエッジキーの一意性を確保する

プロパティ グラフのすべてのノードとエッジには、一意のキーが必要です。ビューを使用してグラフ要素を定義する場合は、要素キーの一意性を検証する方法を選択できます。

  • 厳格なキー検証(デフォルト): Spanner は、ビューがサポートされているクエリパターンに従っていることを検証して、キーの一意性を確保します。
  • キー検証が無効(任意の SQL クエリ): validate_element_key_uniqueness = false グラフ オプションを設定すると、任意の SQL クエリを使用できます。このモードでは、要素キーが一意であることを確認する必要があります。

厳格な鍵検証(デフォルト)

デフォルトでは、Spanner は、ノードテーブルまたはエッジテーブルを定義するビューが次のいずれかのパターンに従っていることを確認して、各ノードまたはエッジが一意であることを確認します。

  • パターン 1: ビューで単一のテーブルの主キーを使用する。

  • パターン 2: ビューで GROUP BY 句または SELECT DISTINCT 句が使用されている。

WHERE、HAVING、ORDER BY、LIMIT、TABLESAMPLE などの他の SQL 演算子をこれらのパターンと組み合わせて使用できます。これらの演算子は結果をフィルタリングまたは並べ替えますが、パターンが提供する基盤となる一意性の保証は変更しません。

パターン 1: 単一のテーブルの主キーを使用する

このパターンでは、ビューは単一のテーブルから選択し、グラフ定義の KEY 句はベーステーブルの主キー列と一致します。このため、ビューによって生成される各ノード行またはエッジ行は一意です。

たとえば、次の例では、Account テーブルから行のサブセットを選択します。グラフ KEY(account_id) は Account テーブルの主キーと一致します。これにより、ビューによって生成される各行が一意になります。

-- Table has PRIMARY KEY(account_id).
CREATE TABLE Account (
  account_id INT64 NOT NULL,
  customer_id INT64 NOT NULL,
  account_type STRING(MAX),
  balance INT64
) PRIMARY KEY(account_id);

-- Pattern 1: View uses the primary key from a single table.
CREATE VIEW SavingAccount
  SQL SECURITY INVOKER AS
    SELECT accnt.account_id, accnt.customer_id, accnt.balance
    FROM Account accnt
    WHERE accnt.account_type = 'saving';

CREATE PROPERTY GRAPH SavingAccountGraph
  NODE TABLES (
    -- The element KEY(account_id) matches the table's primary key.
    SavingAccount KEY(account_id)
  );

パターン 2: GROUP BY 句または SELECT DISTINCT 句を使用する

このパターンでは、ビューのクエリで GROUP BY 句または SELECT DISTINCT 句を使用します。KEY 句の列は、これらの句が一意性を定義するために使用する列と一致する必要があります。

  • GROUP BY の場合: KEY 句の列は、GROUP BY 句のすべての列と一致する必要があります。

  • SELECT DISTINCT の場合: KEY 句の列は、SELECT DISTINCT リストの列と一致する必要があります。

GROUP BY を使用する例:

CREATE TABLE Customer (
  customer_id INT64,
  name STRING(MAX)
) PRIMARY KEY (customer_id);

CREATE TABLE SaleOrder (
  order_id INT64,
  customer_id INT64,
  amount INT64
) PRIMARY KEY (order_id);

CREATE VIEW CustomerOrder
  SQL SECURITY INVOKER AS
    SELECT
      s.order_id,
      ANY_VALUE(c.customer_id) AS customer_id,
      ANY_VALUE(c.name) AS customer_name
    FROM Customer c JOIN SaleOrder s ON c.customer_id = s.customer_id
    GROUP BY s.order_id;

CREATE PROPERTY GRAPH OrderGraph
  NODE TABLES (
    -- The KEY(order_id) matches the GROUP BY column in view definition.
    CustomerOrder KEY(order_id)
  );

SELECT DISTINCT を使用する例:

CREATE TABLE SaleOrder (
  order_id INT64,
  customer_id INT64,
  amount INT64
) PRIMARY KEY (order_id);

CREATE VIEW KeyCustomer SQL SECURITY INVOKER AS
  SELECT DISTINCT s.customer_id, s.amount
  FROM SaleOrder s
  WHERE s.amount > 1000;

CREATE PROPERTY GRAPH KeyCustomersGraph
  NODE TABLES (
    -- The KEY(customer_id, amount) matches the DISTINCT columns.
    KeyCustomer KEY(customer_id, amount)
  );

キー検証を無効化(任意の SQL クエリ)

ビューで、パターン 1 またはパターン 2 に従わないクエリ(GROUP BY 句または SELECT DISTINCT 句なしでテーブルを結合するクエリなど)を使用している場合は、グラフ オプション validate_element_key_uniqueness = false を設定して、要素キーの検証を無効にできます。

デフォルトでは、validate_element_key_uniqueness は true となっています。false に設定すると、Spanner はスキーマの作成時にビューのクエリ定義を検証しません。ビューでは任意の SQL クエリを使用できますが、KEY 句で指定された列に、すべてのノード行またはエッジ行の一意の値が含まれている必要があります。

次の例では、GROUP BY 句なしで Customer テーブルと SaleOrder テーブルを結合する CustomerOrderTrusted という名前のビューを定義します。各販売注文は一意であるため、SaleOrder と Customer を結合すると、ビューの結果で order_id の一意性が維持されます。ただし、クエリは JOIN を使用し、パターン 1 またはパターン 2 に従っていないため、Spanner は一意性を構文的に検証できません。

KEY(order_id) を指定し、OPTIONS 句で validate_element_key_uniqueness = false を設定すると、ビュークエリを変更せずにプロパティ グラフを定義できます。

-- View uses a JOIN without GROUP BY or DISTINCT.
CREATE VIEW CustomerOrderTrusted
  SQL SECURITY INVOKER AS
    SELECT
      s.order_id,
      c.customer_id,
      c.name AS customer_name
    FROM Customer c JOIN SaleOrder s ON c.customer_id = s.customer_id;

-- Property graph disables element key uniqueness validation.
CREATE PROPERTY GRAPH OrderGraphTrusted
  NODE TABLES (
    CustomerOrderTrusted
      KEY(order_id)
      LABEL CustomerOrder PROPERTIES(
        order_id,
        customer_id,
        customer_name)
  ) OPTIONS (validate_element_key_uniqueness = false);

ビューでリモート関数を使用する場合は、揮発性列を有効にする

CREATE PROPERTY GRAPH ステートメントの OPTIONS 句で allow_view_with_volatile_column = true を設定することで、リモート関数(LANGUAGE REMOTE)を呼び出すビューにプロパティ グラフを定義できます。

デフォルトでは、Spanner では、揮発性列(allow_view_with_volatile_column = false)を含むビューにプロパティ グラフを定義できません。ビュー列の式が揮発性関数を呼び出す場合、その列は揮発性です。リモート関数(NOT DETERMINISTIC)など、同じ引数を持つ単一のステートメント実行内でも戻り値が変更される可能性がある場合、関数は揮発性です。JOIN 条件や WHERE 句など、ビューの定義本文に揮発性がある場合、ビュー内のすべての投影列も揮発性になります。コード例については、リモート関数を使用してプロパティを計算するをご覧ください。

ビューを使用する際の考慮事項

ビューを使用してグラフ要素を定義する場合、次のことが効果的なグラフの設計と実装に役立ちます。

プロパティ グラフのクエリ パフォーマンス

データ変換(GROUP BY、UNNEST、JOIN オペレーションなど)を実行するビューでグラフ要素を定義する場合は、ユースケースのクエリ パフォーマンスを慎重に評価してください。Spanner は、クエリが要素パターン マッチングを実行するたびに、ビューのクエリ定義を実行します。

グラフスキーマの最適化

ビューを使用してグラフ要素を定義すると、テーブルを使用してグラフ要素を定義する場合よりも、グラフスキーマの最適化の効果が低下する可能性があります。

単一のテーブルの主キーを投影するビュー

ビューが単一のベーステーブルからのプロジェクションである場合、その基になるテーブルに対する最適化はグラフクエリでも有効です。たとえば、ベーステーブルに次の手法を適用すると、そのようなビューで定義されたグラフ要素に同様のパフォーマンス上のメリットが得られます。

GROUP BY 句または DISTINCT 句で定義されたビュー

GROUP BY、SELECT DISTINCT、その他の複雑な変換などの集計を実行するビューは、基盤となるテーブル構造との直接的な関係を失います。このため、ベーステーブルのスキーマ最適化を行っても、ビューを操作するグラフクエリで同じパフォーマンス上のメリットが得られない場合があります。ビューで複雑な集計を行う場合は、ユースケースのクエリ パフォーマンスを慎重に評価してください。

ビューベースのグラフを使用したデータ変更

ビューはマテリアライズされません。つまり、ビューを定義するクエリの結果は、データ ストレージにテーブルとして保存されず、読み取り専用になります。このため、ビューから作成されたグラフでノードやエッジを挿入、更新、削除するには、ビューの作成に使用されたテーブルのデータを変更します。

データの完全性を確保するためのグラフのエラー処理

ビューを使用してグラフ要素を定義する場合は、基になるベーステーブルにデータの完全性を適用します(たとえば、データ型を適用します)。そうしないと、ベーステーブルのデータが無効になり、ビューベースのグラフに対するクエリが実行時に失敗する可能性があります。

たとえば、スキーマレスから正式なグラフに移行する場合は、CHECK 制約を使用して、ベーステーブル(GraphNode と GraphEdge)のデータを検証します。次のコードは、JSON プロパティ内でこれらの制約を適用して、ソースでのデータの完全性を確保し、ランタイム クエリエラーを防止します。

-- Enforce that the 'name' property exists for nodes with the 'person' label.
ALTER TABLE GraphNode
ADD CONSTRAINT NameMustExistForPersonConstraint
CHECK (IF(label = 'person', properties.name IS NOT NULL, TRUE));

-- Enforce that the 'name' property is a string for nodes with the 'person' label.
ALTER TABLE GraphNode
ADD CONSTRAINT PersonNameMustBeStringTypeConstraint
CHECK (IF(label = 'person', JSON_TYPE(properties.name) = 'string', TRUE));

次のステップ