インデックスと地域別パーティショニング

Spanner には、クエリのパフォーマンスを向上させるためのさまざまな種類のインデックスが用意されています。スキーマとクエリ パターンに適切なインデックス タイプを選択することは、特に地理的パーティショニングを使用するデータベースでは非常に重要です。このページでは、さまざまなインデックス タイプのメリットと、地域別パーティショニングで Spanner インデックスを選択して使用するためのベスト プラクティスについて説明します。

インデックスのタイプ

Spanner は、グローバル インデックス、ローカル インデックス、リモート インデックスをサポートしています。タイプごとにパフォーマンス特性とユースケースが異なります。地理的パーティショニングされたデータベースでは、これらのインデックス タイプを理解することが重要です。適切なインデックスを選択すると、データベース スキーマとクエリを最適化できます。これにより、地域パーティショニングされたデータベースのレイテンシを大幅に改善できます。地域別パーティション分割を使用しないデータベースの場合、これらのインデックス タイプはすべてデフォルトの配置に保存され、パフォーマンス特性が類似しているため、これらのインデックス タイプを理解することはあまり重要ではありません。

グローバル インデックス

グローバル インデックスは、Spanner のデフォルトのインデックス タイプです。インデックス データはデフォルトのパーティションに保存されます。このパーティションは、テーブルのデータと同じ場所に配置されない可能性があります。地理パーティション分割テーブルにグローバル インデックスを作成すると、インデックス付き列を含む書き込みの書き込みレイテンシが大幅に増加する可能性があります。特に、インデックスのデフォルト パーティションの書き込みクォーラムが、書き込み先のテーブル行の書き込みクォーラムから遠い場合は、その可能性が高くなります。グローバル インデックスの読み取りレイテンシを軽減するには、読み取りリース リージョンまたはステイル読み取りとともに、近くの読み取り専用レプリカを使用します。

グローバル インデックスには次の特徴があります。

  • これらは、テーブル全体のスキャンが必要になるクエリを高速化し、場所に関係なくすべてのテーブル行で一意性を適用します。
  • データベース全体で一意の値を必要とする列に適しています。
  • インデックス付き列でフィルタリングまたは並べ替えを行うクエリを高速化します。

グローバル一意インデックスの例を次に示します。

CREATE UNIQUE INDEX idx_customer_email ON customer(email);

ローカル インデックス

ローカル インデックスは、インデックス付きテーブルの親階層にインターリーブされます。主キー列の名前と型は、インデックス付きテーブルと一致している必要があります。

ローカル インデックスには次の特徴があります。

  • インデックス データは、インデックスが作成されたデータと同じパーティションに保存されます。書き込みレイテンシは、デフォルトのプレースメントの書き込みクォーラムではなく、特定のプレースメントの書き込みクォーラムの影響を受けます。

  • インデックスとテーブル データが同じ配置にコロケーションされているため、特定のキー接頭辞を対象とするクエリのレイテンシが最小になります。

ローカル インデックスを作成するには、インデックスを親テーブルにインターリーブします。UNIQUE ローカル インデックスを使用する場合、一意性はテーブル全体ではなく、特定の親行内でのみ適用されます。

次に、テーブル customer にローカル インデックスを作成し、親テーブル locations にインターリーブする例を示します。

GoogleSQL

-- Create locations placement table
CREATE TABLE locations (
  location STRING(MAX) NOT NULL PLACEMENT KEY,
) PRIMARY KEY(location);

-- Create customer table interleaved in the locations table
CREATE TABLE customer (
  location STRING(MAX) NOT NULL,
  customerId  INT64 NOT NULL,
  email STRING(MAX),
  webcookie STRING(64),
) PRIMARY KEY(location, customerId), INTERLEAVE IN PARENT locations;

-- Create a local index on the interleaved customer table
CREATE INDEX idx_customer_email_local ON customer(location, email),
INTERLEAVE IN locations;

PostgreSQL

-- Create locations placement table
CREATE TABLE locations (
  location varchar NOT NULL PLACEMENT KEY PRIMARY KEY
);

-- Create customer table interleaved in the locations table
CREATE TABLE customer (
  location varchar NOT NULL,
  customerId  BIGINT NOT NULL,
  email varchar(1024),
  webcookie varchar(64),
  PRIMARY KEY(location, customerId)
) INTERLEAVE IN PARENT locations;

-- Create a local index on the interleaved customer table
CREATE INDEX idx_customer_email_local ON customer(location, email)
INTERLEAVE IN locations;

読み取り / 書き込みトランザクションでデータをクエリする場合は、クエリでインデックス登録されたテーブルの主キーの接頭辞を指定する必要があります。そうしないと、クエリでテーブル全体のスキャンが必要になる可能性があります。次に例を示します。

GoogleSQL

-- The location (the index key prefix) must be specified
SELECT *
FROM customer
WHERE location= @location AND email= @email;

PostgreSQL

-- The location (the index key prefix) must be specified
SELECT *
FROM customer
WHERE location= @location AND email= @email;

ロケーションの指定を必要としない最適化については、ローカルまたはリモート インデックスでグローバル一意インデックスを使用するをご覧ください。

ローカル インデックスは、プレースメント テーブルがエンティティ ベースで、特定のエンティティまたはサブエンティティ内のデータをインデックス登録する場合にも便利です。次に例を示します。

GoogleSQL

-- Create entity based customer placement table
CREATE TABLE customer (
  customerId INT64 NOT NULL,
  email STRING(MAX),
  webcookie STRING(64),
  location STRING(MAX) NOT NULL PLACEMENT KEY
) PRIMARY KEY(customerId);

-- Create customerOrders child table
CREATE TABLE customerOrders (
  customerId INT64 NOT NULL,
  orderId INT64 NOT NULL,
  orderName STRING(MAX) NOT NULL
) PRIMARY KEY(customerId, orderId), INTERLEAVE IN PARENT customer;

-- Create a local index on the interleaved child table
CREATE INDEX idx_order_local ON customerOrders(customerId, orderName),
INTERLEAVE IN customer;

PostgreSQL

-- Create entity based customer placement table
CREATE TABLE customer (
  customerId BIGINT NOT NULL PRIMARY KEY,
  email varchar(1024),
  webcookie varchar(64),
  location varchar NOT NULL PLACEMENT KEY
);

-- Create customerOrders child table
CREATE TABLE customerOrders (
  customerId BIGINT NOT NULL,
  orderId BIGINT NOT NULL,
  orderName varchar(1024) NOT NULL,
  PRIMARY KEY(customerId, orderId)
) INTERLEAVE IN PARENT customer;

-- Create a local index on the interleaved child table
CREATE INDEX idx_order_local ON customerOrders(customerId, orderName)
INTERLEAVE IN customer;

リモート インデックス

リモート インデックスは、インデックス付きテーブルのインターリーブ階層で祖先ではないテーブルの下にインデックス データをインターリーブします。主キーの型は、対応するインデックス列の型と一致する必要がありますが、名前は異なってもかまいません。

地理的パーティショニングを使用すると、自動管理のルート配置テーブルの下にのみリモート インデックスをインターリーブできます。このテーブルには、データベース内のプレースメントごとに 1 行が含まれます。

リモート インデックスには次の特徴があります。

  • これらは、テーブルの主キーが配置キーを使用して接頭辞を付加されていないが、配置キーに従ってインデックスのパーティションを地理的に配置する場合に特に便利です。
  • 配置テーブルの列のインデックス作成のみをサポートし、インターリーブされた子テーブルの列はサポートしていません。

地域別パーティション分割でリモート インデックスを使用するには、ALTER DATABASE DDL ステートメントで auto_managed_root_placement_table_name オプションを設定して、ルート プレースメント テーブルを作成します。

  1. ALTER DATABASE DDL ステートメントを使用して、ルート配置テーブルを作成します。

    GoogleSQL

    ALTER DATABASE DATABASE_NAME SET OPTIONS
      (auto_managed_root_placement_table_name="TABLE_NAME");
    

    次のように置き換えます。

    • DATABASE_NAME: データベースの名前。
    • TABLE_NAME: 作成するテーブルの名前。root_placement_table という名前を使用することをおすすめします。

    たとえば、次のコマンドは root_placement_table というテーブルを作成します。

    ALTER DATABASE example_db SET OPTIONS
      (auto_managed_root_placement_table_name='root_placement_table');
    

    ルート プレースメント テーブルを作成すると、Spanner は内部テーブルを作成し、プレースメントの作成または削除時に行を自動的に挿入および削除します。次の例は、Spanner によって作成されたシステム定義のプレースメント テーブルの例です。この例では、テーブル名が root_placement_table に設定されています。(この例は実行しないでください)。

    // Automatically generated after you run the previous example.
    // Don't put this in your schema explicitly.
    CREATE TABLE root_placement_table (
    location STRING(MAX) NOT NULL PLACEMENT KEY
    ) PRIMARY KEY(location);
    

    PostgreSQL

    ALTER DATABASE DATABASE_NAME SET
      spanner.auto_managed_root_placement_table_name='TABLE_NAME';
    

    次のように置き換えます。

    • DATABASE_NAME: データベースの名前。
    • TABLE_NAME: 作成するテーブルの名前。

    たとえば、インターリーブ ルートとして使用される root_placement_table テーブルを作成するには、次のコマンドを実行します。

    ALTER DATABASE example_db SET
      spanner.auto_managed_root_placement_table_name='root_placement_table';
    

    ルート プレースメント テーブルを作成すると、Spanner は内部テーブルを作成し、プレースメントの作成または削除時に行を自動的に挿入および削除します。次の例は、Spanner によって作成されたシステム定義のプレースメント テーブルの例です。この例では、テーブル名が root_placement_table に設定されています。(この例は実行しないでください)。

    // Automatically generated after you run the previous example.
    // Don't put this in your schema explicitly.
    CREATE TABLE root_placement_table (
      location varchar NOT NULL PLACEMENT KEY,
      PRIMARY KEY (location)
    );
    
  2. 自動管理の root_placement_table テーブルの下にインターリーブされたリモート インデックスを作成します。

    GoogleSQL

    -- Create a customer table with a primary key that is not the location
    CREATE TABLE customer (
      customerId INT64 NOT NULL ,
      email STRING(MAX),
      webcookie STRING(64),
      location STRING(MAX) NOT NULL PLACEMENT KEY,
    ) PRIMARY KEY(customerId);
    
    -- Create a remote index on the customer table
    CREATE INDEX idx_customer_email_remote ON customer(location, email),
    INTERLEAVE IN root_placement_table;
    

    PostgreSQL

    -- Create a customer table with a primary key that is not the location
    CREATE TABLE customer (
      customerId BIGINT NOT NULL PRIMARY KEY,
      email varchar(1024),
      webcookie varchar(64),
      location varchar NOT NULL PLACEMENT KEY
    );
    
    -- Creates a remote index on the customer table
    CREATE INDEX idx_customer_email_remote ON customer(location, email)
    INTERLEAVE IN root_placement_table;
    
  3. 読み取り / 書き込みトランザクションでデータをクエリする場合は、テーブル全体のスキャンが不要になるように、クエリ述語でインデックスのキー接頭辞を指定します。次に例を示します。

    GoogleSQL

    -- Specify the location (the index key prefix) in query
    SELECT *
    FROM customer
    WHERE location= @location AND email= @email;
    

    ロケーションの指定を必要としない最適化については、ローカル インデックスまたはリモート インデックスを使用したグローバル一意インデックスのセクションをご覧ください。

    PostgreSQL

    -- Specify the location (the index key prefix) in query
    SELECT *
    FROM customer
    WHERE location= @location AND email= @email;
    

    ロケーションの指定を必要としない最適化については、ローカル インデックスまたはリモート インデックスを使用したグローバル一意インデックスのセクションをご覧ください。

グローバル一意インデックスの最適化

グローバル一意インデックスを使用すると、Spanner は次のユースケースでヒューリスティック ベースの最適化によりクエリ レイテンシの改善をトリガーする可能性があります。

  • ローカル インデックスまたはリモート インデックスでグローバル一意インデックスを使用する場合
  • 部分主キーでグローバル一意インデックスを使用する場合

以降のセクションでは、各ユースケースで Spanner が最適化を適用する方法について説明します。

ローカル インデックスまたはリモート インデックスを含むグローバル一意インデックス

ローカルクエリのレイテンシを短縮するため、Spanner はグローバル一意インデックスがローカル インデックスまたはリモート インデックスと組み合わされたときに、ヒューリスティック ベースの最適化を開始することがあります。

この最適化により、地理的パーティショニングされたデータの場所が指定されていない場合でも、クライアントの場所と同じ場所に配置されていると推測し、グローバル インデックスのデフォルト パーティションをバイパスするか、フィルタされたテーブル全体のスキャンを不要にすることで、リージョン内のクエリのレイテンシを最小限に抑えます。このようなアプローチは、クライアントが主に独自のリージョンに保存されているデータにアクセスする場合に特に有効です。

リージョン内のクエリ レイテンシが主な懸念事項であり、書き込みレイテンシの増加を許容できる場合は、さまざまなインデックス タイプを組み合わせて使用すると効果的です。さまざまなインデックス タイプを組み合わせると、クエリでロケーションを指定していない場合でも、リージョン内クエリのパフォーマンスが向上します。

この最適化では、同じ列にグローバル一意インデックスと対応するローカルまたはリモート インデックスを作成する必要があります。インデックス登録されたデータはグローバルに一意である必要があります。次の条件に該当する場合、Spanner はこの最適化をクエリに適用します。

  • 主キーの接頭辞がわからず、データの場所を指定していない。
  • リクエストは、ローカルまたはリモート インデックス シャードを含むデータの配置のデフォルト リーダーと同じリージョンから送信されます。

Spanner は、次の方法で最適化を適用します。

  • 最適化がトリガーされ、ローカル配置で行が見つかった場合: グローバル一意インデックスが指定されているため、Spanner は他のロケーションを検索する必要はありません。クエリにリージョン内レイテンシがあります。
  • 最初のロケーション検索で行が返されない場合: これは、リージョン内クエリではないことを示します。Spanner はグローバル インデックスの使用にフォールバックします。

次の例では、グローバル一意インデックスとローカル インデックスを作成します。

GoogleSQL

CREATE UNIQUE INDEX idx_customer_email ON customer(email);
CREATE INDEX idx_customer_email_local ON customer(location, email), INTERLEAVE IN locations;

PostgreSQL

CREATE UNIQUE INDEX idx_customer_email ON customer(email);
CREATE INDEX idx_customer_email_local ON customer(location, email) INTERLEAVE IN locations;

次の例では、グローバル一意インデックスとリモート インデックスを作成します。

GoogleSQL

CREATE UNIQUE INDEX idx_customer_email ON customer(email);
CREATE INDEX idx_customer_email_remote ON customer(location, email), INTERLEAVE IN root_placement_table;

PostgreSQL

CREATE UNIQUE INDEX idx_customer_email ON customer(email);
CREATE INDEX idx_customer_email_remote ON customer(location, email) INTERLEAVE IN root_placement_table;

上記のインデックスの例に基づくと、次のクエリ例にはリージョン内レイテンシがあります。

GoogleSQL

SELECT *
FROM customer
WHERE email= @email;

PostgreSQL

SELECT *
FROM customer
WHERE email= @email;

部分主キーのグローバル一意インデックス

Spanner は、部分的な主キーでグローバル一意インデックスを使用する場合、ローカル インデックスまたはリモート インデックスでグローバル一意インデックスを使用するで説明されているものと同様の最適化を適用できます。

次の例では、親テーブル locations にインターリーブされた customer を作成し、customerId 列にグローバル一意インデックスを作成します。

GoogleSQL

-- Create locations placement table
CREATE TABLE locations (
location STRING(MAX) NOT NULL PLACEMENT KEY,
) PRIMARY KEY(location);

-- Create customer table interleaved in the locations table
CREATE TABLE customer (
  location STRING(MAX) NOT NULL,
  customerId  INT64 NOT NULL,
  email STRING(MAX),
  webcookie STRING(64),
) PRIMARY KEY(location, customerId), INTERLEAVE IN PARENT locations;

-- Create global unique index on customerId column
CREATE UNIQUE INDEX idx_customer_customerid ON customer(customerId);

PostgreSQL

-- Create locations placement table
CREATE TABLE locations (
  location varchar NOT NULL PLACEMENT KEY PRIMARY KEY
);

-- Create customer table interleaved in the locations table
CREATE TABLE customer (
  location varchar NOT NULL,
  customerId  BIGINT NOT NULL,
  email varchar(1024),
  webcookie varchar(64),
  PRIMARY KEY(location, customerId)
) INTERLEAVE IN PARENT locations;

-- Create global unique index on customerId column
CREATE UNIQUE INDEX idx_customer_customerid ON customer(customerId);

最適化は、次のようなクエリに適用されます。

GoogleSQL

SELECT * FROM customer WHERE customerId= @customerId;

PostgreSQL

SELECT * FROM customer WHERE customerId= @customerId;

グローバル一意インデックスを作成しない場合、このクエリではテーブルのフルスキャンが必要になることがあります。グローバル一意インデックスを使用していない場合は、クエリにロケーション フィルタを追加して、クエリのレイテンシを短縮する必要があります。

GoogleSQL

SELECT * FROM customer WHERE location = @location AND customerId= @customerId;

PostgreSQL

SELECT * FROM customer WHERE location = @location AND customerId= @customerId;

最適なレイテンシを実現するためのインデックス タイプの選択に関する一般的なガイドライン

選択するインデックスのタイプは、クエリのレイテンシに直接影響します。インデックス データのテーブルデータに対する相対的な位置は、地理的パーティショニングされたワークロードのパフォーマンスに影響する主な要因です。

このセクションでは、グローバル インデックス、ローカル インデックス、リモート インデックスの選択方法について説明します。

グローバル インデックスを選択する場合

ワークロードで関連する読み取り / 書き込みレイテンシを許容できる場合、またはインデックス付き列でグローバル一意性を強制する必要がある場合は、グローバル インデックスを使用します。

グローバル インデックスを選択する際は、次の点を考慮してください。

  • クライアントとデフォルトの書き込みクォーラムのリーダー間の距離と、クォーラムのデフォルトのレイテンシによって、書き込みレイテンシの増加が決まります。この影響は、インデックス付き列を含むオペレーション(行の挿入やインデックス付き列の更新など)に限定されます。
  • 読み取り専用レプリカを追加するか、読み取りリースを使用すると、読み取りレイテンシの増加を軽減できます。
    • 地理的に近い場所に読み取り専用レプリカを追加すると、ステイル読み取りのレイテンシを短縮できます。
    • 読み取り専用レプリカを追加して読み取りリース リージョンを使用すると、強力な読み取りのレイテンシを短縮できます。読み取りリース リージョンを使用せずに読み取り専用レプリカを追加すると、強力な読み取りレイテンシは短縮されませんが、読み取りスループットは増加します。
    • Spanner は、常にリーダーからペシミスティック トランザクション読み取りを提供します。デフォルトのプレースメントにレプリカを追加しても、デフォルトのプレースメント内のデータのペシミスティック トランザクション読み取りには役立ちません。
  • グローバル インデックス(キーと保存値を含む)は、プレースメント レベルのデータ所在地を提供しないデフォルトのプレースメントに配置されます。詳細については、Spanner のデータ所在地の概要をご覧ください。

ローカル インデックスとリモート インデックスを選択する場合

ローカル インデックスとリモート インデックスを選択する際は、次の点を考慮してください。

  • ローカル インデックスとリモート インデックスは、配置ローカルの読み取りと書き込みのパフォーマンスを提供しますが、一意インデックス列のグローバルな一意性と順序付けのプロパティが犠牲になります。代わりに、ローカル インデックスとリモート インデックスは、インターリーブされている親行内のインデックス付き列の順序と一意性を提供します。
  • ローカル インデックスまたはリモート インデックスを使用する場合は、クエリ述語に配置場所を含める必要があります。ただし、Spanner がローカル配置場所を推測できるグローバル一意インデックスも存在する場合は除きます。そうしないと、クエリプランとパフォーマンスが非決定的になります。Spanner は、クエリ統計に基づいて、プレースメント ロケーション全体でベーステーブル スキャンまたはインデックスからの分散と収集を実行し、レイテンシを増加させる可能性があります。

ローカル インデックスまたはリモート インデックスを含むグローバル一意インデックスを選択する場合

グローバル一意インデックスとローカル インデックスまたはリモート インデックスの組み合わせを選択する場合は、次の点を考慮してください。

  • 特定のプレースメントの場所が不明な場合は、グローバル一意インデックスとローカル インデックスまたはリモート インデックスを組み合わせて使用します。このアプローチは、ほとんどのクエリが、リクエストされたデータの配置と同じリージョン内の地理的に配置されたサービスから発信される場合に最適です。
  • グローバル インデックスを書き込む場合、書き込みレイテンシにはデフォルトの書き込みクォーラム レイテンシが追加されます。
  • ヒューリスティック ベースの最適化では、クエリはローカル インデックス シャードによって処理され、ほとんどの場合、リージョン内のレイテンシが示されます。

特定のスキーマ設計のインデックスを選択するための詳細なガイドライン

最適なインデックス戦略は、テーブルの主キー構造とアプリケーションのクエリパターンによって異なります。このセクションでは、一般的な 3 つのスキーマ設計に適したインデックス タイプを選択するためのガイダンスを提供します。

  • エンティティを主キーとして使用するスキーマ
  • ロケーションを主キーとして使用するスキーマ
  • 位置情報関連の値を主キーとして使用するスキーマ

スキーマ設計: エンティティを主キーとして使用する

スキーマでエンティティを主キーとして使用する場合は、クエリでロケーションが指定されているかどうかに基づいてインデックス戦略を選択します。

customerID などのエンティティが主キーで、location などのキー以外の別の列がプレースメント キーである場合は、クエリ パターンに基づいてプレースメント テーブルのインデックス作成戦略を決定します。(エンティティの挿入レイテンシが問題になる場合は、エンティティをプレースメント テーブルの主キーとして使用しないでください)。

customerID などの特定のエンティティのデータをインデックス登録する場合は、ローカル インデックスを使用します。データはエンティティ内でインデックス登録され、並べ替えられますが、エンティティ間では並べ替えられません。たとえば、各顧客の注文を日付でインデックス登録する場合は、customerID ID の下にインターリーブされたローカル インデックスを作成できます。

クエリで常に場所がわかっている場合は、次のいずれかの戦略を使用します。

  • クエリでロケーションが常に認識され、グローバル一意性の適用が不要な場合は、リモート インデックスを使用します。これらのインデックスは、読み取りと書き込みの両方のオペレーションでリージョン内レイテンシを提供します。

    リモート インデックスは、インターリーブ テーブルの列ではなく、配置テーブルの列のインデックス作成のみをサポートします。リモート インデックスは、ルート プレースメント テーブルの下にインターリーブする必要があります。リモート インデックスは、プレースメントのすべてのプレースメント行のデータをインデックス登録します。

クエリで場所が常にわかっているわけではない場合は、次のいずれかの戦略を使用します。

  • インデックス付きの列がグローバルに一意である場合は、その一意性を強制するためにグローバル一意インデックスを作成します。

    低レイテンシの強整合性読み取りを実現するには、グローバル一意インデックスに加えてリモート インデックスを作成します。

    この組み合わせでは、書き込みでリージョン間のレイテンシが発生する可能性がありますが、指定されたロケーション(WHERE location= @location を使用)を含むクエリは、リモート インデックスを使用してリージョン内のレイテンシのメリットを享受します。ロケーションが指定されていないクエリの場合、Spanner は最初にローカルで検索し、ヒューリスティック ベースの最適化を使用します。データが見つからない場合は、グローバル インデックスにフォールバックします。

    読み取りリース リージョンを使用しており、データと同じリージョンにデフォルト パーティションの読み取り専用レプリカがある場合、リモート インデックスは不要です。読み取りリース リージョンは、グローバル インデックスの読み取りに対してすでに低レイテンシの強力な読み取りを提供しているためです。

  • クエリでロケーションが指定されておらず、インデックス付きの列がグローバルに一意でない場合は、グローバル(一意でない)インデックスのみを作成します。この場合、ローカル インデックスまたはリモート インデックスを追加しても読み取りレイテンシは改善されません。Spanner は、ローカル配置でデータが見つかった場合でも、別の配置に一致するデータがあるかどうかを判断できないためです。

スキーマ設計: ロケーションを主キーとして使用する

location 列が主キーと配置キーの両方として機能する場合、インデックスの選択は、クロス レイテンシの問題と、クエリで常にロケーションが指定されているかどうかによって決まります。

  • リージョン間のレイテンシが問題にならない場合や、グローバルな一意性が必要な場合は、グローバル インデックスを使用します。
  • リージョン間のレイテンシが懸念される場合は、クエリに常にロケーションが含まれ、Spanner でグローバル一意性を適用する必要がないため、ローカル インデックスのみを使用します。これにより、読み取りと書き込みの両方でローカル レイテンシが保証されます。
  • クロスリージョン クエリのレイテンシが懸念され、クロスリージョン書き込みのレイテンシは許容され、ロケーションが常にわかっているわけではない場合は、次の戦略が適用されます。

    条件 推奨事項
    グローバルに一意の部分主キーでクエリを実行する

    一意性を適用するために、一意のグローバル インデックスを作成します。主キーが同様の機能を実行するため、ローカル インデックスは必要ありません。ヒューリスティックに基づく最適化が適用されます。まず、Spanner はグローバル インデックスにフォールバックする前に、ローカル ロケーションで完全な主キーを確認します。

    例については、部分主キーのグローバル一意インデックスをご覧ください。

    非キーのグローバル一意列でクエリを実行する

    一意性を適用する一意のグローバル インデックスを作成します。

    リージョン内のレイテンシについては、次のシナリオが考えられます。

    • グローバル インデックスと同じ列にローカル インデックスを作成します。ヒューリスティックに基づく最適化が適用されます。グローバル インデックスとローカル インデックスを組み合わせることで、リージョン内の強力なクエリと古いクエリのレイテンシが短縮されます。一方、書き込みとクロスリージョン クエリおよび書き込みにはクロスリージョン レイテンシが発生します。
    • データと同じリージョンにデフォルト パーティションの読み取り / 書き込みレプリカまたは読み取り専用レプリカがある場合:
      • ステイル読み取りにリージョン内レイテンシが必要で、強力な読み取りには必要ない場合は、ローカル インデックスは必要ありません。ローカル レプリカはリージョン内のレイテンシを提供します。
      • 強力な読み取りにリージョン内レイテンシが必要な場合は、グローバル インデックスと同じ列にローカル インデックスを作成するか、読み取りリース リージョンを使用します。読み取りリース リージョンでは、書き込みレイテンシは増加しますが、強力な読み取りのレイテンシを短縮できます。
    インデックス付きの列がグローバルに一意ではない グローバル インデックスのみを作成します。ローカル インデックスでは、Spanner がすべてのロケーションを確認する必要があるため、読み取りレイテンシは改善されません。

これらの 3 つのシナリオがユースケースに当てはまらない場合は、アプリケーションの簡素さを犠牲にするか、位置情報を常に提供することで書き込みレイテンシを犠牲にする必要があります。

テーブルの主キーがロケーション関連の値に基づいていても、プレースメント キー列ではない場合(たとえば、国よりもプレースメントが少ない場合に country を主キーとして使用する場合)、グローバル インデックスまたはローカル インデックス(country 列の下にインターリーブ)を使用できます。ただし、このタイプの配置テーブルでインターリーブされたテーブルでは、リモート インデックスはサポートされていません。

このシナリオでは、ヒューリスティック ベースの最適化はローカル インデックスではサポートされていません。したがって、クエリで主キーの接頭辞が明示的に指定されている場合にのみ、ローカル レイテンシが実現します。