Всем доброго времени!
Надеюсь, название темы привлекло внимание экспертов
С Постгресом знаком давно, но только сейчас наткнулся на "интересное" поведение.
Есть большая таблица, точнее, таблица-мастер и таблицы-потомки. Партицирование идет по полю, хранящему дату, на это же поле навешан индекс. Хотя, может партицирование здесь и не при чем.
Этот запрос отрабатывает влет:
SELECT * FROM master_table WHERE mydate >= 'вчера'
SELECT * FROM master_table WHERE mydate >= 'вчера' AND mydate <= 'сегодня'
Для чистоты эксперимента кэш сбрасывал.
Есть какие мысли?
Размести сюда EXPLAIN ANALYSE
Размести сюда
EXPLAIN ANALYSE
explain analyze
Пришлось добавить еще одно поле - msisdn (тоже индексированное) в условие выборки.
Для первого (быстрого) запроса планировщик дает такую картину:
Для второго (медленного):
Никакого криминала не вижу...
Сущий ад. Это даже невозможно
Сущий ад.
Это даже невозможно прочесть. Просто сравни. Первый случай как у тебя:
Второй случай как у тебя:
Что за child_table, если поиск идёт только по parent. Что за дикое количество индексов? Они ещё и "горизонтальные"...
Тебе надо вообще индексы отключить, иначе тут просто даже не разобраться.
Или это всё представление, в котором много join'ов...
это партицирование
Обычное партицирование по дате + региональному признаку.
master_table - родительская таблица
child_table_yyyyyMMdd_regNN - партиция, разделение идет по индексированным полям.
Если смотреть explain, то видно, что планировщик направляет поиск в нужные партиции.
Иначе как ворочать базой на пару терабайт?
В первом случае ходит по
В первом случае ходит по индексу
Filter: (mydate >= '2015-07-14'::date)
-> Bitmap INDEX Scan ON child_table_y2015m07d14reg32_msisdn (cost=0.00..305.19 rows=12101 width=0) (actual time=5.275..5.275 rows=0 loops=1)
INDEX Cond: (msisdn = 79200392997::bigint), и фильтр по дате
во втором
используются два индекса
-> Bitmap INDEX Scan ON child_table_y2015m07d14reg32_msisdn (cost=0.00..305.19 rows=12101 width=0) (actual time=0.209..0.209 rows=0 loops=1)
INDEX Cond: (msisdn = 79990717388::bigint)
-> Bitmap INDEX Scan ON child_table_y2015m07d14reg32_date (cost=0.00..323.18 rows=12101 width=0) (never executed)
INDEX Cond: ((mydate >= '2015-07-14'::date) AND (mydate <= '2015-07-16'::date))
и merge по BitmapAnd, есть некоторые пояснения тут http://www.postgresql.org/message-id/12553.1135634231@sss.pgh.pa.us
и тут решение http://habrahabr.ru/post/169751/
спасибо
Большое вам спасибо за ответ и материал - начинаю изучать.
pg_hint_plan
Когда-то я уже пробовал использовать этот модуль, но ничего хорошего не получилось - планировщик у Постгреса все ж не глупый.
Если я правильно понял ваш совет, вы предложили с помощью pg_hint_plan заменить Bitmap INDEX Scan на Index Scan. Я это сделал и сначала посмотрел explain - планировщик отобразил очень высокий cost (10 нулей). Сам запрос считается полчаса и, наверное, я его закенселю - планировщик со стоимостью, похоже, не обманул.
Разница между доступами к
Разница между доступами к данным по индексам http://use-the-index-luke.com/sql/explain-plan/postgresql/operations,
По идее нужно заставить ипользовать Bitmap Index Scan / Bitmap Heap Scan
Bitmap Heap Scan
Увы, не прокатило с BitmapHeapScan. Считалось даже немного дольше.
интересно а как такой
интересно а как такой вариант
select * from (
select * from table where date >= mindate
) where date <= maxdate
Хорошая идея Но планер
Хорошая идея Но планер обмануть не удалось - expalin у этих запросов один-в-один и считалось, соответственно, столько же долго.
по идее с with прокатит with
по идее с with прокатит
with q as (select * from table where date >= mindate)
select * from q where date <= maxdate
Бинго! Пока не знаю почему,
Бинго!
Пока не знаю почему, но Постгрес явно не любит условие на дату в обе стороны. Вот если только "меньше" либо только "больше", то все работает быстро.
Вы конструкцией with как раз сымитировали то, что он обрабатывает, и получился хороший результат.