| |
Для быстрой работы каждого запроса в вашей базе в основном требуется следующее:
В данном разделе описаны действия, которые должны периодически выполняться для каждой базы. От разработчика требуется только настроить их автоматическое выполнение (при помощи cron) и опытным путём подобрать его оптимальную частоту.
Используется для «сборки мусора» в базе данных. Начиная с версии 7.2, существует в двух вариантах:
Рекомендуется достаточно частое -- в [7] и [8], например, раз в несколько минут (!) -- выполнение VACUUM ANALYZE для часто обновляемых баз (или отдельных таблиц). В обыкновенных случаях достаточно ежедневного 8 выполнения этой команды. При этом обратите внимание: если «бутылочное горлышко» вашего сервера находится в районе дисковой подсистемы, то выполнение VACUUM параллельно с обычной работой может крайне отрицательно сказаться на производительности.
Команду VACUUM FULL стоит запускать достаточно редко, не чаще раза в неделю. Её также имеет смысл запускать вручную для конкретной таблицы после удаления или обновления большой части записей в ней.
Служит для обновления информации о распределении данных в таблице. Эта информация используется оптимизатором для выбора наиболее быстрого плана выполнения запроса.
Обычно команда используется в связке VACUUM ANALYZE. Если в базе есть таблицы, данные в которых не изменяются и не удаляются, а лишь добавляются, то для таких таблиц можно использовать отдельную команду ANALYZE. Также стоит использовать эту команду для отдельной таблицы после добавления в неё большого количества записей.
Начиная с версии 7.4, в дистрибутиве PostgreSQL поставляется программа pg_autovacuum, которая отслеживает изменения в таблицах и автоматически запускает команды VACUUM и/или ANALYZE для этих таблиц по достижении определённого предела.
Использование этой программы позволяет отказаться от настройки периодического выполнения команд VACUUM и ANALYZE. Более того, в случае использования pg_autovacuum ресурсы не тратятся впустую на обработку таблиц, которые практически не подвергались изменениям.
Для работы pg_autovacuum должен быть включён сборщик статистики (см. пункт 2.4.2) и включён параметр stats_row_level.
Команда REINDEX используется для перестройки существующих индексов. Использовать её имеет смысл в случае
Если вы заметили подобное поведение какого-то индекса, то стоит настроить для него периодическое выполнение команды REINDEX. Учтите: команда REINDEX, как и VACUUM FULL, полностью блокирует таблицу, поэтому выполнять её надо тогда, когда загрузка сервера минимальна.
Опыт показывает, что наиболее значительные проблемы с производительностью вызываются отсутствием нужных индексов. Поэтому столкнувшись с медленным запросом, в первую очередь проверьте, существуют ли индексы, которые он может использовать. Если нет -- постройте их.
Излишек индексов, впрочем, тоже чреват проблемами:
Команда EXPLAIN [запрос] показывает, каким образом PostgreSQL собирается выполнять ваш запрос. Команда EXPLAIN ANALYZE [запрос] выполняет запрос 10 и показывает как изначальный план, так и реальный процесс его выполнения.
Чтение вывода этих команд -- искусство, которое приходит с опытом. Для начала обращайте внимание на следующее:
При тестировании запросов с использованием EXPLAIN ANALYZE можно воспользоваться настройками, запрещающими оптимизатору использовать определённые планы выполнения. Например,
Результаты работы сборщика статистики (см. пункт 2.4.2) доступны через специальные системные представления. Наиболее интересны для наших целей следующие:
Вы можете построить индекс не только по полю/нескольким полям таблицы, но и по выражению, зависящему от полей. Пусть, например, в вашей таблице foo есть поле foo_name, и выборки часто делаются по условию «первая буква foo_name = 'буква', в любом регистре». Вы можете создать индекс
ON foo ((lower(substr(foo_name, 1, 1))));
WHERE lower(substr(foo_name, 1, 1)) = 'ы';
Следует отметить, что возможности задания подобных индексов были значительно расширены в версии 7.4, и приведённый пример может потребовать доработки, чтобы быть запущенным на более старой версии.
Под частичным индексом понимается индекс с предикатом WHERE. Пусть, например, у вас есть в базе таблица scheta с параметром uplocheno типа boolean. Записей, где uplocheno = false меньше, чем записей с uplocheno = true, а запросы по ним выполняются значительно чаще. Вы можете создать индекс
WHERE NOT uplocheno;
Обычные индексы не могут быть использованы в запросах, ищущих, например, вхождение подстроки в строку. Для этого требуются специальные средства полнотекстового поиска.
Наиболее продвинутым из имеющихся средств является tsearch2 http://www.sai.msu.su/ megera/postgres/gist/tsearch/V2/ Он поставляется в дистрибутиве PostgreSQL версии 7.4 в каталоге contrib/tsearch2, вариант для версии 7.3 можно скачать на указанном сайте.
За полным описанием возможностей tsearch2 обратитесь к поставляемой с ним документации.
Этот пункт очевиден для опытных пользователей PostrgeSQL и предназначен для тех, кто использует или переносит на PostgreSQL приложения, написанные изначально для более примитивных СУБД.
Реализация части логики на стороне сервера через хранимые процедуры, триггеры, правила 11 часто позволяет ускорить работу приложения. Действительно, если несколько запросов объединены в процедуру, то не требуется
В этом разделе описываются запросы, для которых по разным причинам нельзя заставить оптимизатор использовать индексы, и которые будут всегда вызывать полный просмотр таблицы. Таким образом, если вам требуется использовать эти запросы в требовательном к быстродействию приложении, то придётся их изменить.
Все агрегатные функции в PostgreSQL реализованы одинаково: сначала выбираются все записи, удовлетворяющие условию, а потом к полученному набору записей применяется агрегатная функция. У такого подхода есть достоинства -- вы можете легко написать собственную агрегатную функцию -- но есть и недостаток, который заключается в том, что для работы функций типа min() / max() весь набор записей совершенно не нужен.
Для их работы рациональней было бы воспользоваться индексом по полю, для которого ищется максимум (минимум), но для этого придётся сделать реализацию этих агрегатных функций отличной ото всех остальных.
Запрос вида
Запрос вида
К функции count() относится всё вышесказанное по поводу реализации агрегатных функций в PostgreSQL. Кроме того, информация о видимости записи для текущей транзакции (а конкурентным транзакциям может быть видимо разное количество записей в таблице!) не хранится в индексе. Таким образом, даже если использовать для выполнения запроса индекс первичного ключа таблицы, всё равно потребуется чтение записей собственно из файла таблицы.
Запрос вида
Простого решения проблемы, к сожалению, нет. Возможны следующие подходы:
Сразу отметим, что в версии 7.4 в обработку подзапросов с IN / NOT IN были внесены изменения, и теперь они работают (как минимум) не медленнее, чем подзапросы с EXISTS / NOT EXISTS. Если вы по каким-то причинам не можете обновить версию сервера до 7.4, то читайте дальше.
При использовании подзапроса вида
FROM foo
WHERE foo_field IN (
SELECT bar_field
FROM bar
...
);
Перепишите подзапрос с использованием конструкции EXISTS:
FROM foo
WHERE EXISTS (
SELECT bar_field
FROM bar
WHERE bar.bar_field = foo.foo_field
...
);
Закладки на сайте Проследить за страницей |
Created 1996-2024 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |