чтения интернетов появилось такое понимание.
1) Если широкая таблица, и идет фильтрация по where, то даже с использованием PRIMARY клик читает в память все колонки и идет большая нагрузка на IO и все тормозит
2) PREWHERE позволяет прочитать только отдельные колонки (желательно чтобы это были маленькие по размеру колонки (int32,int64)) и предварительно отфильтровать результаты
Мое понимание правильно? Должна ли колонка по которой идет PREWHERE быть в ORDER BY ?
Нет Prewhere работает только с колонками которые в primary key И читает pk вместо колонок и позволяет очень быстро определить надо ли вычитывать кусок из data parts или нет Есть настройка включенная по умолчанию optimize_move_to_prewhre которая переписывает запрос и старается колонки из pk пробросить из where в prewhere
Про настройку "optimize_move_to_prewhre" я читал, и вроде как оптимизация отключается если руками задать prewhere. А вот про "Prewhere работает только с колонками которые в primary key" - те если колонка указала в prewhere, но ее нету в primary key, то клик просто игнорирует это выражение? Так как запрос где есть prewhere выполняется, даже если нет колонке в индексе. И вот тут https://t.me/clickhouse_ru/180395 , давалась рекомендация наоборот ставить в prewhere только колонки которых нету в primary. А по сути, что такое prewhere - ? это чтение одной колонки (вместо чтения всех колонок в случае с where) и фильтрации по этой колонке?
"Prewhere работает только с колонками которые в primary key" это неправда... отсечение по индексам и партициям делается до всего вообще... prewhere работает по всем колонкам
индекс разреженный и указывает на засечки в колонках. т.е. засечки тоже разреженные и указывают на гранулу колонки (на 8192 строки). можно найти из индекса список засечек, которые надо прочитать, и переходя в засечки найти смещения которые надо прочитать из колонок. Prewere позволяет сузить список засечек, потому в первом проходе прочитаются только колонки, которые в prewhere проверится условия для них, список станет меньше и все остальны колонки прочитаются уже для более короткого списка. Конечно в prewhere должны быть колонки которые не в индексе, НО очень часто помогает для колоконок которые в индексе, потому что индекс может быть длинным и плохо фильтровать по последним полям.
Спасибо за подробный ответ, про prewhere и индекс все понятно. А вот prewhere и колонки которых нет в индексе, по сути есть смысл тестировать только колонки которые можно очень быстро прочитать с диска и которые дадут хорошую фильтрацию. делать prewhere на колонку с длинными строками скорее всего смысла не будет, так как полное чтение всей колонки может быть довольно длительным, а вот считать миллиард int32 - вполне норм? 1 миллиард int32 - это 4гигабайта, а nvme могут отдать это за время меньше секунды
в prewhere имеет смысл перемещать колонки которые хорошо фильтруют и если есть еще более тяжелые поля которые не prewhere . Т.е. если запрос считает например count() и select выбирает только поля по которым фильтрует, то нет смысла помещать что либо в prewhere. Prewhere заставляет кх прочитать колонку два раза.
спасибо, все понятно.
Тогда сорян. значит это я не правильно понимаю как работает prewhere ... извините кажется я ввел вас в заблуждение короче суть prewhere в том это возможность быстро после стадии partition by вычислить нужно ли вытаскивать данные из data part или нет как именно оно реализовано. я похоже не правильно себе представляю подозреваю что да, это чтение одной, несколько небольших хорошо сжатых колонок с константными условиями фильтрации чтобы определять быстро надо ли остальные колонки вычитывать или нет
Обсуждают сегодня