다음을 통해 공유


Azure SQL Database를 사용하여 데이터 가상화(미리 보기)

적용 대상:Azure SQL Database

Azure SQL Database의 데이터 가상화 기능을 사용하면 CSV(구분 기호로 구분된 텍스트 사용 필요 없음), Parquet 및 Delta(1.0)와 같은 일반적인 데이터 형식으로 데이터를 저장하는 파일에서 T-SQL(Transact-SQL) 쿼리를 실행할 수 있습니다. Azure Data Lake Storage Gen2 또는 Azure Blob Storage에서 이 데이터를 쿼리하고 조인을 사용하여 로컬로 저장된 관계형 데이터와 결합할 수 있습니다. 이렇게 하면 원본 형식 및 위치(데이터 가상화라고도 함)로 유지하면서 읽기 전용 모드로 외부 데이터에 투명하게 액세스할 수 있습니다.

개요

데이터 가상화는 다양한 시나리오 집합을 위한 파일을 쿼리하는 두 가지 방법을 제공합니다.

  • OPENROWSET 구문 - 파일의 임시 쿼리에 최적화되어 있습니다. 일반적으로 새 파일 집합의 콘텐츠 및 구조를 빠르게 탐색하는 데 사용됩니다.
  • CREATE EXTERNAL TABLE 구문 - 데이터가 데이터베이스에 로컬로 저장된 것처럼 동일한 구문을 사용하여 파일을 반복적으로 쿼리하는 데 최적화되었습니다. 외부 테이블에는 OPENROWSET 구문에 비해 몇 가지 준비 단계가 필요하지만 데이터 액세스를 보다 자세히 제어할 수 있습니다. 외부 테이블은 일반적으로 분석 워크로드 및 보고에 사용됩니다.

두 경우 모두 이 문서에서 설명한 대로 CREATE EXTERNAL DATA SOURCE T-SQL 구문을 사용하여 외부 데이터 원본을 생성해야 합니다.

파일 형식

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>/

중요합니다

항상 엔드포인트별 접두사를 사용합니다. 제공된 위치 유형 접두사는 통신을 위한 최적의 프로토콜을 선택하고 특정 스토리지 유형에서 제공하는 고급 기능을 활용하는 데 사용됩니다.

일반적인 https:// 접두사는 BULK INSERT에 대해서만 지원되며, OPENROWSET 또는 EXTERNAL TABLE와 같은 다른 사용 사례에는 지원되지 않습니다.

시작하기

데이터 가상화에 익숙하지 않고 기능을 빠르게 테스트하려면 먼저 익명 액세스를 허용하는 Bing 코로나19 데이터 세트와 같이 Azure Open Datasets에서 사용할 수 있는 퍼블릭 데이터 세트를 쿼리합니다.

다음 엔드포인트를 사용하여 Bing 코로나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;

첫 번째 쿼리의 결과 집합에 따라 WHERE, GROUP BY 및 기타 절을 추가하여 데이터 집합 탐색을 계속할 수 있습니다.

공용 데이터 세트 쿼리에 익숙해지면 자격 증명을 제공하고 액세스 권한을 부여하며 방화벽 규칙을 구성해야 하는 비공용 데이터 세트로 전환하는 것이 좋습니다. 다수의 실제 시나리오에서는 주로 프라이빗 데이터 세트를 사용하여 작동합니다.

비공용 스토리지 계정에 대한 액세스

Azure SQL Database에 로그인한 사용자는 비공용 스토리지 계정에 저장된 파일에 액세스하고 쿼리할 수 있는 권한을 부여받아야 합니다. 권한 부여 단계는 Azure SQL Database가 스토리지를 인증하는 방법에 따라 달라집니다. 인증 유형 및 관련 매개 변수는 각 쿼리와 함께 직접 제공되지 않습니다. 사용자 데이터베이스에 저장된 데이터베이스 범위 자격 증명 개체에 캡슐화됩니다. 자격 증명은 데이터베이스에서 쿼리가 실행될 때마다 스토리지 계정에 액세스하는 데 사용됩니다.

Azure SQL Database는 다음 인증 유형을 지원합니다.

  • SAS(공유 액세스 서명)
  • 관리형 아이덴티티
  • 사용자 ID를 통한 Microsoft Entra 통과 인증

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을 사용할 경우 단일 파일을 쿼리하는 다음 예제와 같은 파일 형식을 제공합니다.

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;

매개 변수 없이 호출되면 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과 마찬가지로 외부 테이블은 와일드카드를 사용하여 여러 파일 및 폴더를 쿼리할 수 있습니다. 스키마 유추는 외부 테이블에서 지원되지 않습니다.

성능 고려 사항

쿼리할 수 있는 파일 수 또는 데이터 양에는 하드 제한이 없지만 쿼리 성능은 데이터 양, 데이터 형식 및 쿼리 및 조인의 구성 방식 및 복잡성에 따라 달라집니다.

분할된 데이터 쿼리

데이터는 파티션이라고도 하는 하위 폴더로 구성되는 경우가 많습니다. 특정 폴더 및 파일만 읽도록 쿼리에 지시할 수 있습니다. 이렇게 하면 쿼리에서 읽고 처리하는 데 필요한 파일 수와 데이터 양이 줄어들어 성능이 향상됩니다. 이러한 유형의 쿼리 최적화를 파티션 정리 또는 파티션 제거라고 합니다. 쿼리 절에서 메타데이터 함수 filepath() 를 사용하여 쿼리 실행에서 파티션을 WHERE 제거할 수 있습니다.

다음 샘플 쿼리에서는 2017년 마지막 3개월 동안의 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 절에서는 지원되지 않습니다.

문제 해결

쿼리 실행 문제는 일반적으로 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 계정이 다른 테넌트에 있는 경우 공유 액세스 서명이 지원되는 방법입니다.

알려진 문제

  • SSMS(SQL Server Management Studio)에서 Always Encrypted에 대한 매개 변수화를 사용하도록 설정하면 데이터 가상화 쿼리가 Incorrect syntax near 'PUSHDOWN' 오류 메시지를 나타내며 실패합니다.