GIS-Lab: Руководство по PostGIS: Глава 3. Часто задаваемые вопросы

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

Глава 3. Часто задаваемые вопросы

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

3.1. Какие виды геометрических объектов имеются в моем распоряжении?
3.2. Как вставить объект ГИС в базу данных?
3.3. Как построить пространственный запрос?
3.4. Как повысить скорость пространственных запросов в больших таблицах?
3.5. Почему не поддерживаются R-Tree индексы PostgreSQL?
3.6. Почему я должен использовать функцию AddGeometryColumn() и все прочие функции совместимости с OpenGIS?
3.7. Какой способ лучше использовать для поиска всех объектов в радиусе от другого объекта?
3.8. Как включить в запрос перепроектирование координат?
3.1. Какие виды геометрических объектов имеются в моем распоряжении?

В вашем распоряжении point, line, polygon, multipoint, multiline, multipolygon, and geometrycollections (точка, линия, полигон, мультиточка, мультилиния, мультиполигон и геометрическая коллекция). Они определены в формате Well Known Text Open GIS (с расширениями XYZ, XYM, XYZM).

3.2. Как вставить объект ГИС в базу данных?

Сначала вы должны создать таблицу со столбцом типа "geometry", который будет содержать ваши ГИС-данные. Соединитесь с вашей базой данных с помощью psql и выполните SQL:

CREATE TABLE gtest ( ID int4, NAME varchar(20) );
SELECT AddGeometryColumn('', 'gtest','geom',-1,'LINESTRING',2);

Если не получилось добавить столбец геометрии, то, вероятно, вы не загрузили функции и объекты PostGIS в свою базу данных. Смотрите инструкцию по установке.

Далее, вы можете вставлять геометрию в таблицу с помощью SQL-команды insert. Объект ГИС будет форматирован согласно формату "well-known text" Консорциума OpenGIS:

INSERT INTO gtest (ID, NAME, GEOM)
VALUES (
1,
'Первая геометрия',
GeomFromText('LINESTRING(2 3,4 5,6 5,7 8)', -1)
);

Подробную информацию о других объектах ГИС можно посмотреть в справочнике объектов.

Просмотр ваших ГИС-данных в таблице:

SELECT id, name, AsText(geom) AS geom FROM gtest;

Результат должен выглядеть примерно так:

 id | name             | geom
---+------------------+-----------------------------
  1 | Первая геометрия | LINESTRING(2 3,4 5,6 5,7 8)
(1 row)
3.3. Как построить пространственный запрос?

Так же, как вы строите другие запросы к базе данных, используя SQL-запрос для получения значений, функций, логических тестов.

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

Чаще всего вам будет нужен "оператор пересечения" (&&), который проверяет пересекаются ли границы объектов. Польза оператора && заключается в том, что он может использовать пространственный индекс, если он существует. Это ускорит выполнения запроса.

Кроме того, вы можете использовать пространственные функции, такие как Distance(), ST_Intersects(), ST_Contains() and ST_Within() и другие для сужения результатов поиска. Большинство пространственных запросов включают тест на индекс и тест на пространственную функцию. Тест индекса полезен тем, что ограничивает число проверок значений теми, которые могут попасть в требуемый набор. Далее используются пространственные функции используются для окончательной проверки условия.

SELECT id, the_geom FROM thetable
WHERE
the_geom && 'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'
AND
_ST_Contains(the_geom,'POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))');

3.4. Как повысить скорость пространственных запросов в больших таблицах?

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

Для создания пространственного индекса таблицы со столбцом geometry, используйте запрос "CREATE INDEX", как показано ниже:

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

Опция "USING GIST" означает, что сервер должен использовать индекс GiST (Generalized Search Tree - обобщенное поисковое дерево).

Замечание

Индексы GiST допускают потери. Индексы с потерями используют замещающие объекты (в пространственном случае - охват объекта) для создания индекса.

Вы должны также обеспечить планировщик запросов PostgreSQL достаточной информацией о вашем индексе, чтобы он мог выбирать когда их использовать. Чтобы сделать это, вам нужно "собрать статистику" по вашим таблицам с геометрией.

Для PostgreSQL 8.0.x и старше, выполните команду VACUUM ANALYZE.

Для PostgreSQL 7.4.x и младше, выполните команду SELECT UPDATE_GEOMETRY_STATS()

3.5. Почему не поддерживаются R-Tree индексы PostgreSQL?

Ранние версии PostGIS использовали R-Tree индексы PostgreSQL. Однако индексы стали ненужны начиная с версии 0.6, когда появились пространственные индексы со схемой R-Tree-через-GiST.

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

  • R-Tree индексы в PostgreSQL не умеют работать со объектами, размер которых превышает 8K. Индексы GiST умеют, "теряя" часть информации, заменяя собственно объекты на их охват.
  • R-Tree индексы в PostgreSQL не являются "null-безопасными", т.е. индекс на столбце геометрии, в котором содержатся геометрии null создать нельзя.
3.6. Почему я должен использовать функцию AddGeometryColumn() и все прочие функции совместимости с OpenGIS?

Если у вас нет необходимости использовать функции поддержки OpenGIS, не используйте их. Просто создайте таблицы как в старых версиях, определите столбцы геометрии с помощью CREATE. Вся ваша геометрия будет иметь SRID, равный -1, а таблицы мета-данных OpenGIS не будут должным образом заполнены. Однако большинство приложений, основанных на PostGIS, не смогут с этим работать, и мы советуем вам использовать AddGeometryColumn() при создания геометрических таблиц.

Одним из приложений, которое использует мета-данные geometry_columns, является Mapserver. Mapserver может использовать в SRID столбцов геометрии для перепроектирования объектов на лету в текущую проекцию карты.

3.7. Какой способ лучше использовать для поиска всех объектов в радиусе от другого объекта?

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

Для нахождения индексированных расстояний удобна функция ST_DWithin(geometry, geometry, distance). Она создает поисковый прямоугольник, достаточно большой, чтобы включить все на расстояние радиуса поиска. Затем прямоугольник используется для объектов на необходимом расстоянии в результирующем проиндексированном подмножестве.

Например, чтобы найти все объекты в 100 метрах от POINT(1000 1000), хорошо работает следующий запрос:

SELECT * FROM geotable
WHERE ST_DWithin(geocolumn, 'POINT(1000 1000)', 100.0);

3.8. Как включить в запрос перепроектирование координат?

Для перепроектирования, исходная и конечная система координат должны быть определены в таблице SPATIAL_REF_SYS, а геометрии должны иметь установленный SRID. Если это сделано, то перепроектирование просто осуществляется обращением к нужному SRID.

SELECT ST_Transform(the_geom,4269) FROM geotable;

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

Back to top

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