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

Коллеги, кликауз тормозит, при моём первом подходе к задаче. У

меня есть выборка (ключ, начало периода, конец_периода) через subquery, и как натравить это на большую таблицу с фактами, чтобы выбрались нужные записи? Пока что получается только полный скан большой таблицы, т.к where работает после join

37 ответов

16 просмотров

а что за запрос, почему нельзя where до join?

Zorro-Zorroff Автор вопроса
Konstantin Ilchenko
а что за запрос, почему нельзя where до join?

потому что там в where есть >= на даты, а они не умеют быть в ON

смотрите сторону engine=Join и joinGet https://clickhouse.com/docs/en/engines/table-engines/special/join#creating-a-table либо в сторону словарей SOURCE(CLICKHOUSE(query ...) LAYOUT range_hashed(...) и dictGet https://clickhouse.com/docs/en/sql-reference/dictionaries#range_hashed

Zorro Zorroff
потому что там в where есть >= на даты, а они не у...

может вам вместо джойна нужен range словарь? https://clickhouse.com/docs/en/sql-reference/dictionaries#range_hashed и что без join тоже фулскан по ключам сортировки? и как вообще понять проблему если запрос не показываете)

Zorro-Zorroff Автор вопроса
Konstantin Ilchenko
может вам вместо джойна нужен range словарь? https...

table facts (ts datetime64, key, value) primary key(ts, key) -- large table table facts_1m (ts datetime64, key, value) primary key(ts, key) -- aggregated by 1 minute. в facts_1m лежат sum(value) поминутно по ключам, например. они считаются на кроне, рандомно, на каждый ключ, версией 1 агрегации. Не вдаемся в проблемы почему так, т.к. тут я упрощаю. запрос with last_available as (select key, max(ts) maxts, max(ts)+interval 1 day maxtsneed from facts_1m group by key), -- найти последние вставленные, но не хотеть слишком много ибо ОЗУ на 1 запрос. insquery as (select toMinute(ts) tm, key, sum(value) value -- агрегация from facts f outer join last_available la on f.key=la.key -- прикрутить по ключу and f.ts>la.maxts and f.ts < la.maxtsneed group by key, tm), -- ограничить по диапазону insert into facts_1m select * from insquery -- вставить пропущенное запрос синтаксически не выдержан, но в принципе похож

Zorro Zorroff
table facts (ts datetime64, key, value) primary ke...

первым делом я бы менял ключ сортировки в обоих таблицах на (key, ts), group by ускорится многократно а дальше уже думать над джойн

Zorro-Zorroff Автор вопроса
Zorro Zorroff
table facts (ts datetime64, key, value) primary ke...

версия 1 аггрегации - был предыдущий job который запускался в произвольное время и делал агрегацию по каждому ключу от последнего раза до текущего момента. Таким образом разные ключи агрегированы последний раз в разное время. Я пишу новый job (вторая версия) и хочу одним инсертом вставить всё незааггрегированное по каждому ключу)

Zorro-Zorroff Автор вопроса
Konstantin Ilchenko
первым делом я бы менял ключ сортировки в обоих та...

там так и есть в базе. Я был неточен и по памяти упрощал.

Zorro Zorroff
версия 1 аггрегации - был предыдущий job который з...

ну это хороший вариант, просто выбирать промежуток времени и вставлять всё, без проверок на каждый ключ

Zorro-Zorroff Автор вопроса
Konstantin Ilchenko
ну это хороший вариант, просто выбирать промежуток...

это да, но на текущий момент там рандомные окончания по разным ключам.

Zorro-Zorroff Автор вопроса
Konstantin Ilchenko
ну это хороший вариант, просто выбирать промежуток...

к тому же задача может появляться в подобной формулировке и в других разрезах

Zorro Zorroff
к тому же задача может появляться в подобной форму...

если ключей много и не влазят в память и нужны джойны, мы решаем разбитием на батчи например, циклом key % 10 = 0/1/2/3... в случаях когда памяти хватает но нужна скорость юзаем engine = Join ну и в свежих версиях можно попробовать поиграть с настройкой join_algorithm, иногда очень сильно ускоряет запросы

Zorro-Zorroff Автор вопроса
Konstantin Ilchenko
если ключей много и не влазят в память и нужны джо...

ключей мало. Проблемы с тем, что по ощущению оно не использует индекс чтобы шариться в конце таблицы фактов, а сканирует ее всю.

Zorro-Zorroff Автор вопроса
Zorro Zorroff
ключей мало. Проблемы с тем, что по ощущению оно н...

это не ощущение, а цифры во время select, там progress размером со всю таблицу facts

Zorro Zorroff
ключей мало. Проблемы с тем, что по ощущению оно н...

ну можно через where in попробовать отфильровать например, WHERE (key, toStartOfMinute(ts)) IN (сгенерировать поминутный range от max до max + 1 day). Будет ли разница

Zorro-Zorroff Автор вопроса
Konstantin Ilchenko
ну можно через where in попробовать отфильровать н...

оно не треснет там внутри? а как генерировать range, а как их склеивать?

Zorro Zorroff
оно не треснет там внутри? а как генерировать rang...

ну если ключей немного, то не должно треснуть для теста можно попробовать FROM facts WHERE (key, toStartOfMinute(ts)) IN (SELECT key, arrayJoin(timeSlots(max(ts), toUInt32(60 * 60 * 24), 60)) minute from facts_1m GROUP BY key)

Zorro-Zorroff Автор вопроса
Konstantin Ilchenko
ну если ключей немного, то не должно треснуть для ...

даже работает! спасибо, в этом смысле - ускорил запрос!

Zorro-Zorroff Автор вопроса

щас скажу.

Zorro-Zorroff Автор вопроса
Zorro Zorroff
щас скажу.

у меня предыдущие запросы (часть селекта), генерирующие интервалы, занимают ок 20 секунд. После этого я генерирую arrayJoin, и потом прямой запрос из таблицы с фактами. Там дырка где-то 5 минут должна вернуться. Если я запрашиваю с запасом в сутки вперед и выходит большой arrayJoin, то весь запрос работает 45 секунд. Если я запрашиваю с запасом в час вперед, то работает 27 секунд. В обоих случаях возвращает около 500000 записей из таблицы (фактов) для последующей агрегации. Если старую версию брать, то уходило на десяток минут плюс по ощущениям, я ни разу не дождался, если честно. Время указано на испольнение целиком всего запроса с with...

Zorro-Zorroff Автор вопроса
Konstantin Ilchenko
норм) рабочая техника

теперь если бы еще оптимизировать select key, max(ts) group by key с учетом того что все индексы есть, чтобы не сканировало целиком, было бы совсем улёт 8)

Zorro Zorroff
теперь если бы еще оптимизировать select key, max(...

так оно бы не работало так быстро, если бы индекс не юзался, покажите полный запрос и статистику по нему

Zorro Zorroff
теперь если бы еще оптимизировать select key, max(...

Вроде уже обсуждали что order by limit по индексу пойдет. Ну или projection

Zorro-Zorroff Автор вопроса
Denny [Altinity]
Вроде уже обсуждали что order by limit по индексу ...

да, но там ЕМНИП было для 1 ключа а тут для всех.

Zorro-Zorroff Автор вопроса
Zorro Zorroff
да, но там ЕМНИП было для 1 ключа а тут для всех.

там была фишка с max_block_size, что полезно.

Zorro Zorroff
там была фишка с max_block_size, что полезно.

Ну можно проекцию сделать где будет max уже посчитан

Zorro-Zorroff Автор вопроса
Zorro-Zorroff Автор вопроса
Zorro Zorroff
я туплю, я не понимаю о чем речь.

https://kb.altinity.com/altinity-kb-queries-and-syntax/projections-examples/

Zorro-Zorroff Автор вопроса
Denny [Altinity]
https://kb.altinity.com/altinity-kb-queries-and-sy...

господи боже, а я не в курсе

Zorro Zorroff
господи боже, а я не в курсе

Там внизу ссылки на видео и доки

Zorro-Zorroff Автор вопроса
Konstantin Ilchenko
так оно бы не работало так быстро, если бы индекс ...

так, добавил проекции, поиграл блоком, 9 секунд на часовой интервал, щас интервал еще сделаю динамическим... как смотреть статистику-то?

Zorro Zorroff
так, добавил проекции, поиграл блоком, 9 секунд на...

по хорошему set send_logs_level = 'trace' и дальше запрос выполнить и смотреть логи, максимально подробный вариант

Zorro-Zorroff Автор вопроса
Konstantin Ilchenko
по хорошему set send_logs_level = 'trace' и дальш...

вот на третьем (?) году пользования кликхаузом узнал. Это о чем говорит? Это говорит что все три года всё было и так очень отлично!

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

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

Ребят в СИ можно реализовать ООП?
Николай
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
Карта сайта