2013-05-19 2 views
5

У меня есть таблица, в которой есть поле datetime "updated_at". Многие мои запросы будут запрашивать в этом поле, используя запросы диапазона, такие как строки, которые обновили_а> определенную дату.Postgres: Оптимизация запросов с помощью datetime

Я уже добавил индекс в updated_at, но большинство моих запросов все еще очень медленны, даже когда у меня было ограничение на количество возвращаемых строк.

Что еще я могу сделать для оптимизации запросов, запрашивающих поля datetime?

+5

Можете ли вы опубликовать план объяснения, общее количество строк и точное значение «очень медленно»? –

+0

Пожалуйста, прочитайте http://stackoverflow.com/tags/postgresql-performance/info (и связанную страницу вики SlowQueryQuestions), затем обновите свой вопрос с помощью соответствующих результатов «объясните анализ» и сообщите об этом. Поскольку вы используете генератор запросов, вам может понадобиться использовать 'auto_explain' или регистрировать запросы и повторно выполнять их вручную. –

+0

Пожалуйста, опубликуйте схему и тип запроса, который медленный. Вопрос, как он сформулирован, не может быть разумным ответом ... –

ответ

1

Обычно оптимизаторы базы данных не будут использовать индексы для открытых диапазонов, например updated_at > somedate.

Но во многих случаях колонна datatime не будет превышать «сейчас», так что вы можете сохранить семантику > somedate путем преобразования состояния в диапазоне с помощью between так:

where updated_at between somedate and current_timestamp 

A between предикат гораздо более вероятно, чтобы оптимизатор решил использовать индекс.


Просьба этого подхода улучшить работу вашего карьера.

+2

Действительно ли это относится к PostgreSQL? Я бы подумал, что оптимизатор рассмотрит диапазон значений в соответствующем столбце, через pg_statistics, и произведет оценочную мощность набора результатов для предиката. Если максимальное значение меньше или равно current_timestamp, я бы не подумал, что будет большая разница. Будьте интересны для Хенли, чтобы проверить, хотя - план объяснения раскроет все. –

+0

@DavidAldridge в моем опыте, '>' просто не оптимизирован хорошо. Мне также нравится, как Харви публикует результаты. – Bohemian

+3

Postgres ** будет использовать индекс для '>', если это полезно. Нет необходимости в 'between': см. Здесь пример http://sqlfiddle.com/#!12/e3142/3 Все зависит - как обычно, от индекса - независимо от того, стоит ли стоимость использования индекса меньше чем что-то еще –

0

Предполагая, что индекс используется, но производительность все еще бедны, единственное средство, я могу думать о том, чтобы сгруппировать таблицу по этому показателю: http://www.postgresql.org/docs/9.1/static/sql-cluster.html

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

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

также:

Когда таблица быть сгруппированы, доступ ЭКСКЛЮЗИВ замок приобретается на нем. Это предотвращает выполнение любых других операций с базой данных (как чтениями, так и записью) в таблице до тех пор, пока CLUSTER не будет завершен.

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

3

Для любого запроса, использование индекса зависит от стоимости использования этого индекса по сравнению с последовательным сканированием

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

Вы используете postgres. Postgres не поддерживает кластеризацию по данному атрибуту. Это означает, что postgres, столкнувшись с запросом диапазона (типа att> a и att < b), должен вычислить оценку количества кортежей в результате (убедитесь, что вы часто удаляете свою базу данных) и стоимость использования индекс по сравнению с последовательным сканированием. он затем определит, какой метод использовать.

вы можете проверить это решение, запустив

EXPLAIN ANALYZE <query>; 

в PSQL. Он скажет вам, использует ли он индекс или нет.

Если вы действительно хотите использовать индексы вместо последовательного сканирования (иногда это необходимо), и вы действительно действительно знаете, что вы делаете, вы можете изменить стоимость последовательного сканирования в константах планировщика или отключить последовательное сканирование в пользу любого другого метода. Смотрите эту страницу для деталей:

http://www.postgresql.org/docs/9.1/static/runtime-config-query.html

Убедитесь, что вы выберите правильную версию документации.

--dmg