В аналитическом хранилище запросы часто выбирают узкий диапазон времени. Как физический порядок строк может уменьшить объём чтения?
Если строки физически упорядочены или сгруппированы по времени, система может хранить для каждого блока диапазон значений и не читать блоки, заведомо не содержащие нужный период. Этот механизм называют пропуском данных или data skipping. Он снижает объём чтения без изменения логической схемы, но работает эффективно только при хорошем соответствии физического порядка типичным условиям фильтрации.
Колонночные аналитические системы часто обрабатывают большие объёмы данных, поэтому даже чтение нужных столбцов может быть дорогим. Одним из способов уменьшить стоимость стало хранение статистики по физическим блокам и использование физической локальности данных.
Идея появилась как дополнение к индексам и партиционированию. Вместо поиска каждой строки система сначала отбрасывает целые блоки, если их метаданные показывают, что подходящих значений там быть не может.
Пусть запрос выбирает данные за небольшой временной интервал, а таблица содержит годы наблюдений. При случайном расположении строк почти каждый блок может содержать записи разных дат, поэтому фильтр не позволит пропустить значительную часть блоков.
Если система вынуждена читать все блоки, растут нагрузка на хранилище, задержка ответа и стоимость запроса. Неверно выбранный ключ кластеризации может создать лишь видимость оптимизации: метаданные будут слишком широкими и мало что позволят исключить.
При загрузке или перестройке данных система группирует близкие значения времени в одних и тех же блоках. Для каждого блока она сохраняет статистику, например минимальное и максимальное время. Для фильтра по периоду блок пропускается, если его диапазон полностью не пересекается с искомым интервалом.
Например, блок с диапазоном от 1 января до 10 января не нужен запросу за март. Блок с диапазоном от 1 января до 1 апреля пропустить нельзя, даже если фактически в нём лишь несколько мартовских записей: грубая статистика не доказывает отсутствие совпадений.
Эффективность определяется селективностью фильтра и корреляцией между физическим порядком строк и условием запроса. Часто фильтруемый столбец должен быть ведущим ключом сортировки или кластеризации, а данные должны периодически реорганизовываться после значительных дозагрузок.
Это не то же самое, что партиционирование. Партиционирование создаёт более крупные логические области, а data skipping работает на уровне блоков внутри них. Эти методы могут дополнять друг друга, но чрезмерное число партиций увеличивает административные накладные расходы, а плохая кластеризация снижает пользу статистики.
Есть ограничения. Обновления и поздние загрузки могут нарушить локальность, значения с большим разбросом расширяют диапазоны блоков, а стоимость сортировки или обслуживания может превысить выигрыш для редких запросов. Кроме того, пропуск блоков не меняет результат и не заменяет корректное условие фильтра: это оптимизация физического чтения, а не механизм безопасности или согласованности.
В хранилище событий ежедневно поступают данные за текущий и прошлые периоды. Большинство отчётов выбирает небольшой диапазон времени, но поздние события могут приходить спустя несколько дней.
Первый вариант — оставить строки в порядке поступления. Он прост и не требует обслуживания, но поздние события смешивают даты в блоках, поэтому пропуск данных становится слабым. Второй вариант — полностью пересортировывать всю таблицу после каждой загрузки. Он даёт хорошее чтение, но слишком дорог по вычислениям и может создавать конкуренцию с загрузками.
Практичным решением будет кластеризация по времени с периодической фоновой реорганизацией только наиболее изменяемых областей. Для часто запрашиваемого периода это сохраняет высокий эффект data skipping, а стоимость обслуживания ограничивается «горячими» данными. Старые стабильные области можно перестраивать реже.
1. Достаточно ли отсортировать таблицу один раз?
Нет. Новые данные, особенно поступившие с нарушением временного порядка, могут попадать в блоки с широкими диапазонами значений. По мере накопления таких блоков эффективность пропуска снижается, поэтому необходимы подходящий порядок загрузки, фоновая кластеризация или периодическая реорганизация.
2. Всегда ли сортировка по времени является лучшим выбором?
Нет. Она выгодна, если большинство запросов фильтрует время. Если основная нагрузка использует другой признак, например идентификатор клиента или регион, сортировка только по времени может ухудшить пропуск блоков для этих запросов. Выбор физического порядка — компромисс между типичными предикатами, стоимостью обслуживания и распределением данных.
3. Гарантирует ли пропуск блоков, что система прочитает только подходящие строки?
Нет. Метаданные блока обычно позволяют доказать, что блок можно пропустить, но не всегда позволяют выделить внутри оставшегося блока только подходящие строки. Поэтому система может прочитать блок целиком и затем применить фильтр к строкам или значениям столбца. Data skipping уменьшает объём чтения, но не является точным индексом каждой записи.