Buffer 테이블 엔진

Buffer 테이블 엔진

Buffer 엔진은 쓸 데이터를 RAM에 버퍼링했다가 주기적으로 다른 테이블로 플러시해요. 읽기 연산 중에는 버퍼와 다른 테이블에서 데이터를 동시에 읽습니다. Buffer 테이블 엔진의 권장 대안은 비동기 삽입(asynchronous inserts)을 활성화하는 것이에요.

출처: 문서

본문

쓸 데이터를 RAM에 버퍼링했다가 주기적으로 다른 테이블로 플러시합니다. 읽기 연산 중에는 버퍼와 다른 테이블에서 데이터를 동시에 읽어요.

Buffer 테이블 엔진의 권장 대안은 비동기 삽입(asynchronous inserts)을 활성화하는 것입니다.

Buffer(database, table, num_layers, min_time, max_time, min_rows, max_rows, min_bytes, max_bytes [,flush_time [,flush_rows [,flush_bytes]]])

엔진 매개변수 (Engine parameters)

database

database — 데이터베이스 이름. currentDatabase() 또는 문자열을 반환하는 다른 상수 표현식을 사용할 수 있어요.

table

table — 데이터를 플러시할 테이블.

num_layers

num_layers — 병렬 처리 레이어. 물리적으로 테이블은 num_layers개의 독립적인 버퍼로 표현됩니다.

min_time, max_time, min_rows, max_rows, min_bytes, max_bytes

버퍼에서 데이터를 플러시하기 위한 조건입니다.

선택적 엔진 매개변수 (Optional engine parameters)

flush_time, flush_rows, flush_bytes

배경에서 버퍼의 데이터를 플러시하기 위한 조건입니다(생략하거나 0이면 flush* 매개변수가 없는 것을 의미해요).

모든 min* 조건 또는 최소한 하나의 max* 조건이 충족되면 데이터가 버퍼에서 플러시되고 대상 테이블에 기록됩니다. 또한 min* 조건 중 하나라도 충족되면 배경에서 플러시가 시작됩니다. 이것은 max와 다릅니다. flush를 사용하면 배경 플러시를 별도로 구성하여 Buffer 테이블에 대한 INSERT 쿼리에 지연이 추가되는 것을 피할 수 있어요.

min_time, max_time, flush_time

버퍼에 첫 기록이 있던 시점부터 경과한 시간(초)에 대한 조건입니다.

min_rows, max_rows, flush_rows

버퍼의 행 수에 대한 조건입니다.

min_bytes, max_bytes, flush_bytes

버퍼의 바이트 수에 대한 조건입니다.

쓰기 연산 중에는 데이터가 하나 이상의 무작위 버퍼(num_layers로 구성)에 삽입됩니다. 또는 삽입할 데이터 part가 충분히 크면(max_rows 또는 max_bytes보다 큰 경우) 버퍼를 건너뛰고 대상 테이블에 직접 기록됩니다.

데이터를 플러시하기 위한 조건은 num_layers 버퍼 각각에 대해 별도로 계산됩니다. 예를 들어 num_layers = 16이고 max_bytes = 100000000이면 최대 RAM 소비는 1.6 GB입니다.

예시:

CREATE TABLE merge.hits_buffer AS merge.hits ENGINE = Buffer(merge, hits, 1, 10, 100, 10000, 1000000, 10000000, 100000000)

merge.hits와 동일한 구조를 가진 merge.hits_buffer 테이블을 만들고 Buffer 엔진을 사용합니다. 이 테이블에 쓰면 데이터가 RAM에 버퍼링된 후 'merge.hits' 테이블에 기록됩니다. 단일 버퍼가 생성되고 다음 중 하나에 해당하면 데이터가 플러시됩니다:

  • 마지막 플러시 이후 100초가 경과했거나(max_time)
  • 1백만 행이 기록되었거나(max_rows)
  • 100 MB의 데이터가 기록되었거나(max_bytes)
  • 10초가 경과했고(min_time) 10,000행(min_rows)과 10 MB(min_bytes)의 데이터가 기록되었거나

예를 들어 행 하나만 기록된 경우에도 100초 후에는 무조건 플러시됩니다. 하지만 많은 행이 기록된 경우에는 더 일찍 플러시됩니다.

서버를 중지할 때, DROP TABLE 또는 DETACH TABLE 시에도 버퍼링된 데이터는 대상 테이블로 플러시됩니다.

데이터베이스와 테이블 이름에 작은따옴표 안의 빈 문자열을 설정할 수 있어요. 이것은 대상 테이블이 없음을 나타냅니다. 이 경우 데이터 플러시 조건에 도달하면 버퍼가 단순히 비워집니다. 이는 메모리에 데이터 창(window)을 유지하는 데 유용할 수 있습니다.

Buffer 테이블에서 읽을 때는 버퍼와 대상 테이블(있는 경우) 양쪽에서 데이터가 처리됩니다.

Buffer 테이블은 인덱스를 지원하지 않는다는 점에 유의하세요. 즉 버퍼 안의 데이터는 전체 스캔되는데, 큰 버퍼에서는 느릴 수 있습니다. (하위 테이블의 데이터에는 해당 테이블이 지원하는 인덱스가 사용됩니다.)

Buffer 테이블의 컬럼 집합이 하위 테이블의 컬럼 집합과 일치하지 않으면 두 테이블에 모두 존재하는 컬럼의 부분집합이 삽입됩니다.

Buffer 테이블의 컬럼 중 하나와 하위 테이블의 타입이 일치하지 않으면 오류 메시지가 서버 로그에 기록되고 버퍼가 비워집니다.

버퍼를 플러시할 때 하위 테이블이 존재하지 않는 경우에도 같은 일이 발생합니다.

2021년 10월 26일 이전 릴리스에서 Buffer 테이블에 ALTER를 실행하면 Block 구조 불일치 오류(Block structure mismatch error)가 발생합니다(#15117 및 #30565 참조). 따라서 Buffer 테이블을 삭제한 다음 다시 만드는 것만이 유일한 옵션이에요. Buffer 테이블에서 ALTER를 실행하기 전에 이 오류가 당신의 릴리스에서 수정되었는지 확인하세요.

서버가 비정상적으로 재시작되면 버퍼의 데이터가 손실됩니다.

FINAL과 SAMPLE은 Buffer 테이블에서 올바르게 작동하지 않아요. 이러한 조건은 대상 테이블로 전달되지만 버퍼의 데이터를 처리하는 데는 사용되지 않습니다. 이러한 기능이 필요하다면 캐시 테이블은 쓰기에만 사용하고 대상 테이블에서 읽기를 권장합니다.

Buffer 테이블에 데이터를 추가할 때 버퍼 중 하나가 잠깁니다. 이로 인해 테이블에서 읽기 연산이 동시에 수행되는 경우 지연이 발생합니다.

Buffer 테이블에 삽입된 데이터는 하위 테이블에서 다른 순서와 다른 블록으로 끝날 수 있습니다. 이 때문에 CollapsingMergeTree에 올바르게 쓰기 위해 Buffer 테이블을 사용하기는 어렵습니다. 문제를 피하려면 num_layers를 1로 설정할 수 있어요.

대상 테이블이 레플리케이션되면 Buffer 테이블에 쓸 때 레플리케이션된 테이블의 일부 예상 특성이 손실됩니다. 행 순서와 데이터 part 크기의 무작위 변경으로 데이터 중복 제거가 작동을 멈추며, 이는 레플리케이션된 테이블에 신뢰할 수 있는 '정확히 한 번' 쓰기가 불가능하다는 것을 의미합니다.

이러한 단점 때문에 Buffer 테이블은 드문 경우에만 사용하는 것을 권장합니다.

일정 시간 단위로 많은 서버에서 너무 많은 INSERT를 수신하고, 삽입 전에 데이터를 버퍼링할 수 없어서 INSERT가 충분히 빠르게 실행될 수 없을 때 Buffer 테이블이 사용됩니다.

Buffer 테이블에서도 행을 하나씩 삽입하는 것은 의미가 없다는 점에 유의하세요. 이 경우 초당 수천 행의 속도만 나오지만, 더 큰 블록의 데이터를 삽입하면 초당 백만 행 이상의 속도를 낼 수 있습니다.

더 알아보기 (Learn more)