共用方式為


使用無伺服器 SQL 集區查詢 Azure Cosmos DB 資料

重要事項

Synapse Link for Cosmos DB 已不再支援新專案。 不要使用這個功能。

請為 Microsoft Fabric 使用 Azure Cosmos DB 鏡像,該 Fabric 現在已是正式發行版。 鏡像提供相同的零 ETL 優勢,且與 Microsoft Fabric 完全整合。 想了解更多,請參閱 Cosmos DB 鏡像概覽

無伺服器 SQL 集區讓您能以近乎即時的方式,分析已啟用 Azure Synapse Link 之 Azure Cosmos DB 容器中的資料,且完全不影響交易式工作負載的效能。 它提供熟悉的 Transact-SQL (T-SQL) 語法,以查詢分析存放區中的資料,並透過 T-SQL 介面為多種商業智慧 (BI) 和即席查詢工具提供整合的連線能力。

若要查詢 Azure Cosmos DB,完整的 SELECT 語法支援範圍可透過 OPENROWSET 函式實現,其中包含多數的 SQL 函式與運算子。 您還可以使用 CREATE EXTERNAL TABLE AS SELECT (CETAS),將從 Azure Cosmos DB 讀取資料的查詢結果,連同 Azure Blob 儲存體或 Azure Data Lake Storage 中的資料一併儲存。 您目前無法使用 CETAS 將無伺服器 SQL 集區查詢結果儲存至 Azure Cosmos DB。

本文說明如何透過無伺服器 SQL 集區來撰寫查詢,用以查詢已啟用 Azure Synapse Link 的 Azure Cosmos DB 容器中的資料。 接著,您可以透過 本教學課程,進一步學習如何在 Azure Cosmos DB 容器上建立無伺服器 SQL 集區檢視,並將其連線至 Power BI 模型。 本教學課程使用一個具備 Azure Cosmos DB 明確定義結構描述的容器。 您也可以查看關於如何使用適用於 Azure Synapse Analytics 的 SQL Serveless 查詢 Azure Cosmos DB 的 Learn 課程模組。

先決條件

  • 請確定您已準備分析存放區:
    • 您的 Azure Cosmos DB 容器上啟用分析存放區。
    • 使用可用來查詢分析存放區的唯讀金鑰來取得連接字串。
    • 取得將用來存取 Azure Cosmos DB 容器的唯讀 金鑰。
  • 請確定您已套用所有最佳做法,例如:
    • 請確定您的 Azure Cosmos DB 分析儲存體位於與無伺服器 SQL 集區相同的區域中。
    • 確定用戶端應用程式 (Power BI、Analysis Services) 位於與無伺服器 SQL 集區相同的區域中。
    • 如果您要傳回大量資料 (超過 80 GB),請考慮使用快取層,例如 Analysis Services,並在 Analysis Services 模型中載入小於 80 GB 的分割區。
    • 若您使用字串資料行篩選資料,請務必在 OPENROWSETOPENROWSET 函式中搭配 WITH 子句,並在該子句中指定最小可能的資料類型。 例如,如果您知道屬性最多有五個字元,請勿使用 VARCHAR(1000)

概觀

無伺服器 SQL 集區可讓您使用 OPENROWSET 函式查詢 Azure Cosmos DB 分析儲存體。

OPENROWSET( 
       'CosmosDB',
       '<SQL connection string for Azure Cosmos DB>',
       <other parameters>
    )  [ < with clause > ] AS alias

Azure Cosmos DB 的 SQL 連接字串包括以下元件:

  • 帳戶 - 目標 Azure Cosmos DB 帳戶的名稱。
  • 資料庫 - 容器名稱,在 OPENROWSET 語法中指定,不帶引號。 如果容器名稱包含特殊字元 (例如,破折號 -),則應將其括在方括弧 ([]) 中。
  • 區域 (可選) - Cosmos DB 分析儲存體的區域。 如果省略,則會使用容器的主要區域。
  • 端點 (可選) - Cosmos DB 端點 URI (例如 https://<account name>.documents.azure.us),如果您的 Cosmos DB 帳戶不遵循標準 *.documents.azure.com 格式,則這是必需的。

重要事項

與標準 *.documents.azure.com 格式不匹配的帳戶需要該 endpoint 參數。 例如,如果您的 Azure Cosmos DB 帳戶以 .documents.azure.us 結尾,請確定您在連接字串中新增 endpoint=https://<account name>.documents.azure.us。 確保包含 https:// 前置詞。

可以從標準 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>

此連接字串不包括連接到 Cosmos DB 分析儲存體所需的驗證資訊。 根據使用的驗證類型,需要其他資訊:

  • 如果 OPENROWSET 使用工作區受控身分識別存取分析儲存體,則應新增 AuthType 屬性。
  • 如果 OPENROWSET 使用內嵌帳戶金鑰,則應新增 key 屬性。 這樣,您就可以查詢 Azure Cosmos DB 集合,而無需準備認證。
  • 您也可以不將驗證資訊包含在連接字串中,而讓 OPENROWSET 參照一個內含 Azure Cosmos DB 帳戶金鑰的認證。 此方法可用於在 Azure Cosmos DB 集合上建立檢視。

以下說明這些選項。

無伺服器 SQL 集區讓您能夠查詢 Cosmos DB 分析儲存體,並使用原始的 Cosmos DB 帳戶金鑰進行驗證,或允許 Synapse受控身分識別存取 Cosmos DB 分析儲存體。 在此案例中,您可以使用下列語法:

OPENROWSET( 
       'CosmosDB',
       '<SQL connection string for Azure Cosmos DB>',
       <Container name>
    )  [ < with clause > ] AS alias

除了上述 SQL 連接字串中的常用屬性 (帳戶資料庫區域終端節點) 之外,您還需要新增以下選項之一

  • AuthType - 如果使用 Synapse 工作區受控身分識別存取 Cosmos DB,請將此選項設定為 ManagedIdentity
  • 金鑰 - 用於存取 Cosmos DB 資料的主要金鑰,在未使用 Synapse 工作區受控身分識別時使用。

下表顯示了連接字串的範例:

驗證類型 連線字串
Synapse 工作區的受控身分識別 account=<account name>;database=<db name>;region=<region name>;AuthType=ManagedIdentity
Cosmos DB 帳戶主要金鑰 account=<account name>;database=<db name>;region=<region name>;key=<account master key>

重要事項

請確保使用支援 UTF-8 的資料庫定序,例如 Latin1_General_100_CI_AS_SC_UTF8,這是因為 Azure Cosmos DB 分析儲存體中的字串值皆以 UTF-8 文字編碼儲存。 檔案中的文字編碼與定序不符可能會導致非預期的文字轉換錯誤。 您可以使用 T-SQL 陳述式 alter database current collate Latin1_General_100_CI_AI_SC_UTF8,輕鬆地變更目前資料庫的預設定序。

附註

無伺服器 SQL 集區不支援查詢 Azure Cosmos DB 交易存放區。

範例資料集

本文中的範例基於來自 歐洲疾病預防控制中心 (ECDC) COVID-19 病例COVID-19 開放研究資料集 (CORD-19) 的資料。

您可以在這些頁面上查看資料的授權和結構。 您也可以下載 ECDC 和 CORD-19 資料集的範例資料。

請依照本文操作,了解如何使用無伺服器 SQL 集區查詢 Azure Cosmos DB 資料,在開始之前,請先建立以下資源:

  • 一個已啟用 Azure Synapse Link 的 Azure Cosmos DB 資料庫帳戶。
  • 一個名為 covid 的 Azure Cosmos DB 資料庫。
  • 兩個名為 EcdcCord19 的 Azure Cosmos DB 容器,且已載入前述的範例資料集。

請注意,此連線並不保證效能,因為該帳戶所在的區域可能與您的 Synapse SQL 端點相距甚遠。

使用自動結構描述推斷探索 Azure Cosmos DB 資料

在 Azure Cosmos DB 中探索資料最簡單的方式是使用自動結構描述推斷功能。 在 OPENROWSET 陳述式中省略 WITH 子句,即可指示無伺服器 SQL 集區自動偵測 (推斷) Azure Cosmos DB 容器分析儲存區的結構描述。

重要事項

在指令碼中,將這些數值替換為您自己的值:

  • your-cosmosdb - Cosmos DB 帳戶的名稱
  • yourcosmosdbkey - 您的 Cosmos DB 帳戶金鑰
SELECT TOP 10 *
FROM OPENROWSET( 
       'CosmosDB',
       'Account=your-cosmosdb;Database=covid;Key=yourcosmosdbkey',
       Ecdc) as documents

在上述範例中,我們指示無伺服器 SQL 集區連線至 Azure Cosmos DB 帳戶 MyCosmosDbAccount 中的 covid 資料庫,並使用 Azure Cosmos DB 金鑰進行驗證 (範例中的金鑰為虛構值)。 接著,我們存取位於 West US 2 區域的 Ecdc 容器分析儲存區。 由於未指定要投射的特定屬性,OPENROWSET 函式會從 Azure Cosmos DB 項目中傳回所有屬性。

假設 Azure Cosmos DB 容器中的項目具有 date_repcasesgeo_id 屬性,則此查詢的結果如下表所示:

date_rep 案例 geo_id
2020-08-13 254 RS
2020-08-12 235 RS
2020 年 8 月 11 日 163 RS

若您需要探索同一個 Azure Cosmos DB 資料庫中其他容器的資料,可以使用相同的連接字串,並將目標容器指定為第三個參數:

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 案例 geo_id
2020-08-13 254 RS
2020-08-12 235 RS
2020 年 8 月 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(100) 而非預設的 VARCHAR(8000))。 建議您將支援 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
        ...
     }
     ...
}

當使用 OPENROWSET 函式讀取時,Azure Cosmos DB 中的巢狀物件和陣列在查詢結果中會以 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 標題 中繼資料 authors
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 中的複雜資料類型使用無伺服器 SQL 集區查詢 Parquet 與 JSON 檔案中的巢狀類型

重要事項

如果您的文字中出現非預期的字元 (例如顯示為 MÃÂ&copy;lade而非Mélade),這表示您的資料庫定序未設定為 UTF-8 定序。 您可以使用類似 ALTER DATABASE MyLdw COLLATE LATIN1_GENERAL_100_CI_AS_SC_UTF8 的 SQL 陳述式,將資料庫定序變更為 UTF-8 定序。

扁平化巢狀陣列

Azure Cosmos DB 資料可能有巢狀子陣列,例如來自 CORD-19 資料集的作者陣列:

{
    "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>
            },
            ...
        ],
        ...
}

在某些情況下,您可能需要將頂層項目 (中繼資料) 的屬性聯結到陣列 (作者) 的所有元素中。 無伺服器 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

此查詢的結果可能如下表所示:

標題 authors 第一 最後一 關係
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 弗洛雷斯 {"laboratory":"UMR C53 CIRAD, …

重要事項

如果您的文字中出現非預期的字元 (例如顯示為 MÃÂ&copy;lade而非Mélade),這表示您的資料庫定序未設定為 UTF-8 定序。 您可以使用類似 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 帳戶,其 JSON 屬性支援以下類型:數值字串布林值Null巢狀物件陣列。 如果您使用 OPENROWSET 中的 WITH 子句,則必須選擇符合這些 JSON 類型的 SQL 類型。 下表顯示應該用於 Azure Cosmos DB 中不同屬性類型的 SQL 欄類型。

Azure Cosmos DB 屬性類型 SQL 欄類型
布林值 bit
整數 Bigint
Decimal float
繩子 varchar (UTF-8 資料庫定序)
日期時間 (ISO 格式化的字串) varchar(30)
日期時間 (UNIX 時間戳記) Bigint
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 案例 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 值,但其中存在一個以小數形式輸入的值。 這個值具有 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

若某些數值屬於其他類型 (cases.int64cases.float64) 且無法在 Azure Cosmos DB 容器內清理,則您必須在 WITH 子句中明確引用這些類型,並合併查詢結果。 以下查詢會彙總儲存在 cases 欄位中的所有 int32int64float64 類型數值:

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

在此範例中,案例數目會儲存為 int32int64float64 值。 必須擷取所有值,才能計算每個國家/地區案例的數目。

疑難排解

檢閱 自助頁面,找出已知問題或疑難排解步驟,以協助您解決 Azure Cosmos DB 查詢的潛在問題。