Как стать автором
Обновить

Комментарии 25

Тоже сталкивался с похожей проблемой — когда планировщик тупит и не использует индексы. pg_hint_planner не помог.
Чаще всего таки планировщик оказывается умнее человека :-)
И это прекрасно, очень приятно с Postgres-ом работать.
А как это выяснить, кто прав — я или планировщик?
Я не знаю лучшего способа, чем выключить в конфиге стратегию, которая ему нравится, перезапустить сервер и сравнить cost запросов.

Вообще, если планировщик явно тупит, то первое, что стоит сделать — это ANALYZE таблицы. Ещё можно попробовать сбросить статистику планировщика и дать ей накопиться снова — мало ли, характер нагрузки на сервер изменился.

Но перед сбросом — подумать, почему PostgreSQL может себя так вести.
Например, у вас маленькая таблица, она в кеше — её проще перебрать так, действительно.
Или у вас неселективный запрос — тогда тоже проще считать всё и отфильтровать; потому что если постгрес сначала пойдет в индекс — ему после получения списка строк из индекса придется за каждой пойти в таблицу и перепроверить — получается больше работы с диском, чем подряд.
Это связано с MVCC; в 9.2 появились index-only запросы, но и у них, кажется, есть свои ограничения, я не помню деталей.

По-моему, вот этой причиной — проще считать таблицу, чем делать кучу seek-ов по диску — объясняется большинство случаев выбора Seq Scan постгресом.

Может быть ещё забавное. У меня вот недавно была ситуация — я получал несколько сотен тысяч айдишников в скрипте и по 1000 за раз брал их из базы. Получал таймауты (2 секунды у нас в коде прикручено). Отсортировал айдишники перед тем, как брать из них порции — таймауты ушли :-) И это понятно.
ANALYZE это самое первое, что делаю, да.
Заметил, что часто такое поведение наблюдается, когда по этим индексам идет партицирование таблиц.
О! А я заметил, что если у меня партиционирование по времени, и я делаю запрос по интервалу времени, который целиком укладывается в одну партицию, то намного быстрее запрос идет, если делать его напрямую к ней, а не к сводной таблице.

Не помню уже — то ли разы разницы, а то ли и порядок.
А вы посмотрите analyze для этого запроса — запрос должен сразу перебрасываться на нужную партицию. А cost для обоих запросов должен совпадать. У меня тоже была подобная бага, индекс как-то криво создался чтоли. Пересоздал индекс — все заработало как нужно.
Да я уже гвоздями прикрутил (да-да, именно так!) выбор напрямую нужной партиции :-)

Красиво будет разобраться, конечно, но оно работает — а более животрепещущих проблем навалом.

Но спасибо, я буду в будущем меньше опасаться партиций.
Их не опасаться нужно, а научиться готовить — зело мощный инструмент. Вычислять в коде, к какой партиции обратиться — это #^$!*
Да ладно, не драматизируйте, получилось в пару строчек и вполне надежно :-)
Просто проверка пары дат.
Ну, помимо очевидных плюсов, есть еще один — люблю красивые решения :)
* В определении партиций точно стоят CHECK на ВСЕХ партициях?
* Интервалы указанные в CHECK точно НЕ пересекаются? Это частая проблема, когда используют BETWEEN и границы автоматически включены в обе соседние таблицы.

Ну и как бонус, вдруг кому-то пригодится: небольшой Partitioning триггер, который создаёт партиции автоматически, если её еще не существует при вставке в мастер таблицу.
Если даже pg_hint_planner не помогает, то скорее всего планировщик не тупит, а просто не может то, что вы от него хотите.
Тут у меня правда, есть предположение, что утилита не взлетела, хотя все по инструкции сделал. Ну да Бог с ней. Посыл моего поста заключается в том, как убедиться, что планировщик выбрал оптимальный путь.
Чтобы в части про PostgreSQL можно было что-то понять, нужны версии, определения таблиц, индексов, полные тексты запросов, EXPLAIN (ANALYZE, VERBOSE, BUFFERS) для каждого из запросов. А сейчас пока что только «крик души» )))
Я не готов :-)

Запросы там на несколько сотен символов, непростые. Выводить из этого минимальный повторяющийся случай будет слишком долго, у меня нет времени. Очень много работы.

Мне кажется, суть вполне понятна — вот есть запрос, в нем есть условие по полю intarray, всё работает по индексу (индексу именно по Intarray, именно это поле наиболее селективно), чудесно. Добавляем ещё одно условие на это поле — и кровь кишки :-)

Я не пытаюсь сказать, что тут гарантированно виноват PostgreSQL, я безусловно не понимаю ситуацию до конца, чтобы вот прямо багрепорт пойти написать — но это безусловно было очень странно.
Про постгрес и intarray надо было ко мне обратиться. Там много есть улучшений и ускорений потенциальных.
Олег, мы были бы очень рады с вами познакомиться и пообщаться :-)

Помнится, в первые полгода жизни сервиса я даже с вами связывался, но не мог толком сформулировать свои мысли/вопросы, и общение не пошло.

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

Кстати, двое из нас и с Федором шапочно знакомы — работали рядом в Mail.Ru :-)
Давайте, поработаем. Мы на ниве рекомендаций много работали.
P.S. Где-то на второй трети поста (писал в районе 3 ночи) перестал работать предпросмотр — ну и вообще хабр, потому что 500. Интересно, в чем причина :-)

очевидно накосячили с обновлениями… или просто плановая перезагрузка сервера
А может быть это связано со значением в work_mem (которое всего 1M по умолчанию)? У меня когда-то была подобная проблема, когда планировщик менял план в корне, из-за того, что не мог уместить нужные данные в память. И проявлялось именно при изменении критериев фильтрации.
Не-не, у нас 1GB
1GB? Какая же у Вас большая оперативка… или как же мал Ваш пул запросов. :)

КАЖДЫЙ процесс/запрос может резервировать данное количество памяти для работы (+на самом деле в запросе могут параллельные операции, которые каждая может выделять по work_mem памяти).
Ой, а это мы, оказывается, красиво, да.

Но, видимо, может, да не резервирует — базы в своп ещё не уходили :-)

Спасибо, мы поправим.
Не резервирует, использует по необходимости.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий