共用方式為


Azure SQL 受控執行個體的資料虛擬化

適用於:Azure SQL 受控執行個體

本文說明 Azure SQL 受控執行個體的資料虛擬化功能。 資料虛擬化可讓您在 Azure Data Lake Storage Gen2 或 Azure Blob 儲存體中以一般資料格式儲存資料的檔案上執行 Transact-SQL (T-SQL) 查詢。 您可以使用聯結,將此資料與本端儲存的關聯式資料結合。 透過資料虛擬化,您可以以唯讀模式透明地存取外部資料,同時將其保留為原始格式和位置。

概觀

資料虛擬化提供兩種方式來查詢適用於不同案例集的檔案:

  • OPENROWSET 語法:針對檔案的臨機操作查詢進行了最佳化。 通常用於快速探索一組新檔案的內容和結構。
  • CREATE EXTERNAL TABLE 語法:針對使用相同語法重複查詢檔案進行最佳化,就像資料儲存在資料庫本地一樣。 相較於 OPENROWSET 語法,外部資料表需要進行多項準備工作,但可提高您對資料存取的控制權。 使用外部資料表來處理分析性的工作負載和報告。

無論哪種情況,請使用 CREATE EXTERNAL DATA SOURCE T-SQL 語法來建立外部資料來源,如本文所示。

CREATE EXTERNAL TABLE AS SELECT 語法 也適用於 Azure SQL 受控執行個體。 這是將 T-SQL SELECT 陳述式的結果匯出至 Azure Blob 儲存體或 Azure Data Lake Storage (ADLS) Gen 2 中的 Parquet 或 CSV 檔案,並在這些檔案之上建立外部資料表。

檔案格式

直接支援 Parquet 和分隔符號文字 (CSV) 檔案格式。 當查詢以個別資料列的形式傳回每份文件時,您可藉由指定 CSV 檔案格式,間接支援 JSON 檔案格式。 您可以使用 JSON_VALUEOPENJSON,進一步剖析資料列。

儲存體類型

將檔案儲存在 Azure Data Lake Storage Gen2 或 Azure Blob 儲存體中。 若要查詢檔案,請以特定格式提供位置,並使用對應至外部來源和端點或通訊協定類型的位置類型前置詞,例如下列範例:

--Blob Storage endpoint
abs://<container>@<storage_account>.blob.core.windows.net/<path>/<file_name>.parquet

--Data Lake endpoint
adls://<container>@<storage_account>.dfs.core.windows.net/<path>/<file_name>.parquet

重要

提供的位置類型前置詞可用來選擇最佳通訊協定,以及使用特定儲存類型提供的任何進階功能。 已停用使用一般 https:// 前置詞。 一律使用端點特定的前置詞。

開始

如果您是資料虛擬化的新手,而且想要快速測試功能,請先查詢 Azure 開放資料集中可用的公用資料集,例如允許匿名存取的 Bing COVID-19 資料集

使用下列端點來查詢 BING COVID-19 資料集:

  • Parquet:abs://public@pandemicdatalake.blob.core.windows.net/curated/covid-19/bing_covid-19_data/latest/bing_covid-19_data.parquet
  • CSV:abs://public@pandemicdatalake.blob.core.windows.net/curated/covid-19/bing_covid-19_data/latest/bing_covid-19_data.csv

若要快速開始使用,請執行 T-SQL 查詢,以取得資料集的第一個深入解析。 此查詢會使用 OPENROWSET 來查詢儲存在公開可用儲存體帳戶中的檔案:

--Quick query on a file stored in a publicly available storage account:
SELECT TOP 10 *
FROM OPENROWSET(
 BULK 'abs://public@pandemicdatalake.blob.core.windows.net/curated/covid-19/bing_covid-19_data/latest/bing_covid-19_data.parquet',
 FORMAT = 'parquet'
) AS filerows

您可以根據第一個查詢的結果集附加WHEREGROUP BY及其他子句,以繼續資料集探索。

如果 SQL 受控執行個體上的第一個查詢失敗,則該執行個體可能會限制對 Azure 儲存體帳戶的存取。 在繼續查詢之前,請先諮詢您的網路專家以啟用存取權。

當您熟悉查詢公用資料集時,請考慮切換至需要提供認證、授與存取權限和設定防火牆規則的非公用資料集。 在許多實際案例中,您主要使用私有資料集進行操作。

存取非公用儲存體帳戶

登入 SQL 受控執行個體的使用者必須獲得授權,才能存取和查詢儲存在非公用儲存體帳戶中的檔案。 授權步驟取決於 SQL 受控執行個體向儲存體帳戶進行驗證的方式。 驗證類型和任何相關參數不會直接隨每個查詢一起提供。 儲存在使用者資料庫中的資料庫範圍認證物件會封裝此資訊。 資料庫會在查詢執行時隨時使用認證來存取儲存體帳戶。

Azure SQL 受控執行個體支援下列驗證類型:

  • 受管理的識別
  • 共用存取簽章 (SAS)

受控識別是 Microsoft Entra ID (之前稱為 Azure Active Directory) 的一項功能,可為 Azure 服務 (例如 Azure SQL 受控執行個體) 提供在 Microsoft Entra ID 中管理的身分識別。 您可以使用此身分識別來授權非公用儲存體帳戶中的資料存取要求。 Azure SQL 受控執行個體等服務具有系統指派的受控識別,並且可以有一個或多個使用者指派的受控識別。 您在執行 Azure SQL 受控執行個體的資料虛擬化功能時,可以使用系統指派的受控識別或使用者指派的受控識別。

Azure 儲存體管理員必須首先將權限授與受控識別,才能存取資料。 將權限授與 SQL 受控執行個體的系統指派受控識別,就像授與任何其他 Microsoft Entra 使用者權限的方式一樣。 例如:

  1. 在 Azure 入口網站中,請在儲存體帳戶的 [存取控制 (IAM)] 頁面中選取 [新增角色指派]。
  2. 選擇 [儲存體 Blob 資料讀者] 內建 Azure RBAC 角色。 此角色提供必要 Azure Blob 儲存體容器受控識別的讀取存取權。
    • 您可以授與更細緻的檔案子集權限,而不是將儲存體 Blob 資料讀者 Azure RBAC 角色授與受控識別。 所有需要存取此資料 中個別檔案 的使用者也必須具有所有父資料夾的 執行 權限,直到根資料夾 (容器)。 如需詳細資訊,請參閱在 Azure Data Lake Storage Gen2 中設定 ACL
  3. 在下一頁的 [存取權指派對象] 中,選取 [受控識別]。 選取 [+ 選取成員],然後在 [受控識別] 下拉式清單下,選取所需的受控識別。 如需詳細資訊,請參閱使用 Azure 入口網站指派 Azure 角色
  4. 然後,為受管理識別驗證建立資料庫範圍認證。 請注意,在下列範例中 'Managed Identity' 是硬式編碼字串。
-- Optional: Create MASTER KEY if it doesn't exist in the database:
-- CREATE MASTER KEY ENCRYPTION BY PASSWORD = '<Some Very Strong Password Here>'
GO
CREATE DATABASE SCOPED CREDENTIAL MyCredential
WITH IDENTITY = 'Managed Identity'

外部資料來源

外部資料來源是一種抽象概念,可跨多個查詢輕鬆參考檔案位置。 若要查詢公用位置,請在建立外部資料來源時指定檔案位置:

CREATE EXTERNAL DATA SOURCE MyExternalDataSource
WITH (
    LOCATION = 'abs://public@pandemicdatalake.blob.core.windows.net/curated/covid-19/bing_covid-19_data/latest'
)

若要存取非公用儲存帳戶,請指定位置,並參考具有封裝驗證參數的資料庫範圍憑證。 下列指令碼會建立指向檔案路徑的外部資料來源,並參考資料庫範圍的認證:

-- Create external data source that points to the file path, and that references a database scoped credential:
CREATE EXTERNAL DATA SOURCE MyPrivateExternalDataSource
WITH (
    LOCATION = 'abs://public@pandemicdatalake.blob.core.windows.net/curated/covid-19/bing_covid-19_data/latest'
        CREDENTIAL = [MyCredential];
)

使用 OPENROWSET 查詢資料來源

OPENROWSET 語法可啟用即時特定查詢,同時只需建立最少量的必要資料庫物件。

OPENROWSET 只需要建立外部資料來源 (可能為認證),而不是外部表格方法,這需要外部檔案格式外部表格本身。

DATA_SOURCE 參數值會自動在前面加上 BULK 參數,以形成檔案的完整路徑。

使用 OPENROWSET時,請提供檔案的格式,例如下列範例,以查詢單一檔案:

SELECT TOP 10 *
FROM OPENROWSET(
 BULK 'bing_covid-19_data.parquet',
 DATA_SOURCE = 'MyExternalDataSource',
 FORMAT = 'parquet'
) AS filerows;

查詢多個檔案和資料夾

OPENROWSET 命令也允許使用 BULK 路徑中的萬用字元來查詢多個檔案或資料夾。

下列範例使用 NYC 黃色計程車車程記錄開放資料集

首先,建立外部資料來源:

--Create the data source first:
CREATE EXTERNAL DATA SOURCE NYCTaxiExternalDataSource
WITH (LOCATION = 'abs://nyctlc@azureopendatastorage.blob.core.windows.net');

現在,您可以查詢資料夾中所有副檔名為 的檔案 .parquet 。 例如,下列查詢僅適用於符合名稱模式的檔案:

--Query all files with .parquet extension in folders matching name pattern:
SELECT TOP 10 *
FROM OPENROWSET(
 BULK 'yellow/puYear=*/puMonth=*/*.parquet',
 DATA_SOURCE = 'NYCTaxiExternalDataSource',
 FORMAT = 'parquet'
) AS filerows;

查詢多個檔案或資料夾時,使用單一 OPENROWSET 存取的所有檔案都必須具有相同結構 (例如相同數目的資料行和資料類型)。 資料夾無法以遞迴方式周遊。

結構描述推斷

自動結構描述推斷可協助您快速撰寫查詢,以及在不知道檔案結構描述時探索資料。 結構描述推斷只適用於 Parquet 檔案。

雖然方便,但推斷的資料類型可能大於實際的資料類型,因為來源檔案中可能沒有足夠的資訊來確保使用適當的資料類型。 這可能會導致查詢效能不佳。 例如,parquet 檔案不包含有關字元欄長度上限的中繼資料,因此執行個體會將其推斷為 varchar(8000)。

使用 sp_describe_first_results_set 預存程序來檢查您的查詢產生的資料類型,如下列範例所示:

EXEC sp_describe_first_result_set N'
 SELECT
 vendorID, tpepPickupDateTime, passengerCount
 FROM
 OPENROWSET(
  BULK ''yellow/*/*/*.parquet'',
  DATA_SOURCE = ''NYCTaxiExternalDataSource'',
  FORMAT=''parquet''
 ) AS nyc';

知道資料類型後,請使用 WITH 子句來指定它們以提升效能:

SELECT TOP 100
 vendorID, tpepPickupDateTime, passengerCount
FROM
OPENROWSET(
 BULK 'yellow/*/*/*.parquet',
 DATA_SOURCE = 'NYCTaxiExternalDataSource',
 FORMAT='PARQUET'
 )
WITH (
vendorID varchar(4), -- we're using length of 4 instead of the inferred 8000
tpepPickupDateTime datetime2,
passengerCount int
) AS nyc;

由於無法自動判斷 CSV 檔案的欄位結構,因此請務必使用 WITH 子句指定資料行:

SELECT TOP 10 id, updated, confirmed, confirmed_change
FROM OPENROWSET(
 BULK 'bing_covid-19_data.csv',
 DATA_SOURCE = 'MyExternalDataSource',
 FORMAT = 'CSV',
 FIRSTROW = 2
)
WITH (
 id int,
 updated date,
 confirmed int,
 confirmed_change int
) AS filerows;

檔案中繼資料函式

查詢多個檔案或資料夾時,您可以使用 filepath()filename() 函式來讀取檔案中繼資料,並取得結果集來源中資料列的檔案名稱、完整路徑或部分路徑:

--Query all files and project file path and file name information for each row:
SELECT TOP 10 filerows.filepath(1) as [Year_Folder], filerows.filepath(2) as [Month_Folder],
filerows.filename() as [File_name], filerows.filepath() as [Full_Path], *
FROM OPENROWSET(
 BULK 'yellow/puYear=*/puMonth=*/*.parquet',
 DATA_SOURCE = 'NYCTaxiExternalDataSource',
 FORMAT = 'parquet') AS filerows;
--List all paths:
SELECT DISTINCT filerows.filepath(1) as [Year_Folder], filerows.filepath(2) as [Month_Folder]
FROM OPENROWSET(
 BULK 'yellow/puYear=*/puMonth=*/*.parquet',
 DATA_SOURCE = 'NYCTaxiExternalDataSource',
 FORMAT = 'parquet') AS filerows;

若在沒有參數的情況下進行呼叫時,filepath() 函式會傳回資料列來源的檔案路徑。 在 DATA_SOURCE 中使用 OPENROWSET 時,其會傳回相對於 DATA_SOURCE 的路徑,否則會傳回完整的檔案路徑。

若以參數進行呼叫,則會傳回路徑的一部分,該部分會與參數中所指定位置上的萬用字元相符。 例如,參數值 1 會傳回符合第一個通配符的路徑部分。

filepath() 函式也可用於篩選和匯總資料列:

SELECT
 r.filepath() AS filepath
 ,r.filepath(1) AS [year]
 ,r.filepath(2) AS [month]
 ,COUNT_BIG(*) AS [rows]
FROM OPENROWSET(
 BULK 'yellow/puYear=*/puMonth=*/*.parquet',
DATA_SOURCE = 'NYCTaxiExternalDataSource',
FORMAT = 'parquet'
 ) AS r
WHERE
 r.filepath(1) IN ('2017')
 AND r.filepath(2) IN ('10', '11', '12')
GROUP BY
 r.filepath()
 ,r.filepath(1)
 ,r.filepath(2)
ORDER BY
 filepath;

在 OPENROWSET 頂端建立檢視

您可以建立和使用檢視來包裝 OPENROWSET 查詢,以便輕鬆地重複使用基礎查詢:

CREATE VIEW TaxiRides AS
SELECT *
FROM OPENROWSET(
 BULK 'yellow/puYear=*/puMonth=*/*.parquet',
 DATA_SOURCE = 'NYCTaxiExternalDataSource',
 FORMAT = 'parquet'
) AS filerows

使用 filepath() 函式將具有檔案位置資料的資料行新增至檢視也很方便,可讓您更容易且更有效能地進行篩選。 使用檢視可以減少檔案數目,以及檢視頂端的查詢在依任何這些資料行篩選時需要讀取和處理的資料量:

CREATE VIEW TaxiRides AS
SELECT *
 , filerows.filepath(1) AS [year]
 , filerows.filepath(2) AS [month]
FROM OPENROWSET(
 BULK 'yellow/puYear=*/puMonth=*/*.parquet',
 DATA_SOURCE = 'NYCTaxiExternalDataSource',
 FORMAT = 'parquet'
) AS filerows

檢視也會啟用報告和分析工具 (例如 Power BI) 來取用 OPENROWSET 的結果。

外部資料表

外部表封裝了對檔案的訪問,因此查詢它們的感覺與查詢儲存在使用者表中的本地關係資料幾乎相同。 若要建立外部資料表,您必須有外部資料來源和外部檔案格式物件:

--Create external file format
CREATE EXTERNAL FILE FORMAT DemoFileFormat
WITH (
 FORMAT_TYPE=PARQUET
)
GO

--Create external table:
CREATE EXTERNAL TABLE tbl_TaxiRides(
 vendorID VARCHAR(100) COLLATE Latin1_General_BIN2,
 tpepPickupDateTime DATETIME2,
 tpepDropoffDateTime DATETIME2,
 passengerCount INT,
 tripDistance FLOAT,
 puLocationId VARCHAR(8000),
 doLocationId VARCHAR(8000),
 startLon FLOAT,
 startLat FLOAT,
 endLon FLOAT,
 endLat FLOAT,
 rateCodeId SMALLINT,
 storeAndFwdFlag VARCHAR(8000),
 paymentType VARCHAR(8000),
 fareAmount FLOAT,
 extra FLOAT,
 mtaTax FLOAT,
 improvementSurcharge VARCHAR(8000),
 tipAmount FLOAT,
 tollsAmount FLOAT,
 totalAmount FLOAT
)
WITH (
 LOCATION = 'yellow/puYear=*/puMonth=*/*.parquet',
 DATA_SOURCE = NYCTaxiExternalDataSource,
 FILE_FORMAT = DemoFileFormat
);
GO

建立外部資料表之後,您可以像查詢任何其他資料表一樣:

SELECT TOP 10 *
FROM tbl_TaxiRides;

OPENROWSET,外部表支援使用通配符查詢多個檔案和資料夾。 不過,外部資料表不支援結構描述推斷。

效能考量

您可以查詢的檔案數目或資料量沒有硬性限制,但查詢效能取決於資料量、資料格式、資料的組織方式,以及查詢和聯結的複雜性。

查詢分割區的資料

資料通常組織在子資料夾中,也稱為分割區。 您可以指示 SQL 受控執行個體只查詢特定資料夾和檔案。 這麼做會減少查詢需要讀取和處理的檔案數目和資料量,進而提升效能。 這種類型的查詢最佳化稱為資料分割剪除或資料分割刪除。 您可以在查詢子句中使用filepath()中繼資料函式WHERE,從查詢執行中消除分割區。

下列範例查詢只會讀取 2017 年最後三個月的 NYC Yellow Taxi 資料檔案:

SELECT
    r.filepath() AS filepath
    ,r.filepath(1) AS [year]
    ,r.filepath(2) AS [month]
    ,COUNT_BIG(*) AS [rows]
FROM OPENROWSET(
        BULK 'yellow/puYear=*/puMonth=*/*.parquet',
        DATA_SOURCE = 'NYCTaxiExternalDataSource',
        FORMAT = 'parquet'
    )
WITH (
    vendorID INT
) AS [r]
WHERE
    r.filepath(1) IN ('2017')
    AND r.filepath(2) IN ('10', '11', '12')
GROUP BY
    r.filepath()
    ,r.filepath(1)
    ,r.filepath(2)
ORDER BY
    filepath;

如果您的儲存資料未分割,請考慮進行資料分割以提升查詢效能。

如果您使用外部資料表, filepath()filename() 函式受支援,但子句中不支援 WHERE 。 您仍然可以依filenamefilepath篩選,如果您在計算資料行中使用它們,例如下列範例所示:

CREATE EXTERNAL TABLE tbl_TaxiRides (
 vendorID VARCHAR(100) COLLATE Latin1_General_BIN2,
 tpepPickupDateTime DATETIME2,
 tpepDropoffDateTime DATETIME2,
 passengerCount INT,
 tripDistance FLOAT,
 puLocationId VARCHAR(8000),
 doLocationId VARCHAR(8000),
 startLon FLOAT,
 startLat FLOAT,
 endLon FLOAT,
 endLat FLOAT,
 rateCodeId SMALLINT,
 storeAndFwdFlag VARCHAR(8000),
 paymentType VARCHAR(8000),
 fareAmount FLOAT,
 extra FLOAT,
 mtaTax FLOAT,
 improvementSurcharge VARCHAR(8000),
 tipAmount FLOAT,
 tollsAmount FLOAT,
 totalAmount FLOAT,
 [Year]  AS CAST(filepath(1) AS INT), --use filepath() for partitioning
 [Month]  AS CAST(filepath(2) AS INT) --use filepath() for partitioning
)
WITH (
 LOCATION = 'yellow/puYear=*/puMonth=*/*.parquet',
 DATA_SOURCE = NYCTaxiExternalDataSource,
 FILE_FORMAT = DemoFileFormat
);
GO

SELECT *
      FROM tbl_TaxiRides
WHERE
      [year]=2017
      AND [month] in (10,11,12);

如果您的儲存資料未分割,請考慮進行資料分割以提升查詢效能。

統計資料

收集外部資料的統計資料,是最佳化查詢的最重要工作之一。 執行個體愈了解您的資料,執行查詢的速度就愈快。 SQL 引擎查詢最佳化工具是以成本為基礎的最佳化工具。 它會比較各種查詢方案的成本,然後選擇成本最低的方案。 在大多數情況下,它會選擇執行最快的方案。

自動建立統計資料

Azure SQL 受控執行個體會分析傳入的使用者查詢是否缺少統計資料。 如果缺少統計資料,查詢最佳化工具會自動在查詢述詞或聯結條件中的個別資料行上建立統計資料,以改善查詢計畫的基數估計值。 自動建立統計資料是同步進行的,因此,如果您的資料行缺少統計資料,查詢效能可能會略為降低。 為單一資料行建立統計資料的時間,取決於目標檔案的大小。

OPENROWSET 手動統計資料

您可以使用OPENROWSET預存程序來建立路徑的單欄統計資料,方法是傳遞具有單一欄作為參數的選取查詢:

EXEC sys.sp_create_openrowset_statistics N'
SELECT pickup_datetime
FROM OPENROWSET(
 BULK ''abs://public@pandemicdatalake.blob.core.windows.net/curated/covid-19/bing_covid-19_data/latest/*.parquet'',
 FORMAT = ''parquet'') AS filerows
';

根據預設,執行個體會使用資料集中提供的 100% 資料來建立統計資料。 您可以選擇性地使用 TABLESAMPLE 選項,將取樣大小指定為百分比。 若要為多個資料行建立單一資料行統計資料,請針對每個資料行執行 sys.sp_create_openrowset_statistics。 您無法為 OPENROWSET 路徑建立多資料行統計資料。

若要更新現有的統計資料,請先使用 sys.sp_drop_openrowset_statistics 預存程序卸除統計資料,然後使用 sys.sp_create_openrowset_statistics 重新建立統計資料:

EXEC sys.sp_drop_openrowset_statistics N'
SELECT pickup_datetime
FROM OPENROWSET(
 BULK ''abs://public@pandemicdatalake.blob.core.windows.net/curated/covid-19/bing_covid-19_data/latest/*.parquet'',
 FORMAT = ''parquet'') AS filerows
';

外部資料表手動統計資料

在外部資料表上建立統計資料的語法,類似於用於一般使用者資料表的語法。 若要建立資料行的統計資料,請提供統計資料物件名稱和資料行名稱:

CREATE STATISTICS sVendor
ON tbl_TaxiRides (vendorID)
WITH FULLSCAN, NORECOMPUTE;

WITH 選項是必要項目,而且針對取樣大小的允許選項為 FULLSCANSAMPLE n 百分比。

  • 若要為多個資料行建立單一資料行統計資料,請針對每個資料行執行 CREATE STATISTICS
  • 不支援多欄統計資料。

疑難排解

查詢執行問題通常會在 SQL 受控執行個體無法存取檔案位置時發生。 相關的錯誤訊息可能會報告存取權限不足、位置不存在、檔案正在由另一個進程使用,或無法列出該目錄。 在大多數情況下,這些錯誤表示網路流量控制策略阻止了對檔案的訪問,或者使用者缺乏存取權限。 檢查以下項目:

  • 錯誤或拼字錯誤的位置路徑。
  • SAS 金鑰有效性。 它可能已過期、包含拼字錯誤或以問號開頭。
  • 允許 SAS 金鑰權限。 至少讀取,如果使用萬用字元,請列出
  • 封鎖了儲存體帳戶上的輸入流量。 如需詳細資料,請檢查 管理 Azure 儲存體的虛擬網路規則, 並確定允許從 SQL 受控執行個體 VNet 存取。
  • 使用 儲存體端點原則封鎖 SQL 受控執行個體上的輸出流量。 允許通往儲存體帳戶的輸出流量。
  • 管理式身分識別存取權限。 請確定執行個體的受管理的識別具有存取儲存帳戶的權限。
  • 資料庫的相容性層級必須是 130 或更高,才能執行資料虛擬化查詢。

CREATE EXTERNAL TABLE AS SELECT (CETAS)

CREATE EXTERNAL TABLE AS SELECT (CETAS) 可讓您將資料從 SQL 受控執行個體匯出至外部儲存體帳戶。 您可以使用 CETAS 在 Azure Blob 儲存體或 Azure Data Lake Storage (ADLS) Gen2 中的 Parquet 或 CSV 檔案的基礎上建立外部資料表。 CETAS 也可以平行將 T-SQL SELECT 陳述式的結果匯出至建立的外部資料表。 這些功能可能會發生資料外流風險,因此 Azure SQL 受控執行個體預設會停用 CETAS。 要啟用,請參閱 CREATE EXTERNAL TABLE AS SELECT (CETAS)

限制

已知問題

  • 在 SQL Server Management Studio (SSMS) 中啟用 Always Encrypted 的參數化時,資料虛擬化查詢失敗並顯示 Incorrect syntax near 'PUSHDOWN' 錯誤訊息。