Таблица T_PIN
имеет 300 000 пинов и T_POLYGON
имеет 36 000 полигонов. T_PIN
имеет этот индекс:
CREATE SPATIAL INDEX [T_PIN_COORD] ON [dbo].[T_PIN]
(
[Coord]
)USING GEOGRAPHY_GRID
WITH (GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH),
CELLS_PER_OBJECT = 128, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY];
T_POLYGON
имеет:
CREATE SPATIAL INDEX [T_POLYGON_COORD] ON [dbo].[T_POLYGON]
(
[COORD]
)USING GEOGRAPHY_GRID
WITH (GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH),
CELLS_PER_OBJECT = 128, PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY];
Запрос для поиска пересечения T_PIN
и выполнения T_POLYGON
занимает более 45 минут:
SELECT COUNT(*)
FROM T_PIN
INNER JOIN T_POLYGON
ON T_PIN.Coord.STIntersects(T_POLYGON.COORD) = 1;
Результат - 4 438 318 строк.
Как я могу ускорить этот запрос?
Ответы:
Во-первых, проверьте, используется ли пространственный индекс, посмотрев план выполнения запроса, и посмотрите, есть ли элемент поиска кластерного индекса (пространственный).
Предполагая, что он используется, вы можете попробовать добавить вторичный / упрощенный фильтр на основе ограничивающего прямоугольника с упрощенными полигонами, чтобы проверить сначала. Сопоставления с этими упрощенными полигонами могут затем проходить через основной фильтр для получения окончательных результатов.
1) Добавьте новый столбец географии и геометрии в таблицу [dbo]. [T_POLYGON]:
2) Создайте ограничивающие полигоны (это включает в себя первоначальное преобразование в геометрию, чтобы воспользоваться STEnvelope ()):
3) Создайте пространственный индекс в столбце упрощенной географии
4) Получите пересечения с этим упрощенным столбцом географии, затем снова отфильтруйте по соответствующим типам данных географии. Примерно как то так:
РЕДАКТИРОВАТЬ : вы можете заменить (1) и (2) с этим вычисленным, постоянным столбцом. Благодарю Пола Уайта за предложение.
источник
Подобные запросы часто занимают много времени из-за сложности полигонов. Я видел, как сложные береговые линии (например) требовали возрастов, чтобы проверить точки, которые находятся вблизи их границ, и им приходилось масштабировать многие уровни, чтобы определить, находится ли точка внутри или снаружи.
... чтобы вы могли попробовать
.Reduce()
полигоны, чтобы посмотреть, поможет ли это.Подробнее об этой функции можно узнать на сайте http://msdn.microsoft.com/en-us/library/cc627410.aspx.
источник
Согласно документам Microsoft, пространственные индексы будут использоваться с типами географии в следующих методах, когда они появляются в начале предиката сравнения с
WHERE
предложением:STIntersects
STDistance
STEquals
Только методы с геометрическими типами (ограниченный список) будут инициировать использование пространственного индекса
JOIN ... ON
, поэтому измените код, который будет использоваться,WHERE geog1.STIntersects(geog2) = 1
и это должно повысить скорость.Я также рекомендую принять совет в ответе g2server и добавить следующее для фильтрации и добавить пространственный индекс на него
тогда вы могли бы получить запрос, подобный следующему (я написал это сообщение быстро и еще не проверял, это просто что-то попробовать, потому что я видел, что ваш запрос и ответы с наибольшим количеством ответов используют JOIN ON пространственный op = 1, который не будет использовать пространственный индекс):
К вашему сведению: вышеупомянутое не работает, если в
SimplePolysGeog
конечном итоге перекрывается (как в выводе может быть в двух упрощенных геог, просто запустил это на людях на участках в состоянии и так как обычные границы полиса, ограничивающие прямоугольники перекрываются), поэтому в большинстве случаев В некоторых случаях будет выдано сообщение о том, что подзапрос вернул более одного результата.Из обзора пространственных индексов MS Docs :
Следующий запрос будет работать в случае
SimplePolysGeogs
наложения:источник