次の方法で共有


サーバーレス 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 分析ストレージがサーバーレス 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 CasesCOVID-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 アカウント MyCosmosDbAccountcovid データベースに接続するように、サーバーレス SQL プールに指示しています。 その後、West US 2 リージョンのコンテナー Ecdc の分析ストアにアクセスします。 特定のプロパティのプロジェクションはないため、OPENROWSET 関数は Azure Cosmos DB の項目からすべてのプロパティを返します。

Azure Cosmos DB コンテナー内の項目に date_repcases、および 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ÃÂ&copy;lade のような予期しない文字がテキストで表示される場合は、データベースの照合順序が MÃÂ&copy;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ÃÂ&copy;lade のような予期しない文字がテキストで表示される場合は、データベースの照合順序が MÃÂ&copy;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 プロパティ型がサポートされています。 OPENROWSETWITH 句を使用する場合は、これらの 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 のプロパティ型を明示的に指定する必要があります。

次の例では、stringgeo_id プロパティの正しい型であり、int32cases プロパティの正しい型であると仮定します。

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_idcases の値は、NULL 値として返されます。 このクエリは、式 (cases.int32) で指定されている型の cases のみを参照します。

Azure Cosmos DB コンテナーでクリーンアップできない他の型 (cases.int64cases.float64) を持つ値がある場合は、WITH 句で明示的に参照し、その結果を結合する必要があります。 次のクエリでは、cases 列に格納されている int32int64、および 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 の数値は int32int64float64 のいずれかの値として格納されます。 国と地域ごとのケースの数を計算するには、すべての値を抽出する必要があります。

トラブルシューティング

セルフヘルプページを参照して、Azure Cosmos DB クエリで発生する可能性のある問題の解決に役立つ既知の問題やトラブルシューティングの手順を確認してください。