184 похожих чатов

Друзья, доброго времени суток! Такой вопрос: Мы используем BI продукт FineBI, внутри

которой есть какая-то своя китайская колоночная БД.
Грузим в 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 млн. строк во втором случае?

7 ответов

121 просмотр

сжатие зависит от сортировки, если значение в колонке лежит в рандомном порядке, сжатие будет плохое если колонка в 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

unhingedlunatic- Автор вопроса
Konstantin Ilchenko
сжатие зависит от сортировки, если значение в коло...

Спасибо! Так еще наглядней это видно) 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 на строку, кошмар просто. В самих запросах или при создании таблицы ни там ни там сортировка не указывалась, но, видимо, так исторически сложилось, что в первой таблице реально бренд чаще за подряд идет одинаковый, а во второй как-то в разнобой. Или это бы не помогло без явной сортировки? Тогда еще такой вопрос: допустим у меня есть два поля "Дата" и "Бренд". Сделав сортировку по Дате и Бренду одновременно (но Дата первая в сортировке) и просто по полю Бренд, в первом случае столбец Бренд будет занимать больше места? Т.е. я обречен на какие-то компромиссы всегда, типа сортирую по Бренду, уменьшаю размер этого столбца, но увеличиваю размер столбца Дата таким образом.

unhingedlunatic
Спасибо! Так еще наглядней это видно) column|type ...

> Т.е. я обречен на какие-то компромиссы всегда Это вообще всегда в разработке, приходится везде выбирать Порядок колонок обычно зависит от кардинальности Чем меньше уникальных значений тем раньше стоит ставить в ключ сортировки, тогда следующая колонка будет лежать "лучше" Ну и частоту фильтрации по колонке стоит учитывать, если у вас 100% запросов используют какую-то колонку, то стоит её тоже поближе к началу двигать > Или это бы не помогло без явной сортировки? Ну если вы в одном случае всталяете 1млн строк по одному бренду, а во втором случае в разнобой, то может быть и без сортировки разница.

unhingedlunatic- Автор вопроса
Konstantin Ilchenko
> Т.е. я обречен на какие-то компромиссы всегда Эт...

Константин, спасибо большое) стало понятней, завтра попробую поиграться с сортировкой

unhingedlunatic
Константин, спасибо большое) стало понятней, завтр...

если уникальных брендов не много(до 10 тысяч значений) можно ещё попробовать LowCardinality(String) тип попробовать, должно ещё меньше места занимать

unhingedlunatic- Автор вопроса
Konstantin Ilchenko
если уникальных брендов не много(до 10 тысяч значе...

Их как-раз плюс минус 10 тысяч 😁 но у меня другие поля есть, например, города и специальности, можно туда, наверное, это попробовать прикрутить, их то совсем мало

unhingedlunatic
Их как-раз плюс минус 10 тысяч 😁 но у меня другие ...

Тогда вполне возможно имеет смысл использовать lowCardinality

Похожие вопросы

Обсуждают сегодня

Ребят в СИ можно реализовать ООП?
Николай
33
~ 2m21s  nix shell github:nixos/nixpkgs#stack ~  stack ghc -- --version error: … while calling the 'derivationStrict' builtin at /builtin/derivation.nix:...
Rebuild your mind.
6
Добрый вечер, Пока не совсем понимаю как наладить общение между телеграм ботом и ПО для работы с сим боксом. По самому боту так понял: - Нужен некий баланс, который можно поп...
Magic
6
Всем доброго вечера. Разрабатываю 32 раз. приложение в Delphi. Столкнулся с тем, что стандартный  TFilestream  не работает с большим файлом > 2 ГБайт (после вызова функции see...
Vadim Gl
16
Всем привет! Имеется функция: function IsValidChar(ch: UTF8Char): Boolean; var i: Integer; ValidChars: AnsiString; begin ValidChars := 'abcdefghijklmnopqrstuvwxyzABCDE...
Евгений
44
добрый день. Подскажите, есть сайт на 1.4.7 и я хочу обновиться, особо ничего не меняя. мне выбирать версию 1.4.35 или третью ветку? и можно ли обновлять "как есть", или нужно...
Digital Cat
12
Кто кодит под Лазарем на винде, у вас аналогично VCL переопределяются CreateWnd и CreateParams для конкретных классов контролов и все заданные флаги влияют?
А Андрей
11
У меня задача: написать брокер сообщений. Очереди и потребители. Очереди поддерживают приоритеты. Очередь отдает сообщения, только обработчикам с соответствующими характеристи...
Aleksandr Filippov
2
народ, плиз хелп, всю голову сломал себе уже... разве может быть так, что GetProcAddress( GetModuleHandle( "kernel32.dll" ), "SetThreadDescription" ) вернёт ненулевое значение...
Iluha Companets
12
А, ты про текущую реализацию? Нет конечно, я бы сделал правильно - сейчас там гавнокод
Александр (Rouse_) Багель
6
Карта сайта