Memory 테이블 엔진

Memory 테이블 엔진

Memory 엔진은 데이터를 압축되지 않은 형태로 RAM에 저장해요. 이 테이블에서 읽는 것은 완전히 공짜(비용이 들지 않는)이며, 데이터가 읽힐 때 받은 것과 정확히 같은 형태로 저장되기 때문에 읽기 성능이 매우 뛰어나답니다. 주로 테스트나 상대적으로 적은 행 수(약 100,000,000개까지)에서 최대 속도가 필요한 작업에 사용돼요.

출처: 문서

본문

ClickHouse Cloud에서 Memory 테이블 엔진을 사용하면 데이터가 모든 노드에 레플리케이션되지 않아요(설계상). 모든 쿼리가 같은 노드로 라우팅되고 Memory 테이블 엔진이 예상대로 작동하도록 보장하려면 다음 중 하나를 수행하면 됩니다:

  • 모든 연산을 같은 세션에서 실행
  • 스티키 연결(sticky connections)을 지원하는 TCP 또는 네이티브 인터페이스를 사용하는 클라이언트 사용. 예: clickhouse-client

Memory 엔진은 데이터를 압축되지 않은 형태로 RAM에 저장합니다. 데이터는 읽을 때 받은 것과 정확히 같은 형태로 저장됩니다. 즉 이 테이블에서 읽는 것은 완전히 공짜입니다.

동시 데이터 접근은 동기화됩니다. 잠금은 짧습니다. 읽기와 쓰기 연산은 서로를 차단하지 않아요.

인덱스는 지원되지 않습니다. 읽기는 병렬화됩니다.

단순한 쿼리에서 디스크 읽기, 압축 해제, 역직렬화가 없기 때문에 최대 생산성(10 GB/sec 이상)에 도달합니다. (많은 경우 MergeTree 엔진의 생산성도 거의 비슷하게 높다는 점을 기억하세요.)

서버를 재시작하면 테이블의 데이터가 사라지고 테이블은 비어 있게 됩니다.

일반적으로 이 테이블 엔진을 사용하는 것은 정당화되지 않습니다. 그러나 테스트와 상대적으로 적은 행 수(약 100,000,000개까지)에서 최대 속도가 필요한 작업에는 사용할 수 있어요.

Memory 엔진은 외부 쿼리 데이터가 있는 임시 테이블( "External data for processing a query" 섹션 참조)과 GLOBAL IN 구현("IN operators" 섹션 참조)을 위해 시스템에서 사용됩니다.

Memory 엔진 테이블 크기를 제한하기 위해 상한과 하한을 지정할 수 있으며, 사실상 순환 버퍼처럼 동작하게 할 수 있어요(Engine Parameters 참조).

엔진 매개변수 (Engine parameters)

  • min_bytes_to_keep — 메모리 테이블이 크기 제한이 있을 때 유지할 최소 바이트. - 기본값: 0 - max_bytes_to_keep 필요
  • max_bytes_to_keep — 메모리 테이블 내에서 유지할 최대 바이트. 각 삽입 시 가장 오래된 행이 삭제됩니다(즉 순환 버퍼). 큰 블록을 추가할 때 제거할 가장 오래된 행 배치가 min_bytes_to_keep 한도보다 작으면 최대 바이트가 명시된 한도를 초과할 수 있어요. - 기본값: 0
  • min_rows_to_keep — 메모리 테이블이 크기 제한이 있을 때 유지할 최소 행. - 기본값: 0 - max_rows_to_keep 필요
  • max_rows_to_keep — 메모리 테이블 내에서 유지할 최대 행. 각 삽입 시 가장 오래된 행이 삭제됩니다(즉 순환 버퍼). 큰 블록을 추가할 때 제거할 가장 오래된 행 배치가 min_rows_to_keep 한도보다 작으면 최대 행이 명시된 한도를 초과할 수 있어요. - 기본값: 0
  • compress - 메모리의 데이터를 압축할지 여부. - 기본값: false

사용 (Usage)

설정 초기화

CREATE TABLE memory (i UInt32) ENGINE = Memory SETTINGS min_rows_to_keep = 100, max_rows_to_keep = 1000;

설정 수정

ALTER TABLE memory MODIFY SETTING min_rows_to_keep = 100, max_rows_to_keep = 1000;

참고: 바이트와 행 제한 매개변수를 동시에 설정할 수 있지만, max와 min의 하한이 준수됩니다.

예시 (Examples)

CREATE TABLE memory (i UInt32) ENGINE = Memory SETTINGS min_bytes_to_keep = 4096, max_bytes_to_keep = 16384;

/* 1. testing oldest block doesn't get deleted due to min-threshold - 3000 rows */
INSERT INTO memory SELECT * FROM numbers(0, 1600); -- 8'192 bytes

/* 2. adding block that doesn't get deleted */
INSERT INTO memory SELECT * FROM numbers(1000, 100); -- 1'024 bytes

/* 3. testing oldest block gets deleted - 9216 bytes - 1100 */
INSERT INTO memory SELECT * FROM numbers(9000, 1000); -- 8'192 bytes

/* 4. checking a very large block overrides all */
INSERT INTO memory SELECT * FROM numbers(9000, 10000); -- 65'536 bytes

SELECT total_bytes, total_rows FROM system.tables WHERE name = 'memory' AND database = currentDatabase();
┌─total_bytes─┬─total_rows─┐
│       65536 │      10000 │
└─────────────┴────────────┘

또한, 행(row)의 경우:

CREATE TABLE memory (i UInt32) ENGINE = Memory SETTINGS min_rows_to_keep = 4000, max_rows_to_keep = 10000;

/* 1. testing oldest block doesn't get deleted due to min-threshold - 3000 rows */
INSERT INTO memory SELECT * FROM numbers(0, 1600); -- 1'600 rows

/* 2. adding block that doesn't get deleted */
INSERT INTO memory SELECT * FROM numbers(1000, 100); -- 100 rows

/* 3. testing oldest block gets deleted - 9216 bytes - 1100 */
INSERT INTO memory SELECT * FROM numbers(9000, 1000); -- 1'000 rows

/* 4. checking a very large block overrides all */
INSERT INTO memory SELECT * FROM numbers(9000, 10000); -- 10'000 rows

SELECT total_bytes, total_rows FROM system.tables WHERE name = 'memory' AND database = currentDatabase();
┌─total_bytes─┬─total_rows─┐
│       65536 │      10000 │
└─────────────┴────────────┘

더 알아보기 (Learn more)