サーバーレス SQL プールを使用して Azure Cosmos DB のデータのクエリを実行する
サーバーレス SQL プールを使用すると、トランザクション ワークロードのパフォーマンスに影響を与えることなく、Azure Synapse Link で有効になっている Azure Cosmos DB コンテナー内のデータをほぼリアルタイムで分析できます。 それが提供する使いやすい Transact-SQL (T-SQL) 構文を使って、分析ストアや、T-SQL インターフェイスを介して統合されたさまざまなビジネス インテリジェンス (BI) やアドホックのクエリ ツールへの接続で、データのクエリを実行できます。
Azure Cosmos DB のクエリを実行する場合、SELECT のすべての機能が OPENROWSET 関数によってサポートされます。これには、SQL の関数と演算子の大部分が含まれます。 また、Azure Blob Storage または Azure Data Lake Storage のデータと共に Azure Cosmos DB からデータを読み取るクエリの結果を、create external table as select (CETAS) を使用して格納することもできます。 現在は、CETAS を使用して、サーバーレス SQL プールのクエリの結果を Azure Cosmos DB に格納することはできません。
この記事では、Azure Synapse Link によって有効にされている Azure Cosmos DB コンテナーのデータのクエリを実行するクエリを、サーバーレス SQL プールを使って作成する方法について説明します。 その後は、このチュートリアルで、Azure Cosmos DB コンテナーに対するサーバーレス SQL プールのビューを構築し、それらを Power BI モデルに接続することの詳細を学習できます。 このチュートリアルでは、Azure Cosmos DB の適切に定義されたスキーマを持つコンテナーを使用します。 また、Azure Synapse Analytics の SQL サーバーレスを使用して Azure Cosmos DB をクエリする方法に関する学習モジュールもご覧ください。
Note
マネージド ID を使って、サーバーレス SQL プールから Azure Cosmos DB コンテナーにアクセスすることはできません。
前提条件
- 分析ストアを確実に準備します。
- 分析ストアを自分の Azure Cosmos DB コンテナーで有効にします。
- 分析ストアのクエリに使用できる接続文字列を、読み取り専用キーを使って取得します。
- Azure Cosmos DB コンテナーへのアクセスに使われる読み取り専用キーを取得します。
- 次のようなすべてのベストプラクティスが適用されていることを確認します。
- Azure Cosmos DB 分析ストレージがサーバーレス SQL プールと同じリージョンにあることを確認します。
- クライアントアプリケーション (Power BI、分析サービス) が、サーバーレス SQL プールと同じリージョンにあることを確認します。
- 大量のデータ (80 GB 超) を返す場合は、Analysis Services などのキャッシュ レイヤーを使用し、Analysis Services モデルに 80 GB より小さいパーティションを読み込むことを検討します。
- 文字列型の列を使ってデータをフィルター処理する場合は、
OPENROWSET
関数で、可能な限り小さい型を使って明示的にWITH
句を指定していることを確認します。 たとえば、プロパティが 5 文字以下であることがわかっている場合は、VARCHAR(1000)
を使わないでください。
概要
サーバーレス SQL プールを使用すると、OPENROWSET
関数を使用して Azure Cosmos DB 分析ストレージに対してクエリを実行できます。
-
OPENROWSET
とインライン キー。 この構文を使うと、資格情報を準備せずに Azure Cosmos DB コレクションのクエリを実行できます。 - Azure Cosmos DB のアカウント キーを含む資格情報を参照する
OPENROWSET
。 この構文を使用すると、Azure Cosmos DB コレクションに対してビューを作成できます。
Azure Cosmos DB 分析ストア内のデータのクエリと分析をサポートするため、サーバーレス SQL プールを使用します。 サーバーレス SQL プールでは OPENROWSET
SQL 構文が使用されているため、まずは Azure Cosmos DB 接続文字列を次の形式に変換する必要があります。
OPENROWSET(
'CosmosDB',
'<SQL connection string for Azure Cosmos DB>',
<Container name>
) [ < with clause > ] AS alias
Azure Cosmos DB 用の SQL 接続文字列は、Azure Cosmos DB のアカウント名、データベース名、データベース アカウント マスター キー、および OPENROWSET
関数に対するオプションのリージョン名を指定します。 この情報の一部は、標準の Azure Cosmos DB 接続文字列から取得できます。
Azure Cosmos DB の標準の接続文字列形式から変換します。
AccountEndpoint=https://<database account name>.documents.azure.com:443/;AccountKey=<database account master key>;
SQL 接続文字列の形式は次のとおりです。
'account=<database account name>;database=<database name>;region=<region name>;key=<database account master key>'
リージョンは省略可能です。 省略した場合、コンテナーのプライマリ リージョンが使用されます。
重要
接続文字列には、endpoint
という名前の別の省略可能なパラメーターがあります。
endpoint
パラメーターは、標準の *.documents.azure.com
形式と一致しないアカウントに必要です。 たとえば、Azure Cosmos DB アカウントの末尾が .documents.azure.us
の場合は、接続文字列に endpoint=<account name>.documents.azure.us
を必ず追加してください。
OPENROWSET
の構文では、引用符を使用しないで Azure Cosmos DB のコンテナー名を指定します。 コンテナー名に特殊文字 (ダッシュ "-" など) が含まれている場合、OPENROWSET
構文では名前を角かっこ ([]
) で囲む必要があります。
重要
Azure Cosmos DB 分析ストア内の文字列値は UTF-8 テキストとしてエンコードされているため、必ず何らかの UTF-8 データベース照合順序 (Latin1_General_100_CI_AS_SC_UTF8
など) を使用してください。
ファイル内のテキスト エンコードと照合順序が一致しないと、予期しないテキスト変換エラーが発生する可能性があります。
現在のデータベースの既定の照合順序は、alter database current collate Latin1_General_100_CI_AI_SC_UTF8
という T-SQL ステートメントを使用して簡単に変更できます。
Note
サーバーレス SQL プールでは、Azure Cosmos DB トランザクション ストアのクエリはサポートされていません。
サンプル データセット
この記事の例は、European Centre for Disease Prevention and Control (ECDC) COVID-19 Cases と COVID-19 Open Research Dataset (CORD-19) のデータに基づいています。
これらのページでは、ライセンスとデータの構造を確認できます。 ECDC および CORD-19 データセットのサンプル データをダウンロードすることもできます。
サーバーレス SQL プールを使用して Azure Cosmos DB データのクエリを実行する方法を示すこの記事の内容をたどるには、以下のリソースを作成してください。
- Azure Synapse Link が有効にされている Azure Cosmos DB データベース アカウント
-
covid
という名前の Azure Cosmos DB データベース - 前述のサンプル データセットが読み込まれた、
Ecdc
およびCord19
という名前の 2 つの Azure Cosmos DB コンテナー
この接続ではパフォーマンスが保証されないことに注意してください。これは、このアカウントが Synapse SQL エンドポイントと比べて遠いリージョンに配置される可能性があるためです。
自動スキーマ推論を使用して Azure Cosmos DB のデータを探索する
Azure Cosmos DB のデータを探索する最も簡単な方法は、自動スキーマ推論機能を使用することです。
OPENROWSET
ステートメントで WITH
句を省略すると、Azure Cosmos DB コンテナーの分析ストアのスキーマを自動検出 (推論) するように、サーバーレス SQL プールに指示できます。
重要
スクリプトで、次の値を実際の値に置き換えます。
- your-cosmosdb: Cosmos DB アカウントの名前
- access-key: Cosmos DB アカウント キー
SELECT TOP 10 *
FROM OPENROWSET(
'CosmosDB',
'Account=your-cosmosdb;Database=covid;Key=yourcosmosdbkey',
Ecdc) as documents
この例では、Azure Cosmos DB キー (この例ではダミー) を使用して認証された Azure Cosmos DB アカウント MyCosmosDbAccount
の covid
データベースに接続するように、サーバーレス SQL プールに指示しています。 その後、West US 2
リージョンのコンテナー Ecdc
の分析ストアにアクセスします。 特定のプロパティのプロジェクションはないため、OPENROWSET
関数は Azure Cosmos DB の項目からすべてのプロパティを返します。
Azure Cosmos DB コンテナー内の項目に date_rep
、cases
、および geo_id
プロパティがあると仮定すると、このクエリの結果は次の表のようになります。
date_rep | cases | geo_id |
---|---|---|
2020-08-13 | 254 | RS |
2020-08-12 | 235 | RS |
2020-08-11 | 163 | RS |
同じ Azure Cosmos DB データベース内の他のコンテナーのデータを探索する必要がある場合は、同じ接続文字列を使用し、3 番目のパラメーターとして必要なコンテナーを参照することができます。
SELECT TOP 10 *
FROM OPENROWSET(
'CosmosDB',
'Account=your-cosmosdb;Database=covid;Key=yourcosmosdbkey',
Cord19) as cord19
スキーマを明示的に指定する
OPENROWSET
の自動スキーマ推論機能では、簡単で使いやすいエクスペリエンスが提供されますが、ビジネス シナリオによっては、Azure Cosmos DB のデータから関連するプロパティのみを読み取るように、スキーマを明示的に指定することが必要な場合があります。
OPENROWSET
関数を使うと、コンテナー内のデータから読み取るプロパティとデータ型を明示的に指定できます。
次のような構造の ECDC COVID データセットから、一部のデータを Azure Cosmos DB にインポートしたとします。
{"date_rep":"2020-08-13","cases":254,"countries_and_territories":"Serbia","geo_id":"RS"}
{"date_rep":"2020-08-12","cases":235,"countries_and_territories":"Serbia","geo_id":"RS"}
{"date_rep":"2020-08-11","cases":163,"countries_and_territories":"Serbia","geo_id":"RS"}
Azure Cosmos DB のこのようなフラットな JSON ドキュメントは、Synapse SQL では行と列のセットとして表すことができます。
OPENROWSET
関数を使うと、読み取るプロパティのサブセットと列の厳密な型を、WITH
句で指定できます。
SELECT TOP 10 *
FROM OPENROWSET(
'CosmosDB',
'Account=your-cosmosdb;Database=covid;Key=yourcosmosdbkey',
Ecdc
) with ( date_rep varchar(20), cases bigint, geo_id varchar(6) ) as rows
このクエリの結果は次の表のようになります。
date_rep | cases | geo_id |
---|---|---|
2020-08-13 | 254 | RS |
2020-08-12 | 235 | RS |
2020-08-11 | 163 | RS |
Azure Cosmos DB の値に使う必要がある SQL 型について詳しくは、この記事の最後にある「Azure Cosmos DB から SQL 型へのマッピング」をご覧ください。
ビューを作成する
master
または既定のデータベースにビューを作成することは推奨されないか、サポートされていません。 そのため、ビューのためのユーザー データベースを作成する必要があります。
スキーマを特定したら、Azure Cosmos DB データの上にビューを準備できます。 Azure Cosmos DB アカウント キーを別の資格情報に配置し、OPENROWSET
関数からこの資格情報を参照する必要があります。 アカウント キーをビューの定義で保持しないでください。
CREATE CREDENTIAL MyCosmosDbAccountCredential
WITH IDENTITY = 'SHARED ACCESS SIGNATURE', SECRET = 'yourcosmosdbkey';
GO
CREATE OR ALTER VIEW Ecdc
AS SELECT *
FROM OPENROWSET(
PROVIDER = 'CosmosDB',
CONNECTION = 'Account=your-cosmosdb;Database=covid',
OBJECT = 'Ecdc',
SERVER_CREDENTIAL = 'MyCosmosDbAccountCredential'
) with ( date_rep varchar(20), cases bigint, geo_id varchar(6) ) as rows
パフォーマンスに影響する可能性があるため、明示的に定義されたスキーマを使わずに OPENROWSET
を使用しないでください。 列のサイズは可能な限り小さくしてください (たとえば、既定の VARCHAR(8000)
ではなく VARCHAR(100)
)。
UTF-8 の変換に関する問題を回避するため、何らかの UTF-8 照合順序を既定のデータベース照合順序として使用するか、明示的な列の照合順序として設定する必要があります。 照合順序 Latin1_General_100_BIN2_UTF8
は、文字列型の列を使用してデータをフィルター処理する場合に最も高いパフォーマンスを提供します。
ビューのクエリを実行すると、エラーや予期しない結果が発生する可能性があります。 ビュー参照の列またはオブジェクトが変更されたか、存在しなくなった可能性があります。 基になるスキーマの変更に合わせてビュー定義を手動で調整する必要があります。 これは、ビューで自動スキーマ推論を使うときと、スキーマを明示的に指定するときのどちらでも発生する可能性があることに注意してください。
入れ子になったオブジェクトに対してクエリを実行する
Azure Cosmos DB を使用すると、入れ子になったオブジェクトまたは配列として構成することで、より複雑なデータ モデルを表すことができます。 Azure Cosmos DB に対する Azure Synapse Link の自動同期機能により、何もしなくても分析ストアでのスキーマ表現が管理されます。これには、サーバーレス SQL プールからの高度なクエリを可能にする、入れ子になったデータ型の処理が含まれます。
たとえば、CORD-19 データ セットには、次の構造に従った JSON ドキュメントが含まれています。
{
"paper_id": <str>, # 40-character sha1 of the PDF
"metadata": {
"title": <str>,
"authors": <array of objects> # list of author dicts, in order
...
}
...
}
Azure Cosmos DB 内の入れ子になったオブジェクトと配列は、OPENROWSET
関数で読み取ると、クエリ結果で JSON 文字列として表されます。
WITH
句を使用するときに、オブジェクト内の入れ子になった値へのパスを指定できます。
SELECT TOP 10 *
FROM OPENROWSET(
'CosmosDB',
'Account=your-cosmosdb;Database=covid;Key=yourcosmosdbkey',
Cord19)
WITH ( paper_id varchar(8000),
title varchar(1000) '$.metadata.title',
metadata varchar(max),
authors varchar(max) '$.metadata.authors'
) AS docs;
このクエリの結果は次の表のようになります。
paper_id | title | metadata | 作成者 |
---|---|---|---|
bb11206963e831f… | Supplementary Information An eco-epidemi… | {"title":"Supplementary Informati… |
[{"first":"Julien","last":"Mélade","suffix":"","af… |
bb1206963e831f1… | The Use of Convalescent Sera in Immune-E… | {"title":"The Use of Convalescent… |
[{"first":"Antonio","last":"Lavazza","suffix":"", … |
bb378eca9aac649… | Tylosema esculentum (Marama) Tuber and B… | {"title":"Tylosema esculentum (Ma… |
[{"first":"Walter","last":"Chingwaru","suffix":"",… |
詳しくは、「Azure Synapse Analytics で複合データ型を分析する」または Parquet と JSON ファイルで入れ子にされた型に対するサーバーレス SQL プールを使用したクエリの実行に関する記事をご覧ください。
重要
Mélade
ではなく Mélade
のような予期しない文字がテキストで表示される場合は、データベースの照合順序が Mélade
の照合順序に設定されていません。
ALTER DATABASE MyLdw COLLATE LATIN1_GENERAL_100_CI_AS_SC_UTF8
のような SQL ステートメントを使って、UTF-8 照合順序にデータベースの照合順序を変更できます。
入れ子になった配列のフラット化
Azure Cosmos DB のデータには、CORD-19 データ セットの authors 配列のように、入れ子になったサブ配列が存在する場合があります。
{
"paper_id": <str>, # 40-character sha1 of the PDF
"metadata": {
"title": <str>,
"authors": [ # list of author dicts, in order
{
"first": <str>,
"middle": <list of str>,
"last": <str>,
"suffix": <str>,
"affiliation": <dict>,
"email": <str>
},
...
],
...
}
場合によっては、最上位の項目 (metadata) のプロパティと、配列 (authors) のすべての要素の "結合" が必要になります。 サーバーレス SQL プールを使うと、入れ子になった配列に OPENJSON
関数を適用して、入れ子構造をフラット化できます。
SELECT
*
FROM
OPENROWSET(
'CosmosDB',
'Account=your-cosmosdb;Database=covid;Key=yourcosmosdbkey',
Cord19
) WITH ( title varchar(1000) '$.metadata.title',
authors varchar(max) '$.metadata.authors' ) AS docs
CROSS APPLY OPENJSON ( authors )
WITH (
first varchar(50),
last varchar(50),
affiliation nvarchar(max) as json
) AS a
このクエリの結果は次の表のようになります。
title | 作成者 | first | last | affiliation |
---|---|---|---|---|
Supplementary Information An eco-epidemi… | [{"first":"Julien","last":"Mélade","suffix":"","affiliation":{"laboratory":"Centre de Recher… |
Julien | Mélade | {"laboratory":"Centre de Recher… |
Supplementary Information An eco-epidemi… | [{"first":"Nicolas","last":"4#","suffix":"","affiliation":{"laboratory":"","institution":"U… |
Nicolas | 4# | {"laboratory":"","institution":"U… |
Supplementary Information An eco-epidemi… | [{"first":"Beza","last":"Ramazindrazana","suffix":"","affiliation":{"laboratory":"Centre de Recher… |
Beza | Ramazindrazana | {"laboratory":"Centre de Recher… |
Supplementary Information An eco-epidemi… | [{"first":"Olivier","last":"Flores","suffix":"","affiliation":{"laboratory":"UMR C53 CIRAD, … |
Olivier | Flores | {"laboratory":"UMR C53 CIRAD, … |
重要
Mélade
ではなく Mélade
のような予期しない文字がテキストで表示される場合は、データベースの照合順序が Mélade
の照合順序に設定されていません。
ALTER DATABASE MyLdw COLLATE LATIN1_GENERAL_100_CI_AS_SC_UTF8
のような SQL ステートメントを使って、UTF-8 照合順序にデータベースの照合順序を変更できます。
Azure Cosmos DB から SQL 型へのマッピング
Azure Cosmos DB のトランザクション ストアはスキーマに依存しませんが、分析ストアは分析クエリのパフォーマンスを最適化するためにスキーマ化されています。 Azure Synapse Link の自動同期機能により、Azure Cosmos DB では何もしなくても分析ストアでのスキーマ表現が管理されます。これには、入れ子になったデータ型の処理が含まれます。 サーバーレス SQL プールでは分析ストアのクエリが実行されるため、Azure Cosmos DB の入力データ型を SQL データ型にマップする方法を理解することが重要です。
SQL (Core) API の Azure Cosmos DB アカウントでは、"数値"、"文字列"、"ブール値"、null、"入れ子になったオブジェクト"、または "配列" の JSON プロパティ型がサポートされています。
OPENROWSET
で WITH
句を使用する場合は、これらの JSON 型に一致する SQL 型を選択する必要があります。 次の表は、Azure Cosmos DB のさまざまなプロパティの型に対して使用する必要がある SQL 列の型を示しています。
Azure Cosmos DB のプロパティの型 | SQL 列の型 |
---|---|
Boolean | bit |
Integer | bigint |
Decimal | float |
String | varchar (UTF-8 データベース照合順序) |
日付と時刻 (ISO 形式の文字列) | varchar(30) |
日付と時刻 (UNIX タイムスタンプ) | bigint |
[Null] | any SQL type |
入れ子になったオブジェクトまたは配列 | varchar(max) (UTF-8 データベース照合順序)、JSON テキストとしてシリアル化 |
完全に忠実なスキーマ
Azure Cosmos DB の完全に忠実なスキーマを使用すると、コンテナー内のすべてのプロパティについて、値と最も一致する型の両方を記録できます。 完全に忠実なスキーマを持つコンテナーで OPENROWSET
関数を使用すると、各セルに型と実際の値の両方が提供されます。 次のクエリでは、完全に忠実なスキーマでコンテナーから項目を読み取ると仮定します。
SELECT *
FROM OPENROWSET(
'CosmosDB',
'account=MyCosmosDbAccount;database=covid;region=westus2;key=C0Sm0sDbKey==',
Ecdc
) as rows
このクエリの結果では、JSON テキストとして書式設定された型と値が返されます。
date_rep | cases | geo_id |
---|---|---|
{"date":"2020-08-13"} | {"int32":"254"} | {"string":"RS"} |
{"date":"2020-08-12"} | {"int32":"235"} | {"string":"RS"} |
{"date":"2020-08-11"} | {"int32":"316"} | {"string":"RS"} |
{"date":"2020-08-10"} | {"int32":"281"} | {"string":"RS"} |
{"date":"2020-08-09"} | {"int32":"295"} | {"string":"RS"} |
{"string":"2020/08/08"} | {"int32":"312"} | {"string":"RS"} |
{"date":"2020-08-07"} | {"float64":"339.0"} | {"string":"RS"} |
すべての値について、Azure Cosmos DB コンテナーの項目で識別された型を確認できます。
date_rep
プロパティの値のほとんどに date
値が含まれていますが、一部の値が Azure Cosmos DB に誤って文字列として格納されています。 完全に忠実なスキーマからは、正しく型指定された date
値と、正しく書式設定されていない string
値の両方が返されます。
ケースの数は int32
値として格納されますが、10 進数として入力される値が 1 つあります。 この値の型は float64
です。
int32
の最大値を超える値がある場合は int64
型として格納されます。 この例のすべての geo_id
値は string
型として格納されます。
重要
WITH
句が指定されていない OPENROWSET
関数では、予期される型を持つ値と、入力された型が正しくない値の両方が公開されます。 この関数は、レポート用ではなく、データの探索用に設計されています。 この関数から返された JSON 値を解析してレポートを作成しないでください。 レポートを作成するには、明示的な WITH 句 を使用します。 完全に忠実な分析ストアで補正を適用するためには、Azure Cosmos DB コンテナー内の型が正しくない値をクリーンアップする必要があります。
Azure Cosmos DB for MongoDB アカウントに対してクエリを実行する場合は、分析ストア内の完全に忠実なスキーマ表現と、使用される拡張プロパティ名の詳細を、「Azure Cosmos DB の分析ストアとは」で確認してください。
完全に忠実なスキーマの項目に対してクエリを実行する
完全に忠実なスキーマにクエリを実行する際は、WITH
句で SQL 型と、想定される Azure Cosmos DB のプロパティ型を明示的に指定する必要があります。
次の例では、string
は geo_id
プロパティの正しい型であり、int32
は cases
プロパティの正しい型であると仮定します。
SELECT geo_id, cases = SUM(cases)
FROM OPENROWSET(
'CosmosDB'
'account=MyCosmosDbAccount;database=covid;region=westus2;key=C0Sm0sDbKey==',
Ecdc
) WITH ( geo_id VARCHAR(50) '$.geo_id.string',
cases INT '$.cases.int32'
) as rows
GROUP BY geo_id
他の型を持つ geo_id
と cases
の値は、NULL
値として返されます。 このクエリは、式 (cases.int32
) で指定されている型の cases
のみを参照します。
Azure Cosmos DB コンテナーでクリーンアップできない他の型 (cases.int64
、cases.float64
) を持つ値がある場合は、WITH
句で明示的に参照し、その結果を結合する必要があります。 次のクエリでは、cases
列に格納されている int32
、int64
、および float64
の両方を集約します。
SELECT geo_id, cases = SUM(cases_int) + SUM(cases_bigint) + SUM(cases_float)
FROM OPENROWSET(
'CosmosDB',
'account=MyCosmosDbAccount;database=covid;region=westus2;key=C0Sm0sDbKey==',
Ecdc
) WITH ( geo_id VARCHAR(50) '$.geo_id.string',
cases_int INT '$.cases.int32',
cases_bigint BIGINT '$.cases.int64',
cases_float FLOAT '$.cases.float64'
) as rows
GROUP BY geo_id
この例では、cases の数値は int32
、 int64
、 float64
のいずれかの値として格納されます。 国と地域ごとのケースの数を計算するには、すべての値を抽出する必要があります。
トラブルシューティング
セルフヘルプページを参照して、Azure Cosmos DB クエリで発生する可能性のある問題の解決に役立つ既知の問題やトラブルシューティングの手順を確認してください。