次の方法で共有


Azure SQL Database を使用したデータ仮想化 (プレビュー)

適用対象:Azure SQL データベース

Azure SQL Database のデータ仮想化機能を使用すると、CSV (区切りテキストを使用する必要はありません)、Parquet、デルタ (1.0) などの一般的なデータ形式でデータを格納するファイルに対して、Transact-SQL (T-SQL) クエリを実行できます。 このデータは、Azure Data Lake Storage Gen2 または Azure Blob Storage でクエリを実行し、結合を使用してローカルに格納されたリレーショナル データと組み合わせることができます。 こうすることで、外部データ (読み取り専用モード内) を元の形式と場所に保持したまま透過的にアクセスすることができます。これはデータの仮想化とも呼ばれています。

概要

データ仮想化では、さまざまなシナリオのセットを対象としたファイルのクエリを実行する 2 つの方法が提供されます。

  • OPENROWSET 構文 – ファイルのアドホック クエリ用に最適化されています。 通常は、新しいファイル セットのコンテンツと構造をすばやく調べるために使用されます。
  • CREATE EXTERNAL TABLE 構文 – データがデータベースにローカルに保存されているのと同じ構文で、ファイルを繰り返しクエリするために最適化されています。 外部テーブルでは、OPENROWSET 構文と比較していくつかの準備ステップが必要ですが、データ アクセスの制御をより強化することができます。 外部テーブルは、通常、分析ワークロードとレポートに使用されます。

どちらの場合も、この記事で示すように、T-SQL の CREATE EXTERNAL DATA SOURCE 構文を使って外部データ ソースを作成する必要があります。

ファイル形式

Parquet 形式と区切りテキスト (CSV) ファイル形式が直接サポートされています。 JSON ファイル形式は、クエリがすべてのドキュメントを個別の行として返す CSV ファイル形式を指定することで間接的にサポートされます。 JSON_VALUEOPENJSON を使用して、行をさらに解析できます。

ストレージの種類

ファイルは、Azure Data Lake Storage Gen2 または Azure Blob Storage に格納できます。 ファイルのクエリを実行するには、特定の形式で場所を指定し、次の例のように、外部ソースとエンドポイントまたはプロトコルの種類に対応する場所の種類のプレフィックスを使用する必要があります。

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

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

Von Bedeutung

常にエンドポイント固有のプレフィックスを使用します。 指定された場所の種類のプレフィックスは、通信に最適なプロトコルを選び、特定のストレージの種類によって提供される高度な機能を利用するために使用されます。

ジェネリック https:// プレフィックスは、 BULK INSERTでのみサポートされますが、 OPENROWSETEXTERNAL TABLEを含む他のユース ケースではサポートされません。

始めましょう

データの仮想化が初めてで、機能をすばやくテストしたい場合は、匿名アクセスを許可する Bing COVID-19 データセットなど、Azure Open Datasets で利用可能なパブリック データ セットをクエリすることから始めます。

次のエンドポイントを使用して、Bing COVID-19 データセットにクエリを実行します。

  • 寄木細工: 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 、およびその他の句を追加することで、データ セットの探索を続行できます。

パブリック データ セットのクエリに慣れたら、資格情報の提供、アクセス権の付与、ファイアウォール規則の構成を必要とする非パブリック データ セットへの切り替えを検討してください。 多くの実世界のシナリオでは、主にプライベート データ セットを操作します。

非パブリック ストレージ アカウントにアクセスする

Azure SQL Database にログインしているユーザーは、非パブリック ストレージ アカウントに格納されているファイルにアクセスしてクエリを実行する権限を持っている必要があります。 承認手順は、Azure SQL Database がストレージを認証する方法によって異なります。 認証の種類と関連するパラメーターは、各クエリで直接提供されるわけではありません。 これらは、ユーザー データベースに格納されているデータベース スコープ資格情報オブジェクトにカプセル化されます。 資格情報は、クエリが実行されるたびにストレージ アカウントにアクセスするためにデータベースで使用されます。

Azure SQL Database では、次の認証の種類がサポートされています。

  • Shared Access Signature (SAS)
  • マネージド ID
  • ユーザー ID を使用した Microsoft Entra パススルー認証

Shared Access Signature (SAS) は、ストレージ アカウント内のファイルへの委任されたアクセスを提供します。 SAS では、有効期間、許可されたアクセス許可、許容できる IP アドレス範囲など、付与するアクセスの種類をきめ細かく制御できます。 作成された SAS トークンは取り消したり削除したりできず、有効期間が切れるまでアクセスを許可します。

  1. SAS トークンは、複数の方法で取得できます。

  2. 外部データにアクセスするには、SAS を介して [読み取り] および [リスト] アクセス許可を付与します。 現在、Azure SQL Database でのデータ仮想化は読み取り専用です。

  3. Azure SQL Database でデータベース スコープの資格情報を作成するには、まず データベース マスター キーを作成する必要があります (まだ存在しない場合)。 資格情報に SECRETが必要な場合は、データベース マスター キーが必要です。

    -- Create MASTER KEY if it doesn't exist in the database:
    CREATE MASTER KEY 
    ENCRYPTION BY PASSWORD = '<Some Very Strong Password Here>';
    
  4. SAS トークンが生成されると、トークンの先頭に疑問符 (?) が含まれます。 このトークンを使用するには、資格情報の作成時につけられた疑問符 (?) を削除する必要があります。 例えば次が挙げられます。

    CREATE DATABASE SCOPED CREDENTIAL MyCredential
    WITH IDENTITY = 'SHARED ACCESS SIGNATURE',
    SECRET = 'sv=secret string here';
    

匿名アカウントを使用したパブリック ストレージへのアクセス

目的のデータセットでパブリック アクセス (匿名アクセスとも呼ばれます) が許可されている場合、Azure Storage が適切に構成されている限り、資格情報は必要ありません。 コンテナーと BLOB の匿名読み取りアクセスの構成に関するページを参照してください。

外部データ ソース

外部データ ソースは、複数のクエリ間でファイルの場所を簡単に参照できるように抽象化したものです。 パブリックの場所に対してクエリを実行する場合、外部データ ソースの作成時に指定する必要があるのはファイルの場所だけです。

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 pointing to the file path, and referencing database-scoped credential:
CREATE EXTERNAL DATA SOURCE MyPrivateExternalDataSource
WITH (
    LOCATION = 'abs://<privatecontainer>@privatestorageaccount.blob.core.windows.net/dataset/' 
       CREDENTIAL = [MyCredential]
);

OPENROWSET を使用してデータ ソースのクエリを実行する

OPENROWSET 構文を使用すると、必要な最小限の数のデータベース オブジェクトだけを作成しながら、アドホック クエリをすぐに実行できます。

OPENROWSET は、外部ファイル形式外部テーブル自体を必要とする外部テーブルアプローチとは対照的に、外部データソース(および場合によっては資格情報)を作成するだけで済みます。

DATA_SOURCEパラメーター値が BULK パラメーターの前に自動的に付加され、ファイルへの完全なパスが形成されます。

OPENROWSETを使用する場合は、次の例のように、ファイルの形式を指定して1 つのファイルに対してクエリを実行します。

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;

複数のファイルまたはフォルダー に対してクエリを実行する場合、1 つの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;

パラメーターを指定せずに呼び出した場合、filepath()関数は行の元となるファイルパスを返します。 DATA_SOURCEOPENROWSETで使用されている場合は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
);

--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
);

外部テーブルが作成されると、他のテーブルと同様にクエリを実行できます。

SELECT TOP 10 *
FROM tbl_TaxiRides;

OPENROWSETと同様に、外部テーブルを使用すると、ワイルドカードを使用して複数のファイルとフォルダーのクエリを実行できます。 スキーマ推論は、外部テーブルではサポートされていません。

パフォーマンスに関する考慮事項

クエリを実行できるファイルの数やデータの量にハード制限はありませんが、クエリのパフォーマンスは、データの量、データ形式、データの整理方法、およびクエリと結合の複雑さによって異なります。

パーティション分割されたデータに対してクエリを実行する

データは、多くの場合、パーティションとも呼ばれるサブフォルダーに整理されます。 特定のフォルダーとファイルのみを読み取るクエリを指示できます。 そうすれば、クエリで読み込んで処理する必要があるファイルの数とデータの量が減り、パフォーマンスが向上します。 この種類のクエリ最適化は、パーティション プルーニングまたは パーティションの削除 と呼ばれます。 クエリのWHERE句でメタデータ関数filepath()を使用して、クエリの実行からパーティションを削除できます。

次のクエリ サンプルでは、2017 年の過去 3 か月間についてのみ、NYC イエロー タクシーのデータ ファイルが読み取られます。

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 句ではサポートされていません。

トラブルシューティング

クエリの実行に関する問題は、通常、Azure SQL Database がファイルの場所にアクセスできないことが原因で発生します。 関連するエラー メッセージで、アクセス権が十分ではない、場所またはファイル パスが存在しない、ファイルが別のプロセスで使われている、あるいはディレクトリの一覧を取得できない、などが報告される場合があります。 ほとんどの場合、ネットワークトラフィックコントロールポリシーやアクセス権の欠如により、ファイルへのアクセスがブロックされていることを示します。 これが確認すべきことです。

  • ロケーションパスが誤っているか、または入力ミスがあります。
  • SAS キーの有効性: 有効期限が切れている、タイプミスが含まれている、疑問符で始まっている可能性があります。
  • SAS キーのアクセス許可: 少なくとも読み取りアクセス許可、およびワイルドカードが使用されている場合はリストのアクセス許可が必要です。
  • ストレージ アカウントでインバウンドトラフィックがブロックされました。 Azure Storage の仮想ネットワーク 規則の管理を確認します
  • マネージド ID アクセス権: Azure SQL Database のマネージド ID にストレージ アカウントへのアクセス権が付与されていることを確認します。
  • データ仮想化クエリを機能させるには、データベースの互換性レベルを 130 以上とする必要があります。

制限事項

  • 現時点では、外部テーブルの統計は Azure SQL Database ではサポートされていません。
  • 現時点では、 CREATE EXTERNAL TABLE AS SELECT は Azure SQL Database では使用できません。
  • 行レベルのセキュリティ機能は、外部テーブルではサポートされていません。
  • 外部テーブルの列に対して、動的データ マスク ルールを定義することはできません。
  • マネージド ID はテナント間のシナリオをサポートしていません。Azure Storage アカウントが別のテナントにある場合、Shared Access Signature がサポートされている方法です。

既知の問題

  • Always Encrypted のパラメーター化が SQL Server Management Studio (SSMS) で有効になっている場合、データ仮想化クエリが失敗し、エラー メッセージ Incorrect syntax near 'PUSHDOWN' が表示されます。