которой есть какая-то своя китайская колоночная БД.
Грузим в FineBi датасет относительно небольшой (20 млн. строк) - получаем 13.1 GB.
Грузим такой же датасет в CH - там он весит 7.1 GB.
Обрадовавшись, я подумал, что так будет и со всеми датасетами. Но когда загрузил датасет с большим числом строк (200+ млн. строк), получил обратный эффект, размер датасета в CH больше в 2 раза, чем в китайской БД.
Стал смотреть на размер отдельных столбцов в мегабайтах и заметил такую штуку.
Вот запрос к маленькой табличке и информация по столбцу brand.
SELECT
"column"
, "type"
, "column_bytes_on_disk" / 1024 / 1024 AS "column_bytes_on_disk_mb"
, "rows"
FROM system.parts_columns
WHERE 1=1
AND "table" = 'mart_rx_prescriptions_with_category'
AND "column" = 'brand'
Результат следующий:
column|type |column_bytes_on_disk_mb|rows |
------+------+-----------------------+--------+
brand |String| 41.45439147949219|22774591|
brand |String| 1.4867048263549805| 807546|
Теперь аналогично для большой таблицы:
SELECT
"column"
, "type"
, "column_bytes_on_disk" / 1024 / 1024 AS "column_bytes_on_disk_mb"
, "rows"
FROM system.parts_columns
WHERE 1=1
AND "table" = 'mart_so_regions__dbt_backup'
AND "column" = 'brand'
Результат следующий:
column|type |column_bytes_on_disk_mb|rows |
------+------+-----------------------+--------+
brand |String| 128.24172687530518|14024704|
brand |String| 129.45257377624512|14155776|
brand |String| 129.4500217437744|14155776|
brand |String| 129.46148300170898|14155573|
brand |String| 107.90291976928711|11796480|
brand |String| 21.57454204559326| 2359296|
brand |String| 107.2841968536377|11730944|
brand |String| 21.582709312438965| 2359296|
brand |String| 21.567069053649902| 2359296|
brand |String| 21.577152252197266| 2359296|
brand |String| 20.982440948486328| 2293760|
Так вот теперь вопрос - почему, по сути, одно и то же стринговое поле, которое содержит одни и те же значения с примерно одной и той кардинальностью в первом случае занимает 41 мегабайт на 22 млн. строк и 128 мегабайт на 14 млн. строк во втором случае?
сжатие зависит от сортировки, если значение в колонке лежит в рандомном порядке, сжатие будет плохое если колонка в ORDER BY, значит одинаковые значения лежат рядом на диске, значит сжимаются данные в разы лучше ну и запрос вы странно делаете, сделайте группировку по всем партам и посчитайте размер 1 строки SELECT column, type, sum(column_bytes_on_disk) AS compressed, formatReadableSize(compressed) AS human, sum(column_data_uncompressed_bytes) AS uncompressed, uncompressed / compressed AS ratio, sum(rows) AS row_count, compressed / row_count AS size_per_row FROM system.parts_columns WHERE (table = '...') AND (column = '...') AND active GROUP BY column, type ORDER BY compressed ASC
Спасибо! Так еще наглядней это видно) column|type |compressed|human |uncompressed|ratio |row_count|size_per_row | ------+------+----------+----------+------------+-----------------+---------+-----------------+ brand |String| 767340495|731.79 MiB| 1584925202|2.065478379321034| 80019253|9.589448366882404| column|type |compressed|human |uncompressed|ratio |row_count|size_per_row | ------+------+----------+---------+------------+------------------+---------+------------------+ brand |String| 45027003|42.94 MiB| 457261697|10.155277201105301| 23582137|1.9093690703264086| 9.6 vs 1.9 на строку, кошмар просто. В самих запросах или при создании таблицы ни там ни там сортировка не указывалась, но, видимо, так исторически сложилось, что в первой таблице реально бренд чаще за подряд идет одинаковый, а во второй как-то в разнобой. Или это бы не помогло без явной сортировки? Тогда еще такой вопрос: допустим у меня есть два поля "Дата" и "Бренд". Сделав сортировку по Дате и Бренду одновременно (но Дата первая в сортировке) и просто по полю Бренд, в первом случае столбец Бренд будет занимать больше места? Т.е. я обречен на какие-то компромиссы всегда, типа сортирую по Бренду, уменьшаю размер этого столбца, но увеличиваю размер столбца Дата таким образом.
> Т.е. я обречен на какие-то компромиссы всегда Это вообще всегда в разработке, приходится везде выбирать Порядок колонок обычно зависит от кардинальности Чем меньше уникальных значений тем раньше стоит ставить в ключ сортировки, тогда следующая колонка будет лежать "лучше" Ну и частоту фильтрации по колонке стоит учитывать, если у вас 100% запросов используют какую-то колонку, то стоит её тоже поближе к началу двигать > Или это бы не помогло без явной сортировки? Ну если вы в одном случае всталяете 1млн строк по одному бренду, а во втором случае в разнобой, то может быть и без сортировки разница.
Константин, спасибо большое) стало понятней, завтра попробую поиграться с сортировкой
если уникальных брендов не много(до 10 тысяч значений) можно ещё попробовать LowCardinality(String) тип попробовать, должно ещё меньше места занимать
Их как-раз плюс минус 10 тысяч 😁 но у меня другие поля есть, например, города и специальности, можно туда, наверное, это попробовать прикрутить, их то совсем мало
Тогда вполне возможно имеет смысл использовать lowCardinality
Обсуждают сегодня