스트림 소개¶
이 항목에서는 스트림을 사용한 변경 데이터 캡처의 주요 개념을 소개합니다.
이 항목의 내용:
오프셋 저장소¶
스트림은 생성될 때 어떤 시점(오프셋 이라고 함)을 오브젝트의 현재 트랜잭션 버전으로 초기화하여 원본 오브젝트(예: 테이블, 외부 테이블 또는 뷰의 기본 테이블)의 모든 행에 대한 초기 스냅샷을 논리적으로 만듭니다. 그러면 스트림에서 사용되는 변경 내용 추적 시스템이 이 스냅샷을 만든 이후의 DML 변경 사항에 대한 정보를 기록합니다. 변경 레코드는 변경 이전 및 이후 행의 상태를 제공합니다. 변경 정보는 추적 대상 원본 오브젝트의 열 구조를 미러링하며 각 변경 이벤트를 설명하는 추가적인 메타데이터 열을 포함합니다.
스트림 자체에는 테이블 데이터가 포함되지 않음 에 유의하십시오. 스트림은 원본 오브젝트에 대한 오프셋만 저장하며 원본 오브젝트에 대한 버전 관리 내역을 활용하여 CDC 레코드를 반환합니다. 테이블의 첫 번째 스트림이 생성되면, 원본 테이블에 숨겨진 열이 여러 개 추가되고 변경 내용 추적 메타데이터가 저장되기 시작합니다. 이러한 열은 소량의 저장소를 사용합니다. 스트림을 쿼리할 때 반환되는 CDC 레코드는 스트림에 저장된 오프셋 과 테이블에 저장된 변경 내용 추적 메타데이터 의 조합만을 사용합니다. Streams on Views에 대해 뷰 및 기본 테이블이 이러한 테이블에 숨겨진 열을 추가하려면 변경 내용 추적을 명시적으로 활성화해야 합니다.
스트림을 책의 페이지(즉, 원본 오브젝트)에서 시점을 나타내는 책갈피로 생각하면 이해하기 쉽습니다. 책갈피를 삭제한 후 책의 다른 위치에 다른 책갈피를 삽입할 수 있습니다. 유사하게, 스트림을 삭제한 후 동일하거나 다른 시점에 생성하여(다양한 시점에 연속적으로 스트림을 생성하거나 Time Travel 을 사용하여) 동일하거나 다른 오프셋에서 오브젝트의 변경 기록을 사용할 수 있습니다.
CDC 레코드 컨슈머의 한 가지 예는 데이터 파이프라인 이며, 여기서는 마지막 추출 이후에 변경된 스테이징 테이블의 데이터만 변환되어 다른 테이블로 복사됩니다.
테이블 버전 관리¶
한 개 이상의 DML 문이 포함된 트랜잭션이 테이블에 커밋될 때마다 새 테이블 버전이 생성됩니다. 이는 다음 테이블 타입에 적용됩니다.
표준 테이블
디렉터리 테이블
외부 테이블
뷰의 기본 테이블
테이블에 대한 트랜잭션 내역에서 스트림 오프셋은 두 테이블 버전 사이에 위치합니다. 스트림을 쿼리하면 오프셋 이후로부터 현재 시간 또는 현재 시간 이전에 커밋된 트랜잭션에 의한 변경 사항이 반환됩니다.
다음 예는 타임라인에 10개의 커밋된 버전이 있는 원본 테이블을 보여줍니다. 현재 스트림 s1
의 오프셋은 테이블 버전 v3
과 v4
사이에 있습니다. 스트림을 쿼리(또는 사용)하면, 반환되는 레코드에는 테이블 타임라인에서 스트림 오프셋 직후의 버전인 테이블 버전 v4
와 타임라인에서 가장 최근에 커밋된 테이블 버전인 v10
(포함) 사이의 모든 트랜잭션이 포함됩니다.
스트림은 스트림의 현재 오프셋부터 테이블의 현재 버전까지의 최소 변경 사항 집합을 제공합니다.
여러 쿼리가 오프셋을 변경하지 않고 스트림에서 똑같은 변경 데이터를 독립적으로 사용할 수 있습니다. 스트림은 오프셋이 DML 트랜잭션에서 사용되는 경우에 한해서만 오프셋을 이동합니다. 이 동작은 명시적 및 자동 커밋 트랜잭션 모두에 적용됩니다. (기본적으로 DML 문이 실행될 때 자동 커밋 트랜잭션이 암시적으로 시작되고 문이 완료되면 트랜잭션이 커밋됩니다. 이러한 동작은 AUTOCOMMIT 매개 변수로 제어됩니다.) 명시적 트랜잭션 내에서도 스트림만 쿼리하면 오프셋이 이동되지 않습니다. DML 문에서 스트림의 내용을 사용해야 합니다.
참고
DML 작업에서 변경 데이터를 사용하지 않고 스트림의 오프셋을 현재 테이블 버전으로 진행하려면 다음 작업 중 하나를 완료하십시오.
스트림을 다시 생성합니다(CREATE OR REPLACE STREAM 구문 사용).
현재 변경 데이터를 임시 테이블에 삽입합니다. INSERT 문에서 스트림을 쿼리하되, 모든 변경 데이터를 필터링하는 WHERE절(예:
WHERE 0 = 1
)을 포함합니다.
명시적 트랜잭션에서 SQL 문이 스트림을 쿼리하는 경우, 스트림은 문이 실행될 때가 아닌 트랜잭션이 시작될 때 스트림 이동 지점(즉, 타임스탬프)에서 쿼리됩니다. 이 동작은 새 테이블을 기존 스트림의 행으로 채우는 DML 문과 CREATE TABLE … AS SELECT(CTAS) 문에 모두 적용됩니다.
스트림을 조회하는 DML 문은 트랜잭션이 성공적으로 커밋하는 경우에만 스트림의 모든 변경 데이터를 사용합니다. 여러 문이 스트림의 똑같은 변경 레코드에 액세스하도록 하려면 명시적 트랜잭션 문(BEGIN .. COMMIT)으로 감싸십시오. 이것은 스트림을 잠그게 됩니다. 병렬 트랜잭션에서 원본 오브젝트에 대한 DML 업데이트는 변경 내용 추적 시스템에 의해 추적되지만, 명시적 트랜잭션 문이 커밋되고 기존 변경 데이터가 사용될 때까지 스트림이 업데이트되지 않습니다.
Repeatable Read 격리¶
스트림은 Repeatable Read 격리를 지원합니다. Repeatable Read 모드에서는 트랜잭션의 여러 SQL 문이 스트림의 똑같은 레코드 세트를 참조합니다. 이는 테이블에 지원되는 READ COMMITTED 모드와 다릅니다. 이 모드에서는 문이 해당 변경 사항이 아직 커밋되지 않은 경우에도 동일한 트랜잭션 내에서 실행된 이전 문에 의한 변경 사항을 참조합니다.
트랜잭션에서 스트림이 반환하는 델타 레코드는 스트림의 현재 위치부터 트랜잭션 시작 시간까지의 범위입니다. 트랜잭션이 커밋되면 스트림 위치가 트랜잭션 시작 시간으로 이동하며, 그렇지 않은 경우에는 같은 위치에서 유지됩니다.
다음 예를 살펴보겠습니다.
시간 |
트랜잭션 1 |
트랜잭션 2 |
---|---|---|
1 |
트랜잭션을 시작합니다. |
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
트랜잭션을 커밋합니다. 트랜잭션의 DML 문에서 스트림이 사용된 경우 스트림 위치가 트랜잭션 시작 시간으로 이동합니다. |
|
6 |
트랜잭션을 시작합니다. |
|
7 |
|
트랜잭션 1에서 s1
스트림에 대한 모든 쿼리는 동일한 레코드 세트를 참조합니다. 트랜잭션이 커밋되는 경우에만 t1
테이블에 대한 DML 변경 사항이 스트림에 기록됩니다.
트랜잭션 2에서 스트림에 대한 쿼리는 트랜잭션 1의 테이블에 기록된 변경 사항을 참조합니다. 트랜잭션 1이 커밋되기 전 트랜잭션 2가 시작되면, 스트림에 대한 쿼리는 스트림의 위치에서 트랜잭션 2의 시작 시간까지 스트림의 스냅샷을 반환하며 트랜잭션 1에 의해 커밋된 변경 사항을 참조하지 않는다는 점에 유의하십시오.
스트림 열¶
스트림은 실제 테이블 열이나 데이터가 아닌 원본 오브젝트에 대한 오프셋을 저장합니다. 쿼리가 수행되면, 스트림은 원본 오브젝트와 모양이 동일한(즉, 열 이름 및 순서가 동일) 과거 데이터에 액세스하고 다음 추가 열과 함께 과거 데이터를 반환합니다.
- METADATA$ACTION:
기록된 DML 작업(INSERT, DELETE)을 나타냅니다.
- METADATA$ISUPDATE:
작업이 UPDATE 문의 일부인지 여부를 나타냅니다. 원본 오브젝트에서 행에 대한 업데이트는 스트림에서 DELETE 및 INSERT 레코드의 페어로 표시되며 메타데이터 열 METADATA$ISUPDATE 값은 TRUE로 설정됩니다.
스트림은 두 오프셋 사이의 차이를 기록한다는 점에 유의하십시오. 행이 추가된 후 현재 오프셋에서 업데이트되면 델타 변경 사항이 새 행이 됩니다. METADATA$ISUPDATE 행은 FALSE 값으로 기록됩니다.
- METADATA$ROW_ID:
행의 고유하고 변경이 불가능한 ID를 지정하며, 시간 경과에 따른 특정 행의 변경 사항을 추적하기 위해 사용할 수 있습니다.
Snowflake는 METADATA$ROW_ID에 대해 다음과 같은 보증을 제공합니다.
METADATA$ROW_ID는 스트림의 원본 오브젝트에 따라 달라집니다.
예를 들어 테이블
table1
의 스트림stream1
과 테이블table1
의 스트림stream2
는 동일한 행에 대해 동일한 METADATA$ROW_ID를 생성하지만, 뷰view1
의 스트림stream_view
는view
가CREATE VIEW view AS SELECT * FROM table1
문을 사용하여 정의된 경우에도stream1
과 동일한 METADATA$ROW_ID를 생성할 것으로 보장되지 않습니다.원본 오브젝트의 스트림과 원본 오브젝트 복제본의 스트림은 복제 시 존재하는 행에 대해 동일한 METADATA$ROW_ID를 생성합니다.
원본 오브젝트의 스트림과 원본 오브젝트 복제본의 스트림은 복제된 행에 대해 동일한 METADATA$ROW_ID를 생성합니다.
스트림의 유형¶
각각에 의해 기록된 메타데이터를 기준으로 사용할 수 있는 스트림의 유형은 다음과 같습니다.
- 표준:
테이블, 디렉터리 테이블 또는 뷰의 스트림에 지원됩니다. 표준(즉, 델타) 스트림은 삽입, 업데이트 및 삭제(테이블 자르기 포함) 등 원본 오브젝트에 대한 모든 DML 변경 사항을 추적합니다. 이 스트림 유형은 변경 집합의 삽입 및 삭제된 행에서 조인을 수행하여 행 수준 델타를 제공합니다. 예를 들어, 테이블의 두 트랜잭션 시점 사이에서 삽입된 후 삭제된 행은 결과적으로 델타에서 제거됩니다(즉, 스트림 쿼리 시 반환되지 않음).
참고
표준 스트림은 지리 공간 데이터에 대한 변경 데이터를 검색할 수 없습니다. 지리 공간 데이터가 포함된 오브젝트에 추가 전용 스트림을 생성하는 것이 좋습니다.
- Append-only:
표준 테이블, 디렉터리 테이블 또는 뷰의 스트림에 지원됩니다. Append-only 스트림은 행 삽입을 배타적으로 추적합니다. 업데이트, 삭제 및 자르기 작업은 Append-only 스트림으로 캡처되지 않습니다. 예를 들어, 처음에 행 10개를 테이블에 삽입한 다음 이들 행 중 5개를 삭제한 후 Append-only 스트림에 대한 오프셋을 진행하면 스트림은 삽입된 10개 행만 기록합니다.
Append-only 스트림은 추가된 행을 특정하여 반환하므로 추출, 로드, 변환(ELT)을 위한 표준 스트림과 행 삽입에만 의존하는 유사한 시나리오보다 성능이 훨씬 더 뛰어납니다. 예를 들어, Append-only 스트림에서 행을 사용한 직후 원본 테이블을 자를 수 있으며, 이러한 레코드 삭제는 다음 번 스트림 쿼리 또는 사용 시의 오버헤드에 영향을 주지 않습니다.
보조 오브젝트를 원본으로 사용하여 대상 계정에서 Append-only 스트림을 생성할 수는 없습니다.
- Insert-only:
외부 테이블의 스트림에만 지원됩니다. Insert-only 스트림은 행의 삽입만 추적하며, 삽입된 세트에서 행을 제거하는 삭제 작업을 기록하지 않습니다(즉, no-op). 예를 들어, 두 오프셋 사이에서, 외부 테이블이 참조하는 클라우드 저장소 위치에서 File1이 제거되고 File2가 추가된 경우 스트림은 File2의 행에 대한 레코드만 반환합니다. 표준 테이블에 대한 CDC 데이터를 추적할 때와는 달리, Snowflake는 클라우드 저장소의 파일에 대한 과거 레코드에 액세스할 수 없습니다.
덮어쓰거나 추가한 파일은 기본적으로 새 파일로 취급되며, 파일의 기존 버전은 클라우드 저장소에서 제거되지만 삽입 전용 스트림은 삭제 작업을 기록하지 않습니다. 파일의 새 버전은 클라우드 저장소에 추가되고 삽입 전용 스트림은 행을 삽입으로 기록합니다. 스트림은 기존 파일 버전과 새 파일 버전의 차이를 기록하지 않습니다. Azure AppendBlobs 를 사용할 때와 같이 외부 테이블 메타데이터를 자동으로 새로 고칠 때 추가가 트리거되지 않음에 유의해야 합니다.
데이터 흐름¶
다음 다이어그램은 원본의 행이 업데이트될 때 표준 스트림의 내용이 변경되는 방법을 보여줍니다. DML 문에서 스트림 내용을 사용할 때마다 스트림 위치가 이동하여 테이블에 대한 다음 DML 변경 사항 세트(즉, 테이블 버전 의 변경 사항)을 추적합니다.
데이터 보존 기간 및 부실¶
오프셋이 원본 테이블(또는 원본 뷰의 기본 테이블)에 대한 데이터 보존 기간을 벗어나면 스트림이 부실해집니다. 스트림이 부실해지면, 사용되지 않은 변경 레코드 등 원본 테이블의 과거 데이터에 더 이상 액세스할 수 없습니다. 테이블에 대한 새로운 변경 레코드를 추적하려면, 스트림을 다시 생성(CREATE STREAM 사용)합니다. 스트림이 부실해지는 것을 방지하려면 테이블의 보존 기간 중에 트랜잭션 내에서 스트림 레코드를 사용하십시오. 데이터 보존 기간에 대한 자세한 내용은 Time Travel 이해 및 사용하기 을 참조하십시오.
참고
이 제한은 데이터 보존 기간이 없는 디렉터리 테이블 또는 외부 테이블의 스트림에는 적용되지 않습니다.
또한, 공유 테이블 또는 뷰의 스트림은 각각 테이블 또는 기본 테이블에 대한 데이터 보존 기간을 연장하지 않습니다. 자세한 내용은 공유 오브젝트의 스트림 섹션을 참조하십시오.
테이블의 데이터 보존 기간이 14일 미만 이고 스트림을 사용한 적 없다면 Snowflake는 이 기간을 일시적으로 늘려 스트림이 부실해지는 것을 방지합니다. 보존 기간은 계정의 Snowflake 에디션 과 관계없이 최대 14일까지 스트림 오프셋이 연장됩니다. Snowflake가 데이터 보존 기간을 연장할 수 있는 최대 일수는 MAX_DATA_EXTENSION_TIME_IN_DAYS 매개 변수 값에 의해 결정됩니다. 스트림이 사용되면 연장된 데이터 보존 기간이 테이블의 기본 보존 기간으로 감소합니다.
다음 테이블은 DATA_RETENTION_TIME_IN_DAYS 및 MAX_DATA_EXTENSION_TIME_IN_DAYS 값의 예를 보여주며 부실해지는 것을 방지하기 위해 스트림 내용을 사용해야 하는 빈도를 나타냅니다.
DATA_RETENTION_TIME_IN_DAYS |
MAX_DATA_EXTENSION_TIME_IN_DAYS |
X일 내에 스트림 사용 |
---|---|---|
14 |
0 |
14 |
1 |
14 |
14 |
0 |
90 |
90 |
스트림의 현재 부실 상태를 보려면 DESCRIBE STREAM 또는 SHOW STREAMS 명령을 실행하십시오. STALE_AFTER 열 타임스탬프는 스트림이 현재 부실 상태가 될 것으로 예측되는 때(또는 과거 시점의 타임스탬프인 경우에는 부실 상태가 된 때)를 나타냅니다. 이는 원본 오브젝트에 대해 연장된 데이터 보존 기간입니다. 이 타임스탬프는 원본 오브젝트에 대한 DATA_RETENTION_TIME_IN_DAYS 또는 MAX_DATA_EXTENSION_TIME_IN_DAYS 매개 변수 설정 중 더 큰 값을 현재 타임스탬프에 더해 계산됩니다.
참고
원본 테이블의 데이터 보존 기간이 스키마 또는 데이터베이스 수준에서 설정된 경우 현재 역할은 STALE_AFTER 값을 계산하기 위해 스키마 또는 데이터베이스에 대한 액세스 권한이 있어야 합니다.
스트림의 변경 데이터를 사용하면 STALE_AFTER 타임스탬프가 앞으로 이동합니다. STALE_AFTER 타임스탬프 이후의 일정 시간 동안에도 스트림을 읽을 수 있습니다. 그러나 이 시간 동안에는 언제라도 스트림이 부실해질 수 있습니다. STALE 열은 실제로는 스트림이 아직 부실 상태가 아닐 수도 있지만 스트림이 현재 부실해질 것으로 예상되는지 여부를 나타냅니다.
스트림이 부실해지지 않도록 하려면 반드시 STALE_AFTER 타임스탬프 이전(즉, 원본 오브젝트의 연장된 데이터 보존 기간 내)에 변경 데이터를 정기적으로 사용하는 것이 좋습니다.
STALE_AFTER 타임스탬프가 지난 후에는 스트림에 대해 사용되지 않은 레코드가 없더라도 스트림이 언제든지 부실해질 수 있습니다. 원본 오브젝트에 대한 변경 데이터가 있더라도 스트림을 쿼리할 때 반환되는 레코드 수가 0개일 수 있습니다. 예를 들어 Append-only 스트림은 행 삽입만 추적하지만, 업데이트 및 삭제 활동은 변경 레코드를 원본 오브젝트에 쓰기도 합니다. 덜 명확하긴 하지만, 변경 데이터를 생성하지 않는 테이블 쓰기의 예로 재클러스터링이 있습니다.
스트림의 변경 데이터를 사용하면 그 사이의 버전에 변경 데이터가 포함되는지 여부에 관계없이 오프셋이 현재 시점으로 진행됩니다.
중요
오브젝트를 다시 생성(CREATE OR REPLACE TABLE 구문 사용)하면 내역이 삭제되고, 이로 인해 테이블이나 뷰의 스트림이 부실해질 수도 있습니다. 또한 뷰의 기본 테이블을 다시 만들거나 삭제하면 뷰의 모든 스트림이 부실해집니다.
현재는 스트림과 그 원본 테이블(또는 원본 뷰의 기본 테이블)이 포함된 데이터베이스 또는 스키마가 복제되면 스트림 복제본에서 사용되지 않은 모든 레코드에 액세스할 수 없습니다. 이 동작은 테이블에 대한 Time Travel 과 일치합니다. 테이블이 복제된 경우, 테이블 복제본에 대한 과거 데이터는 복제본이 생성된 시간/지점에서 시작됩니다.
원본 오브젝트의 이름을 바꾸어도 스트림이 손상되거나 부실해지지 않습니다. 또한, 원본 오브젝트를 삭제하고 이름이 같은 새 오브젝트를 생성하면 원래 오브젝트에 연결된 모든 스트림은 새 오브젝트에 연결되지 않습니다.
여러 스트림 컨슈머¶
사용자는 오브젝트에 대한 변경 사항 레코드의 각 컨슈머에 대해 별도의 스트림을 생성하는 것이 좋습니다. “컨슈머”란 DML 트랜잭션을 사용하여 오브젝트의 변경 사항 레코드를 사용하는 작업, 스크립트 또는 다른 메커니즘을 나타냅니다. 이 항목의 앞에서 설명한 바와 같이, 스트림은 DML 트랜잭션에서 사용될 때 오프셋을 앞으로 이동시킵니다. Time Travel을 사용하는 경우를 제외하고, 단일 스트림에서 변경 데이터의 다양한 컨슈머가 다양한 델타를 검색합니다. DML 트랜잭션을 사용하여 스트림의 최신 오프셋에서 캡처된 변경 데이터를 사용하는 경우 스트림은 오프셋을 앞으로 이동시킵니다. 다음 컨슈머의 경우 더 이상 변경 데이터를 사용할 수 없습니다. 오브젝트에 대해 똑같은 변경 데이터를 사용하려면 해당 오브젝트의 여러 스트림을 생성하십시오. 스트림은 실제 테이블 열 데이터가 아닌 원본 오브젝트에 대한 오프셋만 저장하므로, 커다란 비용이 발생하지 않고 오브젝트에 대한 스트림을 원하는 수만큼 생성할 수 있습니다.
Streams on Views¶
Streams on Views는 보안 뷰를 포함하여 Snowflake Secure Data Sharing을 사용하여 공유되는 뷰와 로컬 뷰를 모두 지원합니다. 현재, 스트림은 구체화된 뷰의 변경 사항을 추적할 수 없습니다.
스트림은 다음과 같은 요구 사항을 충족하는 뷰로 제한됩니다.
- 기본 테이블:
모든 기본 테이블은 네이티브 테이블이어야 합니다.
뷰는 다음 작업만 적용할 수 있습니다.
Projections
필터
내부 또는 크로스 조인
UNION ALL
완전히 확장된 쿼리가 이 요구 사항 테이블의 다른 요구 사항을 충족하는 한, FROM 절의 중첩 뷰와 하위 쿼리가 지원됩니다.
- 뷰 쿼리:
일반적인 요구 사항:
쿼리는 임의 개수의 열을 선택할 수 있습니다.
쿼리는 임의 개수의 WHERE 조건자를 포함할 수 있습니다.
다음 작업이 포함된 뷰는 아직 지원되지 않습니다.
GROUP BY 절
QUALIFY 절
FROM 절에 없는 하위 쿼리
상관 관계가 있는 하위 쿼리
LIMIT 절
함수:
선택 목록의 함수는 시스템에서 정의된 스칼라 함수여야 합니다.
- 변경 내용 추적:
기본 테이블에서 변경 내용 추적을 활성화해야 합니다.
뷰에서 스트림을 만들기 전에 뷰의 기본 테이블에서 변경 내용 추적을 활성화해야 합니다. 자세한 지침은 뷰와 기본 테이블에서 변경 내용 추적 활성화하기 섹션을 참조하십시오.
조인 결과 동작¶
조인을 포함한 뷰의 변경 사항을 추적하는 스트림의 결과를 검사할 때 어떤 데이터가 조인되는지 이해하는 것이 중요합니다. 스트림 오프셋이 오른쪽 테이블과 조인된 이후로 왼쪽 테이블에서 발생한 변경 사항, 스트림 오프셋이 왼쪽 테이블과 조인된 이후로 오른쪽 테이블에서 발생한 변경 사항, 스트림 오프셋이 서로 조인된 이후로 두 테이블에서 모두 발생한 변경 사항.
다음 예를 살펴보겠습니다.
다음 두 테이블이 생성됩니다.
create or replace table orders (id int, order_name varchar);
create or replace table customers (id int, customer_name varchar);
id
에서 두 테이블을 조인하기 위해 뷰가 생성됩니다. 각 테이블에는 다른 테이블과 조인하는 단일 행이 있습니다.
create or replace view ordersByCustomer as select * from orders natural join customers;
insert into orders values (1, 'order1');
insert into customers values (1, 'customer1');
뷰에 대한 변경 사항을 추적하는 스트림이 생성됩니다.
create or replace stream ordersByCustomerStream on view ordersBycustomer;
스트림의 현재 오프셋 이후로 테이블에 대한 변경 사항이 없었으므로 뷰에는 항목이 한 개 있고 스트림에는 항목이 없습니다.
select * from ordersByCustomer;
+----+------------+---------------+
| ID | ORDER_NAME | CUSTOMER_NAME |
|----+------------+---------------|
| 1 | order1 | customer1 |
+----+------------+---------------+
select * exclude metadata$row_id from ordersByCustomerStream;
+----+------------+---------------+-----------------+-------------------+
| ID | ORDER_NAME | CUSTOMER_NAME | METADATA$ACTION | METADATA$ISUPDATE |
|----+------------+---------------+-----------------+-------------------|
+----+------------+---------------+-----------------+-------------------+
기본 테이블이 업데이트되면 ordersByCustomerStream
을 선택하면 orders
x Δ customers
+ Δ orders
x customers
+ Δ orders
x Δ customers
의 레코드가 생성됩니다. 여기서
Δ
orders
및 Δcustomers
는 스트림 오프셋 이후 각 테이블에 발생한 변경 사항입니다.주문 및 고객은 현재 스트림 오프셋에서 테이블의 전체 내용입니다.
Snowflake에서 최적화로 인해 이 식을 계산하는 비용이 항상 입력 크기에 선형적으로 비례하는 것은 아닙니다.
조인하는 다른 행이 orders
에 삽입된 경우에는 ordersByCustomer
에 새 행이 생깁니다.
insert into orders values (1, 'order2');
select * from ordersByCustomer;
+----+------------+---------------+
| ID | ORDER_NAME | CUSTOMER_NAME |
|----+------------+---------------|
| 1 | order1 | customer1 |
| 1 | order2 | customer1 |
+----+------------+---------------+
Δ orders
x customers
에 새로운 삽입이 포함되고 orders
x Δ customers
+ Δ orders
x Δ customers
가 비어 있으므로 ordersByCustomersStream
에서 선택하면 한 개의 행이 생성됩니다.
select * exclude metadata$row_id from ordersByCustomerStream;
+----+------------+---------------+-----------------+-------------------+
| ID | ORDER_NAME | CUSTOMER_NAME | METADATA$ACTION | METADATA$ISUPDATE |
|----+------------+---------------+-----------------+-------------------|
| 1 | order2 | customer1 | INSERT | False |
+----+------------+---------------+-----------------+-------------------+
조인하는 다른 행이 customers
에 삽입되면 ordersByCustomer
에 총 세 개의 새 행이 생깁니다.
insert into customers values (1, 'customer2');
select * from ordersByCustomer;
+----+------------+---------------+
| ID | ORDER_NAME | CUSTOMER_NAME |
|----+------------+---------------|
| 1 | order1 | customer1 |
| 1 | order2 | customer1 |
| 1 | order1 | customer2 |
| 1 | order2 | customer2 |
+----+------------+---------------+
Δ orders
x customers
, orders
x Δ customers
, Δ orders
x Δ customers
가 각각 하나씩 행을 생성하므로 ordersByCustomersStream
에서 선택하면 세 개의 행이 생성됩니다.
select * exclude metadata$row_id from ordersByCustomerStream;
+----+------------+---------------+-----------------+-------------------+
| ID | ORDER_NAME | CUSTOMER_NAME | METADATA$ACTION | METADATA$ISUPDATE |
|----+------------+---------------+-----------------+-------------------|
| 1 | order1 | customer2 | INSERT | False |
| 1 | order2 | customer1 | INSERT | False |
| 1 | order2 | customer2 | INSERT | False |
+----+------------+---------------+-----------------+-------------------+
Append-only 스트림의 경우 Δ orders
와 Δ customers
에는 행 삽입만 포함되는 반면, orders
와 customers
에는 스트림 오프셋 이전에 발생한 모든 업데이트를 포함하여 테이블의 전체 내용이 포함됩니다.
CHANGES 절: 스트림에 대한 읽기 전용의 대안¶
스트림에 대한 대안으로, Snowflake는 SELECT 문에 대해 CHANGES 절을 사용하여 테이블 또는 뷰에 대한 변경 내용 추적 메타데이터 쿼리를 지원합니다. CHANGES 절을 사용하면 명시적인 트랜잭션 오프셋이 포함된 스트림을 생성할 필요 없이 두 시점 사이의 변경 내용 추적 메타데이터를 쿼리할 수 있습니다. CHANGES 절을 사용하면 오프셋이 이동하지 않습니다 (즉, 레코드 사용). 다중 쿼리는 서로 다른 트랜잭션 시작과 엔드포인트 사이에서 변경 내용 추적 메타데이터를 검색할 수 있습니다. 이 옵션을 사용하려면 AT | BEFORE 절을 사용하여 메타데이터의 트랜잭션 시작점을 지정해야 하며, 변경 내용 추적 간격에 대한 끝점은 선택적 END 절을 사용하여 설정할 수 있습니다.
스트림은 현재 트랜잭션 테이블 버전 을 저장하며 대부분의 경우 CDC 레코드의 적절한 원본입니다. 드물지만 임의 기간을 위한 오프셋을 관리해야 하는 경우에는 CHANGES 절을 사용할 수 있습니다.
현재는 다음을 true로 설정해야 변경 내용 추적 메타데이터를 기록할 수 있습니다.
- 테이블:
테이블에서 변경 내용 추적을 활성화하거나(ALTER TABLE … CHANGE_TRACKING = TRUE 사용) 테이블에 스트림을 생성합니다(CREATE STREAM 사용).
- 뷰:
뷰와 뷰의 기본 테이블에서 변경 내용 추적을 활성화합니다. 자세한 지침은 뷰와 기본 테이블에서 변경 내용 추적 활성화하기 섹션을 참조하십시오.
변경 내용 추적을 사용하면 숨겨진 열이 여러 개 테이블에 추가되며 변경 내용 추적 메타데이터가 저장되기 시작합니다. 이러한 숨겨진 CDC 데이터 열의 값은 스트림 메타데이터 열 에 대한 입력을 제공합니다. 열은 소량의 저장소를 사용합니다.
이러한 조건 중 하나가 충족되기 전의 기간 동안에는 오브젝트에 대한 변경 내용 추적 메타데이터를 사용할 수 없습니다.
필수 액세스 권한¶
스트림을 쿼리하려면 최소한으로 다음의 역할 권한이 있는 역할이 필요합니다.
오브젝트 |
권한 |
참고 |
---|---|---|
데이터베이스 |
USAGE |
|
스키마 |
USAGE |
|
스트림 |
SELECT |
|
테이블 |
SELECT |
테이블의 스트림만 해당. |
뷰 |
SELECT |
Streams on Views만 해당. |
외부 스테이지 |
USAGE |
(외부 스테이지에서) 디렉터리 테이블의 스트림만 해당 |
내부 스테이지 |
READ |
(내부 스테이지에서) 디렉터리 테이블의 스트림만 해당 |
스트림 요금¶
이 항목의 데이터 보존 기간 및 부실 섹션에서 설명한 바와 같이, 스트림이 정기적으로 사용되지 않으면 Snowflake는 원본 뷰에서 원본 테이블 또는 기본 테이블의 데이터 보존 기간을 일시적으로 연장합니다. 테이블의 데이터 보존 기간이 14일 미만이면 계정의 Snowflake 에디션 과 관계없이 스트림 트랜잭션 오프셋 또는 14일(테이블의 데이터 보존 기간이 14일 미만인 경우) 중 짧은 기간 으로 연장됩니다.
데이터 보존 기간을 연장하려면 추가 저장소가 필요하며, 이와 관련한 월간 저장소 요금이 부과된다는 점에 유의하십시오.
스트림과 관련된 기본 비용은 스트림을 쿼리하기 위해 가상 웨어하우스에서 사용하는 처리 시간입니다. 이러한 요금은 청구서에 익숙한 Snowflake 크레딧으로 표시됩니다.