Производительность и рекомендации

При выборе между CH и CHYT возникает вопрос — что быстрее и насколько?

Ответить на этот вопрос в общем случае невозможно, так как скорость выполнения запроса зависит от множества факторов, в том числе от самого запроса, количества ресурсов и схемы хранения данных.

Данные в YTsaurus изначально не предназначены для выполнения OLAP-запросов. Чтобы получить нормальную скорость, нужно их подготовить.
Добиться скорости CH, скорее всего, не получится, но можно приблизиться, правильно выбирая схему хранения данных и запросов к ним.
Зато неправильным хранением данных легко можно добиться скорости запросов в сотни раз ниже чем в CH.

На что уходит время

Ниже приведены этапы выполнения запроса, которые могут быть "узким местом".

  1. Чтение метаинформации таблиц и чанков, распределение запроса по инстансам.
  2. Чтение данных с диска.
  3. Передача данных по сети.
  4. Расжатие данных и декодирование.
  5. Merge версий (только для динамических таблиц).
  6. Конвертация данных из формата YTsaurus в формат CH.
  7. Обработка данных движком ClickHouse.
  8. Конвертирование данных из формата CH в формат YTsaurus (только для операций записи).
  9. Запись данных в YTsaurus (только для операций записи).

В зависимости от того, как данные хранятся и какими запросами обрабатываются, разные этапы могут быть узким местом.

Чтение данных

Далее описаны факторы, влияющие на скорость запросов чтения.

Размер обрабатываемых данных

В первую очередь CHYT заточен для быстрой обработки (порядка секунд) данных малого (порядка ГБ) и среднего (порядка десятков ГБ) размера. Эффективно использовать CHYT для обработки ТБ данных не получится. Уменьшить количество обрабатываемых данных можно с помощью правильной схемы хранения данных (используя поколоночность и сортированность).

Для построения дашбордов поверх большого объема данных рекомендуется делать отдельные таблицы с "выжимкой" нужных данных, а так же предагрегированными значениями. Например, если данные в миллисекундах, а аналитику нужно строить по дням, то нужно предагрегировать данные до дня.

Как уменьшить количество вычислений налету:

  • Например, дату можно считать по полю datetime, но фильтрация по этому полю будет медленнее.
  • Избегать выполнения неоправданно тяжелых запросов. Например, сортировка 100ГБ, SELECT DISTINCT или GROUP BY по колонке, которая имеет миллионы различных значений, или использование оператора JOIN для больших таблиц. Такие запросы всегда будут обрабатываться медленно.

Чтение больших таблиц может упереться в любой пункт исполнения запроса из списка выше.

Erasure кодирование

Erasure кодирование предназначено для "холодных" таблиц. Данные в erasure кодировании занимают меньше дискового пространства, но это негативно сказывается на скорости чтении таких данных:

  1. Каждый чанк разбит на 16 (или 9 в зависимости от алгоритма кодирования) частей, что увеличивает количество метаинформации (пункт 1).
  2. Данные хранятся в одной копии, поэтому чтение нельзя распараллелить (пункт 2).
  3. В случае, если диск на ноде загружен, не будет возможности переключиться на чтение данных с другой ноды. А так как чанк разбит на 16 частей, то вероятность что чтение хотя бы одного их них зависнет сильно увеличивается.
  4. Если данные недоступны из-за сбоя узла кластера, их необходимо восстанавливать. Это достаточно долгий и ресурсозатратный процесс. (пункт 2, 4?).

Как результат, чтение данных с erasure кодированием занимает в разы больше времени, а задержки при чтении становятся более вероятными и менее предсказуемыми. Строить дашборды или делать другие регулярные запросы поверх данных в erasure кодированием крайне не рекомендуется.

Формат хранения данных

Данные в YTsaurus таблицах могут храниться как в построчном (optimize_for=lookup), так и в поколоночном (optimize_for=scan) формате.

Внимание

ClickHouse — это колоночная СУБД, поэтому настоятельно рекомендуется использовать именно поколоночное хранение.

Поколоночное хранение данных имеет следующие преимущества:

  • Конвертация данных в формат CH из поколоночного формата YTsaurus в разы (если не в десятки раз) эффективнее, чем из построчного (пункт 6).
  • При поколоночном хранении данных во время запроса будут считаны только запрошенные колонки. (пункты 2, 3 и 4).
  • Данные, хранящиеся поколоночно, лучше сжимаются, поэтому занимают меньше места (пункты 2, 3).

Примечание

Обычная смена аттрибутов optimize_for/erasure_codec не перекладывает старые данные в новый формат. Чтобы изменение формата случилось, запустите операцию merge с опцией force_transform=%true.

Ключевые колонки

Для эффективного чтения в ClickHouse существуют индексы и ключи шардирования. В YTsaurus модель хранения данных немного иная, привычных индексов нет. Но есть сортированные таблицы. Запросы над сортированными таблицами используют ключ сортировки как первичный индекс (Primary key) и ключ шардирования (Sharding key).

Это позволяет:

  • эффективно фильтровать и не читать лишние данные с диска (пункт 2).
  • эффективнее делать запрос, в частности, Sorted Join.
  • лучше сжимать сортированные таблицы, в результате чего они занимают меньше места (пункт 2).

Выбирать ключ сортировки нужно в зависимости от запросов:

  • Например, если запросы выглядит как
    ... where date between '2021-01-01' and '2021-02-01'

Хорошим ключом будет date.

  • Для запросов вида
    ... where user_id = 1234
    Хорошим ключом будет user_id.

В некоторых случаях, если отсортировать таблицу, эффективной фильтрации не будет. Колонка строковая и конвертация DateTime <-> String не является монотонной и однозначной. Преобразование Int <-> DateTime монотонное, но со строковым представлением применять такую оптимизацию в общем случае нельзя. Например, 2020-01-01 00:00:00 и 2020-01-01T00:00:00 — корректное представление одного и того же момента времени в ClickHouse, но при сортировке со строковым представлением между ними может появиться значение 2020-01-01 00:00:01, поэтому преобразование String -> DateTime не является монотонным и использовать эту оптимизацию нельзя.

Количество чанков

Количество чанков влияет на несколько этапов выполнения запроса.

Чем больше количество чанков у таблицы, тем больше необходимо считать метаинформации на шаге 1. Если у таблицы тысячи чанков — считывание метаинформации может затянуться на несколько секунд. Если чанков много у очень маленькой таблицы, то чтение каждого чанка превращается в random read и может работать медленно (шаг 2).
С другой стороны, если чанков слишком мало (например, 1 чанк на 10 GB), то все данных хранятся на одних и тех же дисках, что ограничит параллельность чтения на шаге 2.

Для укрупнения чанков используйте операцию Merge.

Количество входных таблиц

Аналогично количеству чанков, но метаинформация для таблицы в разы тяжелее чем метаинформация для чанка. Кроме того, для каждой таблицы нужно отдельно проверить права доступа. Рекомендуем делать не более сотен таблиц. Желательно объединять много таблиц в одну большую.

Количество колонок

Количество колонок в таблице тоже влияет на скорость работы с данными, даже если данные хранятся в поколоночном формате. Размер блока подбирается так, что бы ридер мог считать по блоку для каждой колонки и выдать результат. Что бы при таком чтении данные влезали в память, при увеличении числа колонок размер блоков уменьшается. При совсем маленьких блоках чтение превращается в random read (шаг 2). Рекомендуем иметь десятки, максимум 100 колонок. Тысячи колонок гарантированно будут работать плохо.
Кроме того, большое количество колонок увеличивает количество метаинформации на шаге 1.

Динамические vs Статические таблицы

Данные в динамических таблицах хранятся по-другому и не предназначены для full-scan-чтения. Это накладывает дополнительные расходы на их чтение:

  1. Во-первых, нужно читать для каждого значения его версию.
  2. Во-вторых, для каждой строчки необходимо прочитать все ключевые колонки, даже если они не используются в запросе.
  3. Далее, необходимо сделать объединение всех строчек с одинаковым ключом, оставив только 1 самую свежую версию. Это очень тяжелый процесс с большим количеством сравнений. Кроме того, процесс сугубо построчный, поэтому даже если данные хранятся поколоночно, их придется переложить построчно.
  4. После этого необходимо переложить данные обратно в поколоночный формат.

Merge может добавлять x10 к времени чтения данных.

Строить дашборды или делать другие регулярные запросы поверх динамических таблиц большого размера крайне не рекомендуется ввиду неэффективности чтения.

SSD vs HDD

SSD диски обладают очевидным преимуществом — большей скоростью чтения и меньшими задержками на шаге 2.

Optional колонки

Большинство колонок в YTsaurus являются опциональными (required: false), то есть вместо значения может храниться Null. В CH это не так, большинство колонок не являются Nullable. Использования опциональных колонок замедляет практически все стадии, от чтения и конвертации данных до обработки в CH.

Рекомендуется ставить более жесткую схему и избавляться от optional колонок там, где нет такой необходимости.

Кеши данных

В CHYT есть большое количество кешей, ускоряющих те или иные стадии выполнения запроса.
Самые главные — compressed_block_cache и uncompressed_block_cache. Использование второго избавляет от этапов 2 и 3. Использование первого — от этапов 2, 3 и 4 (разжатие).
Маленькие таблицы скорее всего будут всегда читаться из кеша.

Предыдущая
Следующая