2010-08-12 4 views
10

Я работаю над перемещением некоторых возможностей пространственного поиска из Postgres с PostGIS на SQL Server, и я вижу довольно ужасную производительность даже с индексами.Почему мои пространственные запросы медленнее в SQL Server, чем PostGIS?

Мои данные около миллиона точек, и я хочу, чтобы выяснить, какие из этих точек в пределах заданной формы, поэтому запрос выглядит следующим образом:

DECLARE @Shape GEOMETRY = ... 
SELECT * FROM PointsTable WHERE Point.STWithin(@Shape) = 1 

Если я выбираю довольно небольшую форму, Иногда я могу получить второстепенное время, но если моя форма довольно большая (что они иногда есть), я могу получить время более 5 минут. Если я запускаю те же поисковые запросы в Postgres, они всегда находятся под второй (на самом деле, почти все составляют менее 200 мс).

Я пробовал несколько разных размеров сетки на моих индексах (все высокие, все средние, все низкие), разные ячейки на объект (16, 64, 256), и независимо от того, что я делаю, время остается довольно постоянным. Я хотел бы попробовать больше комбинаций, но я даже не знаю, в каком направлении идти. Больше клеток на объект? Меньше? Какое-то странное сочетание размеров сетки?

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

Есть ли какие-либо советы, которые кто-либо может дать по этому поводу? Все, что я могу найти, предлагает «мы не можем дать вам никаких советов по индексам, просто попробуйте все, и, возможно, один будет работать», но с этим требуется 10 минут для создания индекса, делая это вслепую - это огромная трата времени.

EDIT: Я также разместил это на a Microsoft forum. Вот некоторая информация, они попросили там:

Лучший рабочий индекс я мог бы получить это был один:

CREATE SPATIAL INDEX MapTesting_Location_Medium_Medium_Medium_Medium_16_NDX 
    ON MapTesting (Location) 
USING GEOMETRY_GRID 
    WITH (
    BOUNDING_BOX = (-- The extent of our data, data is clustered in cities, but this is about as small as the index can be without missing thousands of points 
     XMIN = -12135832, 
     YMIN = 4433884, 
     XMAX = -11296439, 
     YMAX = 5443645), 
    GRIDS = (
     LEVEL_1 = MEDIUM, 
     LEVEL_2 = MEDIUM, 
     LEVEL_3 = MEDIUM, 
     LEVEL_4 = MEDIUM), 
    CELLS_PER_OBJECT = 256 -- This was set to 16 but it was much slower 
) 

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

Для этих тестов я провел тестовый поиск (тот, который указан в моем исходном сообщении) с предложением WITH (INDEX (...)) для каждого из моих индексов (тестирование различных параметров для размера сетки и ячеек на объект) , и один без намека. Я также запускал sp_help_spatial_geometry_index, используя каждый индекс и ту же форму поиска. Указанный выше индекс выполнялся быстрее всего и также был указан как наиболее эффективный в sp_help_spatial_geometry_index.

При выполнении поиска я получаю эту статистику:

(1 row(s) affected) 
Table 'MapTesting'. Scan count 0, logical reads 361142, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'Worktable'. Scan count 0, logical reads 0, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 
Table 'extended_index_592590491_384009'. Scan count 1827, logical reads 8041, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0. 

(1 row(s) affected) 

SQL Server Execution Times: 
    CPU time = 6735 ms, elapsed time = 13499 ms. 

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

Наши данные - это адреса по всему штату, поэтому есть несколько областей с очень высокой плотностью, но в основном с редкими данными. Я думаю, проблема заключается в том, что настройка параметров сетки не работает хорошо для обоих. С сетками, установленными в HIGH, индекс возвращает слишком много ячеек в областях с низкой плотностью, а сетки, установленные на LOW, сетки бесполезны в областях с высокой плотностью (в MEDIUM, это не так плохо, но все равно не очень хорошо).

Я могу использовать индекс, это просто не помогает. Каждый тест запускался с включенным «показать фактический план выполнения», и он всегда показывает индекс.

+0

+1: Я хотел бы также знать. –

+0

Ваши миллионные данные хранятся в виде геометрии (плоское, евклидово пространство) или география (округлые, земные координаты)? Если вы смешиваете геометрию и географию, вы собираетесь ввести удар производительности для математики преобразования. – mwalker

+0

@Mwalker, Это все геометрия, и я не думаю, что вы все равно можете смешивать и сопоставлять их. –

ответ

3

Вот некоторые замечания о пространственных расширений SQL-сервера и как обеспечить, чтобы индекс эффективно используется:

Видимо, планировщик имеет трудности построить хороший план если он не знает фактическую геометрию во время разбора. Автор предлагают вставить exec sp_executesql:

Заменить:

-- does not use the spatial index without a hint 
declare @latlonPoint geometry = geometry::Parse('POINT (45.518066 -122.767464)') 
select a.id, a.shape.STAsText() 
from zipcodes a 
where a.shape.STIntersects(@latlonPoint)=1 
go 

с:

-- this does use the spatial index without using a hint 
declare @latlonPoint geometry = geometry::Parse('POINT (45.518066 -122.767464)') 
exec sp_executesql 
N'select a.id, a.shape.STAsText() 
from zipcodes a 
where a.shape.STIntersects(@latlonPoint)=1', N'@latlonPoint geometry', @latlonPoint 
go 
+0

Мой пространственный индекс используется. Я нажимаю «Включить фактический план выполнения» и показывает используемый пространственный индекс. –

+0

Я попробовал это предложение, чтобы быть уверенным, и время и план выполнения были одинаковыми. –

+0

+1 информативный, даже если он не решит проблему OP –

1

Моя реакция кишка «, потому что Microsoft не потрудился сделать это быстро, потому что это не предприятие Особенность". Может быть, я циничен.

Я не уверен, почему вы тоже уходите от Postgres.

+0

Я подозреваю, что это больше связано с тем, что это новая функция; Я слышал, они должны сделать это намного лучше в следующей версии. Что меня смущает, так это то, что я ничего не слышал о том, что он медленный, поэтому я беспокоюсь, что я просто что-то пропустил. –

+1

После работы с пространственными индексами в SQL Server я начинаю с этого, это правда. –

0

Я не знаком с пространственными запросами, но это может быть Параметризированной проблема Query

попробовать написать запрос (без параметров) с фиксированным значением (используйте значение, которое выполняет медленно с параметризованным запросом) и запустите его. Сравните время с параметризованной версией. Если это намного быстрее, то ваша проблема - это параметризованные запросы.

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

+0

Представляется весьма маловероятным, что проблема здесь связана с параметризацией запроса. ОП сказал: «Если я выберу довольно маленькую фигуру, иногда я могу получить суб-второй раз, но если моя форма довольно велика (что они иногда есть), я могу получить время в течение 5 минут». _ ** 1 . ** На производительность запроса влияют геометрические свойства геометрии запроса. ** 2. ** Даже если вы считаете, что параметризованные запросы могут быть медленными, они не должны превращать быстрый запрос в тот, который занимает более 5 минут (!) Для выполнения ... Я не могу придумать разумного объяснения, почему они будет иметь такой эффект. – stakx

1

Правильно ли вы настроили свой пространственный индекс? Является ли ваш ограничивающий прямоугольник правильным? Все точки внутри? В вашем случае, вероятно, HHMM для GRIDS будет работать лучше всего (в зависимости от боудинга).

Можете ли вы попытаться использовать sp_help_spatial_geometry_index, чтобы узнать, что не так? http://msdn.microsoft.com/en-us/library/cc627426.aspx

Попробуйте использовать операцию фильтрации и сообщите нам, какие именно номера вы получаете? (он выполняет только первичный фильтр (использовать индекс) без прохождения вторичного фильтра (истинная пространственная операция))

Что-то не так с вашей настройкой. Пространство действительно новая функция, но это не так уж плохо.

+0

Я пробовал каждую комбинацию из двух размеров (LLLL, LLMM, LLHH, MMLL и т. Д.), И лучше всего было MMMM с 256 ячейками на объект.'sp_help_spatial_geometry_index' сказал, что основной фильтр был эффективен на 90%, что, я думаю, может быть проблемой (другие были на уровне 70%). 'Фильтр' был намного быстрее, чем' STIntersects', но все же на 2-5 раз медленнее, чем Postgres (и не так точно). –

+0

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

+0

Затем попробуйте настроить несколько пространственных индексов вокруг каждой области высокой плотности. Или, по крайней мере, сломать целые США на несколько больших площадей. Я ожидаю, что у вас будет большая часть ваших данных на восточном и западном побережье. – Desinderlase

2

Я считаю, что STIntersects лучше оптимизирован для использования индекса, имеет лучшую производительность, чем STWithin, особенно для больших форм.

+0

Мы пробовали оба, и это не имело значения. –

+0

Возможно ли вам опубликовать информацию о плане после установки заданного профиля статистики, для запроса STIntersects? – Giri

1

Вы могли бы попытаться разбить его на два прохода:

  1. отбора кандидатов в временную таблицу ж/.Filter().
  2. запрос кандидатов w/.STWithin().

например:

SELECT * INTO #this FROM PointsTable WHERE Point.Filter(@Shape) = 1 
SELECT * FROM #this WHERE Point.STWithin(@Shape) = 1 

(замена SELECT * только с реальными столбцами, которые необходимо уменьшить I/O)

Этот вид микро-оптимизации не должно быть необходимым, но у меня есть ранее видели достойные улучшения производительности. Кроме того, вы сможете оценить, насколько избирательным является ваш индекс по отношению от (1) до (2).

3

Я только что провел день по аналогичной проблеме. В частности, мы делаем запрос типа «точка в полигоне», где имеется относительно небольшой набор полигонов, но каждый многоугольник был большим и сложным.

Решение оказалось следующим образом, для пространственного индекса на полигоне таблицы:

  1. Использование «геометрии автоматической сетки» вместо старого MMLL и т.д. Это дает 8 уровней индексации вместо старого 4, и настройки являются автоматическими. И ...
  2. Set «клеток на объект» в 2000 или 4000. (не легкая вещь, чтобы догадаться, учитывая, что по умолчанию 16!)

Это сделал огромную разницу. Это было в 10 раз быстрее, чем пространственный индекс в конфигурации по умолчанию, и в 60 раз быстрее, чем индекс вообще.

1

Проблемы с эффективностью внедрения, в отличие от SQL Server использует Quadtree index, тогда как PostGIS использует индекс R-tree.

R-дерево для большинства случаев является лучшим алгоритмом, особенно для больших наборов данных с различной геометрией.

Смежные вопросы