column2,
MAX(date) AS maxdate,
multiIf (toTime(maxdate) > toTime(toDateTime('2021-01-01 18:00:00')), toDate(maxdate + toIntervalDay(1)), toDate(maxdate)) AS DPDate
FROM db.table1
WHERE column1 IN ('abc', 'qwe', 'ups')
GROUP BY
column1,
column2
И он выполняется больше 200 секунд, как его максимально ускорить индексами, партициями или ещё чем нибудь? При создании таблицы указывалось только:
PRIMARY KEY date
ORDER BY date
SETTINGS index_granularity = 8192;
Если указать:
ORDER BY date, column1
то он уже выполняется 180 сек, но это всё ещё очень много, хотелось бы 30-40. column2 нельзя указать в order by, потому что Nullable :)
Попробуй: - LowCardinality(data_type) для column1 и column2 если они не имеют больше 100К уникальных записей в партиции - не используй Nullable - конвертни колонку и пользуйся дефолтным значением - максимально ограничивай диапазон по колонке date. - сделай партицианирование
Проверю, но скорее всего column1 и column2 имеют больше 100К уникальных записей. Nullable убрал ) Что ты имел в виду под ограничением диапазона по колонке data? Партиционирование по любой колонке выдаёт: DB::Exception: Too many partitions for single INSERT block (more than 100)
Зачем по любой, по дате надо Я бы так пробовал PARTITION BY toYYYYMM(date) ORDER BY column1, column2, date
Вот как раз так и пробовал
Вы сразу за много месяцев пытаетесь вставить данные?
Партицианирование делается по колонке дата по месяцам, а ограничение по времени (например тебе не надо все значения получать и ты делаешь date BETWEEN ‘2021-1101’ AND NOW()
Всем привет! Был вопрос про оптимизацию запроса, теперь указав следующие параметры: ORDER BY (column1, column2, date) PARTITION BY toYYYYMM(date) SETTINGS index_granularity = 65536, index_granularity_bytes = 83886080 Запрос выполняется 30 секунд вместо 240, что всё ещё довольно много. Индекс гранулярности был подобран экспериментально путём создания десятков разных таблиц и сотен запросов. Скажите, я могу указать ещё какие-нибудь параметры чтобы запрос выполнялся <1 секунду?
а сколько у вас данных вообще? какие сервера? settings optimize_aggregation_in_order = 1 пробовали? возможно вам проще mat view сделать для оптимизации
Если считать только эти колонки, где то 8 гб, 1,1 млрд строк Сервер в Managed Service for ClickHouse в Яндекс Облаке: IOPS - Чтение 300, Запись 900. Максимальная пропускная способность - Чтение 90 МБ/с, Запись 90 МБ/с. 2 ядра и 8 Гб памяти. optimize_aggregation_in_order делает запрос медленнее Вьюшка не поможет, потому-что запросы разные будут в эту таблицу а этот как пример просто.
Раз вьха не поможет, то юзайте проэкции, чтобы оптимизировать выбранные запросы. Все запросы не оптимизировать, но приблизиться к оптимальной схеме вполне реально.
А как представления могут помочь? Может я не понял что-то, потому-что проекции по сути тоже самое
очень слабенький сервер, телефон быстрее будет работать) Вам надо сокращать объём данных, или мат вью или проекции нужны
Раньше если вам надо было ускорить какой-нибудь запрос, который содержит агрегации или для него требуется другой порядок сортировки, то использовали мат вьюхи, а потом переписывали код, чтобы для аыбранных запросов ипользовались эти мат вьюхи. Сейчас достаточно написать проекцию и она будет автоматически подхватываться, так что код переписыва не надо.
Сколько можете посоветовать ядер и памяти для таких объёмов (планируется в разы больше)? 8 ядер и 32 гига уже в 3 раза дороже будут стоить ) Хотелось бы убедиться, что проблема в этом
Ну если вместо 2 ядра будет 8, то скорость запросов врядли вырастет больше чем в 4 раза.
Это запрос
Вот тут DDL настроек при создании таблицы
Это только order by
У вас нет в дате фильтра по времени, а партицировпние по месяцам. Вы достаёте данные за всё время, а потом агрегируете? Не пробовали предагоегировать заранее?
CREATE TABLE table1 ( con0 Int64, con1 Int32, column1 String, column2 String, date DateTime ) ENGINE = MergeTree PARTITION BY toYYYYMM(date) ORDER BY (column1, column2, date) SETTINGS index_granularity = 65536, index_granularity_bytes = 83886080;
Не подскажите как возможно заранее предагрегировать?
у вас нет фильтра по дате. это странно, но допустим так надо - вы делаете аналитику по всему интервалу доступных дней. Если это всегда так будет, то нет смысла складывать все значения по всем датам в момент запроса - можно сделать заранее. В результате в таблице будет меньше строк - col1,col2,val и меньше Mb.
Если фильтр по дате все-таки будет, то это уже уменьшит размер выборки при запросе - и это хорошо. Но можно ограничить возможность задания интервалов скажем 1 часом - и снова сложить заранее с точностью до 1 часа - меньше строк, мегабайт - быстрее.
Вообще аналитика по всему интервалу, а под фильтром по дате подразумевается ещё одно условие в WHERE по колонке date?
Сделайте отдельную таблицу/проекцию с группировкой по нужной колонке и максимумом нужного значения.
Обычно аналитика по сырым данным смотрится только за последний период (день/неделя/месяц), а за весь период уже юзают агрегации, а не читают с диска терабайты данных.
Обсуждают сегодня