Перейти к основному содержанию
Перейти к основному содержанию

Движок таблиц Memory

Примечание

При использовании движка таблиц Memory в ClickHouse Cloud данные по проекту не реплицируются на все узлы (так задумано). Чтобы гарантировать, что все запросы направляются на один и тот же узел и движок Memory работает предсказуемо, вы можете:

  • Выполнять все операции в одном и том же сеансе
  • Использовать клиент, работающий по TCP или через нативный интерфейс (что позволяет использовать «липкие» соединения), например clickhouse-client

Движок Memory хранит данные в оперативной памяти (RAM) в несжатом виде. Данные хранятся в точности в том виде, в котором они были получены при чтении. Другими словами, чтение из этой таблицы полностью бесплатно с точки зрения затрат на обработку. Одновременный доступ к данным синхронизирован. Блокировки кратковременные: операции чтения и записи не блокируют друг друга. Индексы не поддерживаются. Чтение выполняется параллельно.

Максимальная производительность (более 10 ГБ/сек) достигается на простых запросах, поскольку отсутствуют чтение с диска, декомпрессия и десериализация данных. (Следует отметить, что во многих случаях производительность движка MergeTree почти столь же высока.) При перезапуске сервера данные из таблицы исчезают, и таблица становится пустой. Как правило, использование этого движка таблиц не оправдано. Однако его можно применять для тестов и для задач, где требуется максимальная скорость на относительно небольшом количестве строк (до примерно 100 000 000).

Движок Memory используется системой для временных таблиц с внешними данными запроса (см. раздел «Внешние данные для обработки запроса»), а также для реализации GLOBAL IN (см. раздел «Операторы IN»).

Для ограничения размера таблицы с движком Memory можно задать верхнюю и нижнюю границы, фактически позволяя использовать её как кольцевой буфер (см. Параметры движка).

Параметры движка

  • 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

Использование

Инициализация настроек

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;

Примечание: Параметры ограничения bytes и rows могут быть заданы одновременно, однако будет использоваться меньшее из значений max и min.

Примеры

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

/* 1. проверка, что самый старый блок не удаляется из-за минимального порога — 3000 строк */
INSERT INTO memory SELECT * FROM numbers(0, 1600); -- 8'192 bytes

/* 2. добавление блока, который не удаляется */
INSERT INTO memory SELECT * FROM numbers(1000, 100); -- 1'024 bytes

/* 3. проверка, что самый старый блок удаляется — 9216 байт — 1100 строк */
INSERT INTO memory SELECT * FROM numbers(9000, 1000); -- 8'192 bytes

/* 4. проверка, что очень большой блок вытесняет все остальные */
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 │
└─────────────┴────────────┘

а также для строк:

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

/* 1. проверяем, что самый старый блок не удаляется из‑за минимального порога — 3000 строк */
INSERT INTO memory SELECT * FROM numbers(0, 1600); -- 1'600 строк

/* 2. добавляем блок, который не удаляется */
INSERT INTO memory SELECT * FROM numbers(1000, 100); -- 100 строк

/* 3. проверяем, что самый старый блок удаляется — 9216 байт — 1100 строк */
INSERT INTO memory SELECT * FROM numbers(9000, 1000); -- 1'000 строк

/* 4. проверяем, что очень большой блок вытесняет все остальные */
INSERT INTO memory SELECT * FROM numbers(9000, 10000); -- 10'000 строк

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