このページでは、読み取り専用トランザクションと読み書きトランザクションのコンテキスト外で Spanner で読み取りを行う方法を説明します。次のいずれかに該当する場合には、トランザクション ページをご覧ください。
1 つ以上の読み取り結果に応じて書き込みを行う必要がある場合、読み取り書き込みトランザクションの中で読み取りを実行する必要があります。詳細については、読み取り / 書き込みトランザクションをご覧ください。
データの一貫したビューを取得するため、複数の読み取り呼び出しを行う場合、読み取り専用トランザクションの中で読み取りを実行する必要があります。詳細については、読み取り / 書き込みトランザクションをご覧ください。
読み取りのタイプ
Spanner には以下の 2 種類の読み取り方法が用意されており、これによってデータを読み取るときのデータの新しさを指定できます。
- 「強力な読み取り」は、現在のタイムスタンプでの読み取りであり、この読み取りの開始時までに commit されたすべてのデータを確実に確認できます。Spanner のデフォルトでは、強力な読み取りを使用して読み取りリクエストが処理されます。
- 「ステイル読み取り」は、過去のタイムスタンプによる読み取りです。レイテンシの影響を受けやすいものの古いデータは許容できるアプリケーションの場合、ステイル読み取りを使用するとパフォーマンスが向上することがあります。
使用する読み取りのタイプを選択するには、読み取りリクエストでタイムスタンプ バウンドを設定します。タイムスタンプ バウンドを選択する際は、次のおすすめの方法を使用してください。
可能な限り、強力な読み取りを選択します。これは Spanner の読み取り(読み取り専用トランザクションを含む)の、デフォルトのタイムスタンプ バウンドです。強力な読み取りでは、どのレプリカが読み取りを受け取るかに関係なく、読み取りの開始前に commit されたすべてのトランザクションの結果を確実に確認できます。このため強力な読み取りでは、アプリケーション コードが簡略化され、アプリケーションの信頼性も向上します。Spanner の整合性プロパティについては、TrueTime と外部整合性をご覧ください。
レイテンシのために強力な読み取りが不可能な場合は、ステイル読み取りを使用します(bounded-staleness または exact-staleness)。読み取り結果をできるだけ新しいものにする必要がない場合は、これによってパフォーマンスを向上させることができます。レプリケーションのページで説明したように、良好なパフォーマンスを実現するために、ステイルネスの値として 15 秒を使用することは妥当です。
データベース ロールを使用してデータを読み取る
細かいアクセス制御ユーザーの場合は、SQL ステートメントとクエリを実行し、データベースで行オペレーションを実行するには、データベース ロールを選択する必要があります。ロールの選択は、ロールを変更するまでセッション全体を通じて維持されます。
データベース ロールを使用して読み取りを実行する方法については、細かいアクセス制御を使用してデータベースにアクセスするをご覧ください。
単一読み取りメソッド
Spanner では、次の場合にデータベースに対する単一読み取りメソッド(トランザクションのコンテキスト外での読み取りなど)を使用できます。
- SQL クエリ文として読み取りを実行する。あるいは、Spanner の読み取り API を使用する。
- 強力な読み取りを実行してテーブルから単一行または複数行を読み取る。
- ステイル読み取りを実行してテーブルから単一行または複数行を読み取る。
- セカンダリ インデックスの単一行または複数行を読み取る。
マルチリージョン インスタンス構成またはカスタム リージョン構成(オプションの読み取り専用リージョンを含む)内の特定のレプリカまたはリージョンに単一読み取りをルーティングする場合は、有向読み取りをご覧ください。
以降のセクションでは、Spanner クライアント ライブラリを使用して読み取りを行う方法について説明します。
クエリを実行する
以下では、データベースに SQL クエリを実行する方法を説明します。
GoogleSQL
C++
ExecuteQuery()
を使用して、データベースに SQL クエリを実行します。
C#
ExecuteReaderAsync()
を使用して、データベースに対するクエリを実行します。
Go
Client.Single().Query
を使用して、データベースに対するクエリを実行します。
Java
ReadContext.executeQuery
を使用して、データベースに対するクエリを実行します。
Node.js
Database.run
を使用して、データベースに対するクエリを実行します。
PHP
Database::execute
を使用して、データベースに対するクエリを実行します。
Python
Database.execute_sql
を使用して、データベースに対するクエリを実行します。
Ruby
Client#execute
を使用して、データベースに対するクエリを実行します。
SQL ステートメントを作成するときは、SQL クエリ構文と関数と演算子のリファレンスをご覧ください。
強力な読み取りの実行
以下では、強力な読み取りを実行してデータベースから 0 行以上を読み取る方法を説明します。
GoogleSQL
C++
データを読み取るためのコードは、SQL クエリを実行して Spanner をクエリする前述のサンプルと同じです。
C#
データを読み取るためのコードは、SQL クエリを実行して Spanner をクエリする前述のサンプルと同じです。
Go
Client.Single().Read
を使用して、データベースから行を読み取ります。
この例では AllKeys
を使用して、読み取る対象となるキーやキー範囲のコレクションを定義しています。
Java
ReadContext.read
を使用して、データベースから行を読み取ります。
この例では KeySet
を使用して、読み取る対象となるキーやキー範囲のコレクションを定義しています。
Node.js
Table.read
を使用して、データベースから行を読み取ります。
この例では keySet
を使用して、読み取る対象となるキーやキー範囲のコレクションを定義しています。
PHP
Database::read
を使用して、データベースから行を読み取ります。
この例では keySet
を使用して、読み取る対象となるキーやキー範囲のコレクションを定義しています。
Python
Database.read
を使用して、データベースから行を読み取ります。
この例では KeySet
を使用して、読み取る対象となるキーやキー範囲のコレクションを定義しています。
Ruby
Client#read
を使用して、データベースから行を読み取ります。
ステイル読み取りの実行
次のサンプルコードは、exact-staleness タイムスタンプ バウンドを使用してステイル読み取りを実行し、データベースから 0 行以上を読み取る方法を示しています。bounded-staleness タイムスタンプ バウンドを使用してステイル読み取りを実行する方法については、サンプルコードの後の注をご覧ください。利用できるタイムスタンプ バウンドのタイプに関する詳細については、タイムスタンプ バウンドをご覧ください。
GoogleSQL
C++
MakeReadOnlyTransaction()
と Transaction::ReadOnlyOptions()
で ExecuteQuery()
を使用して、ステイル読み取りを実行します。
C#
指定された TimestampBound.OfExactStaleness()
値で connection
に対して BeginReadOnlyTransactionAsync
メソッドを使用し、データベースに対するクエリを実行します。
Go
Client.ReadOnlyTransaction().WithTimestampBound()
を使用して ExactStaleness
値を指定し、exact-staleness タイムスタンプ バウンドを使用してデータベースから行を読み取ります。
この例では AllKeys
を使用して、読み取る対象となるキーやキー範囲のコレクションを定義しています。
Java
指定された TimestampBound.ofExactStaleness()
を含む ReadContext
の read
メソッドを使用して、exact-staleness タイムスタンプ バウンドを使用してデータベースから行を読み取ります。
この例では KeySet
を使用して、読み取る対象となるキーやキー範囲のコレクションを定義しています。
Node.js
Table.read
を exactStaleness
オプションとともに使用し、exact-staleness タイムスタンプ バウンドを使用してデータベースから行を読み取ります。
この例では keySet
を使用して、読み取る対象となるキーやキー範囲のコレクションを定義しています。
PHP
exactStaleness
値を指定して Database::read
を使用し、exact-staleness タイムスタンプ バウンドを使用してデータベースから行を読み取ります。
この例では keySet
を使用して、読み取る対象となるキーやキー範囲のコレクションを定義しています。
Python
指定された exact_staleness
値を含む Database
snapshot
の read
メソッドを使用して、exact-staleness タイムスタンプ バウンドを使用してデータベースから行を読み取ります。
この例では KeySet
を使用して、読み取る対象となるキーやキー範囲のコレクションを定義しています。
Ruby
指定された staleness
値(秒単位)を含むスナップショット Client
の read
メソッドを使用して、exact-staleness タイムスタンプ バウンドを使用してデータベースから行を読み取ります。
インデックスを使用して読み取りを実行する
以下では、インデックスを使用してデータベースから 0 行以上を読み取ります。
GoogleSQL
C++
Read()
関数を使用して、インデックスを使用して読み取りを実行します。
C#
インデックスを使用してデータを読み取るには、インデックスを明示的に指定するクエリを実行します。
Go
Client.Single().ReadUsingIndex
とインデックスを使用して、データベースから行を読み取ります。
Java
ReadContext.readUsingIndex
とインデックスを使用して、データベースから行を読み取ります。
Node.js
Table.read
を使用してクエリでインデックスを指定し、データベースから行を読み取ります。
PHP
Database::read
を使用してインデックスを指定し、データベースから行を読み取ります。
Python
Database.read
を使用してインデックスを指定し、データベースから行を読み取ります。
Ruby
Client#read
を使用してインデックスを指定し、データベースから行を読み取ります。
データを同時に読み込む
Spanner からの大量のデータを含むオペレーションを一括して実行またはクエリする場合、PartitionQuery
API を使用して結果を高速化できます。API は、複数のマシンを使用してパーティションを同時に取得し、クエリをバッチまたはパーティションに分割します。PartitionQuery
API はデータベース全体のエクスポートやスキャンなどの一括オペレーションのみを目的としているため、使用によりレイテンシが高くなることに注意してください。
Spanner クライアント ライブラリを使して、読み取り API オペレーションを同時に行うことができます。ただし、SQL クエリを分割できるのは、クエリがルート パーティショニング可能な場合のみです。クエリがルート パーティション化できるようにするには、クエリプランが次のいずれかの条件を満たしている必要があります。
クエリ実行プランの最初の演算子は、分散ユニオンクエリ実行プランには 1 つの分散ユニオンのみが含まれます(ローカル配布ユニオンを除く)。クエリプランには、分散クロス適用などの他の分散演算子を含めることはできません。
クエリプランには分散演算子がありません。
PartitionQuery
API は、バッチモードでクエリを実行します。Spanner は、バッチモードで実行時にクエリをルート パーティショニング可能にするクエリ実行プランを選択する場合があります。その結果、PartitionQuery
API と Spanner Studio は同じクエリに対して異なるクエリ実行プランを使用する可能性があります。Spanner Studio で PartitionQuery
API によって使用されるクエリ実行プランを取得できない場合があります。
このようなパーティション分割されたクエリでは、Spanner Data Boost を有効にできます。 Data Boost を使用すると、プロビジョニングされた Spanner インスタンスの既存のワークロードへの影響がほぼゼロの、大規模な分析クエリを実行できます。このページの C++、Go、Java、Node.js、Python のコードサンプルは、Data Boost を有効にする方法を示しています。
Data Boost の詳細については、Data Boost の概要をご覧ください。
GoogleSQL
C++
この例では、Singers
テーブルの SQL クエリのパーティションをフェッチし、次の手順で各パーティションにクエリを実行します。
- Spanner バッチ トランザクションを作成する。
- パーティションを複数のワーカーに分散できるように、クエリのパーティションを生成する。
- 各パーティションのクエリ結果を取得する。
C#
この例では、Singers
テーブルの SQL クエリのパーティションをフェッチし、次の手順で各パーティションにクエリを実行します。
- Spanner バッチ トランザクションを作成する。
- パーティションを複数のワーカーに分散できるように、クエリのパーティションを生成する。
- 各パーティションのクエリ結果を取得する。
Go
この例では、Singers
テーブルの SQL クエリのパーティションをフェッチし、次の手順で各パーティションにクエリを実行します。
- Spanner クライアントとトランザクションを作成する。
- パーティションを複数のワーカーに分散できるように、クエリのパーティションを生成する。
- 各パーティションのクエリ結果を取得する。
Java
この例では、Singers
テーブルの SQL クエリのパーティションをフェッチし、次の手順で各パーティションにクエリを実行します。
- Spanner バッチ クライアントとトランザクションを作成する。
- パーティションを複数のワーカーに分散できるように、クエリのパーティションを生成する。
- 各パーティションのクエリ結果を取得する。
Node.js
この例では、Singers
テーブルの SQL クエリのパーティションをフェッチし、次の手順で各パーティションにクエリを実行します。
- Spanner クライアントとバッチを作成する。
- パーティションを複数のワーカーに分散できるように、クエリのパーティションを生成する。
- 各パーティションのクエリ結果を取得する。
PHP
この例では、Singers
テーブルの SQL クエリのパーティションをフェッチし、次の手順で各パーティションにクエリを実行します。
- Spanner クライアントとバッチを作成する。
- パーティションを複数のワーカーに分散できるように、クエリのパーティションを生成する。
- 各パーティションのクエリ結果を取得する。
Python
この例では、Singers
テーブルの SQL クエリのパーティションをフェッチし、次の手順で各パーティションにクエリを実行します。
- Spanner クライアントとバッチ トランザクションを作成する。
- パーティションを複数のワーカーに分散できるように、クエリのパーティションを生成する。
- 各パーティションのクエリ結果を取得する。
Ruby
この例では、Singers
テーブルの SQL クエリのパーティションをフェッチし、次の手順で各パーティションにクエリを実行します。
- Spanner バッチ クライアントを作成する。
- パーティションを複数のワーカーに分散できるように、クエリのパーティションを作成する。
- 各パーティションのクエリ結果を取得する。