В прошлом уроке PostgreSQL прочитал все 506 страниц таблицы заказов ради трёх колонок из одиннадцати. Больше восьмидесяти процентов байт ушло в мусор, и никакой индекс не помог. Проблема была в раскладке: строки лежат на диске целиком. Значит, надо разложить данные иначе.
Тетради вместо карточек
Вернёмся к бухгалтеру и картотеке. Что, если вместо карточек завести тетради, по одной на каждое поле? В тетради «Зона» записаны зоны всех заказов подряд: 5, 11, 3, 1, … В тетради «Цена» цены в том же порядке: 191, 215, 177, 245, … И так одиннадцать тетрадей.
Чтобы узнать всё о третьем заказе, придётся открыть все одиннадцать тетрадей на третьей строчке. Кассиру это неудобно. Зато бухгалтеру для выручки по зонам нужны ровно две тетради: «Зона» и «Цена». Остальные девять он даже не достаёт с полки.
Это и есть колоночное хранение.
Как это выглядит на диске
Колоночная база хранит каждую колонку отдельным файлом. Внутри файла значения идут подряд, в одном и том же порядке строк. Пятая строка таблицы это пятое значение в каждом из файлов.
строковая раскладка (PostgreSQL) колоночная раскладка (ClickHouse)
страница 1: zone_id.bin: 5 11 3 1 ...
[1, 5, 23, delivered, 191.00, ...] price_rub.bin: 191 215 177 245 ...
[2, 11, 24, delivered, 215.00, ...] status.bin: delivered delivered ...
[3, 3, 8, delivered, 177.00, ...] created_at.bin: ...
Запрос «выручка по зонам» читает два файла, zone_id.bin и price_rub.bin. Номер зоны в «Гонце» занимает 2 байта, цена 4 байта. На 41 тысячу заказов это около 250 КБ против 4 МБ у строковой базы. В шестнадцать раз меньше, и это на таблице всего в одиннадцать колонок. Чем шире таблица, тем больше выигрыш: в таблицах событий бывает по сто колонок, а запрос берёт три.
урок из курса
Урок из курса «ClickHouse и аналитические базы». Курс покупается один раз и остаётся навсегда: 500 ₽.
Оплата пока не подключена: премиум и курсы открываются промокодом.