GIS-Lab: Руководство по PostGIS: 4.5. Построение индексов

Руководство по PostGIS

4.5. Построение индексов

<<< предыдущая глава | оглавление | следующая глава >>>

Индексы делают возможным использование пространственной базы данных для больших наборов данных. Без индексации, любой поиск приводил бы к "последовательному сканированию" каждой записи в базе данных. Индексация организовывает данные в поисковое дерево, по которому можно быстро перемещаться, чтобы быстро найти конкретную запись. PostgreSQL по умолчанию поддерживает три вида индексов: индексы B-Tree, индексы R-Tree и индексы GiST.

  • B-Tree (B-деревья) используются, когда данные могут быть отсортированы вдоль одной оси; например, числа, символы, даты. Данные ГИС не могут быть рациональным способом отсортированы вдоль одной оси (что больше: (0,0) или (0,1) или (1,0)?), а потому для их индексирования B-Tree не помогут.

  • R-Tree ( R-деревья) разбивают данные на прямоугольники, под-прямоугольники, под-под-прямоугольники и т.д. R-Tree используются в некоторых пространственных базах данных для индексации данных ГИС, но в PostgreSQL реализация R-Tree не столь надежна, как реализация GiST.

  • Индексы GiST (Generalized Search Trees - обобщенные деревья поиска) разделяют данные на "объекты по одну сторону " ("things to one side"), "пересекающиеся объекты " ("things which overlap"), "объекты внутри" ("things which are inside") и могут быть использованы для многих типов данных, включая данные ГИС. PostGIS использует реализацию R-Tree поверх GiST для индексации данных ГИС.

4.5.1. Индексы GiST

GiST означает "обобщенное поисковое дерево" ("Generalized Search Tree") и является общей формой индексации. Кроме индексации ГИС, GiST используется для ускорения поиска для всех видов нерегулярных структур данных (целочисленные массивы, спектральные данные и т.д.), к которым неприменимо обычное индексирование B-Tree.

Когда таблица данных ГИС вырастает до нескольких тысяч записей, создание индексов необходимо для ускорения поиска пространственных данных (кроме случаев, когда весь ваш поиск основывается атрибутах. Тогда вам достаточно обычных индексов полей атрибутов).

Ниже описан синтаксис запроса для создания GiST-индекса столбца "geometry":

CREATE INDEX [indexname] ON [tablename] USING GIST ( [geometryfield] );

Создание пространственного индекса требует интенсивных вычислений: для таблицы размером 1 миллион строк на машине Solaris 300MHz создание индекса заняло около 1 часа. После создания индекса важно заставить PostgreSQL собрать табличную статистику, которая используется для оптимизации запросов:

VACUUM ANALYZE [table_name] [column_name];
	-- Это необходимо только для PostgreSQL 7.4 и более старых
SELECT UPDATE_GEOMETRY_STATS([table_name], [column_name]);

В PostgreSQL индексы GiST имеют два преимущества перед R-Tree. Во-первых, индексы GiST являются "null-безопасными" ("null safe"). Это означает, что они могут индексировать столбцы, содержащие значения null. Во-вторых, индексы GiST поддерживают концепцию "потерь" ("lossiness"), которая имеет значение, когда объекты ГИС занимают больше 8К (размер страницы PostgreSQL). Потери позволяют PostgreSQL сохранять в индексе только "значимую" часть объекта. В случае объектов ГИС, ими являются охваты. R-Tree не может быть создан для объектов ГИС, занимающих больше 8K.

4.5.2. Использование индексов

Как правило, индексы ускоряют доступ к данным оставаясь при этом прозрачными: как только индекс создан, планировщик запросов самостоятельно решает, использовать ли индексную информацию для создания быстрого плана запроса. К сожалению, планировщик запросов в PostgreSQL неоптимально использует индексы GiST. Так, иногда, там, где при поиске должен использоваться пространственный индекс, используется последовательное сканирование всей таблицы выполняемое по умолчанию.

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

  • Во-первых, убедитесь, что собрана статистика о числе и распределении значений в таблице, для предоставления планировщику запросов лучшей информации при принятии решений об использовании индекса. Для PostgreSQL 7.4 и более ранних это делается запуском update_geometry_stats([table_name, column_name]) (подсчет распределения) и VACUUM ANALYZE [table_name] [column_name] (подсчет числа значений). В PostgreSQL 8.0 запуск VACUUM ANALYZE выполнит обе операции. Вам следует регулярно производить вакуумизацию базы данных. Большинство DBA PostgreSQL позволяют регулярно выполнять VACUUM, как задачу cron во время слабой загрузки базы.

  • Если вакуумизация не работает, вы можете заставить планировщик использовать индекс с помощью команды SET ENABLE_SEQSCAN=OFF. Вам следует осторожно использовать эту команду, и только для запросов с пространственными индексами: как правило, планировщик лучше вас знает, когда следует использовать B-Tree. После выполнения запроса, вам следует восстановить прежнее значение ENABLE_SEQSCAN, чтобы другие запросы обрабатывались планировщиком как обычно.

    Замечание

    Начиная с версии 0.6 нет необходимости заставлять планировщик использовать индекс с ENABLE_SEQSCAN.

  • Если вы считаете, что планировщик неправильно оценивает расходы на последовательное сканирование по сравнению с использованием индекса, можете уменьшить величину random_page_cost в postgresql.conf или использовать SET random_page_cost=#. По умолчанию этот параметр равен 4. Попробуйте установить его в 1 или 2. Уменьшение значения сделает планировщик более склонным к использованию индексов.

Последнее обновление: August 14 2008
(Наверх)

Back to top

(С) Виктор Вислобоков, 2008-2023