Оптимізуйте запит найближчого сусіда на хмарі 70 мільйонів точок на SQL Server 2008


16

У мене близько 75 мільйонів записів у базі даних SQL Server 2008 R2 Express. Кожен - це lat long, що відповідає деякому значенню. У таблиці є стовпчик з географії. Я намагаюся знайти одного найближчого сусіда для заданої широти (точки). У мене вже є запит із просторовим індексом. Але залежно від того, де знаходиться запис у базі даних, скажімо, першої чи останньої чверті, запит може зайняти від 3 до 30 секунд, щоб знайти найближчого сусіда. Я думаю, що це можна оптимізувати, щоб отримати набагато швидший результат, оптимізуючи запит або просторовий індекс. Зараз застосовано деякий просторовий індекс із налаштуваннями за замовчуванням. Ось як виглядає моя таблиця та запит.

CREATE TABLE lidar(
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [POINTID] [int] NOT NULL,
    [GRID_CODE] [numeric](17, 8) NULL,
    [geom] [geography] NULL,
 CONSTRAINT [PK_lidar_1] PRIMARY KEY CLUSTERED ([id] ASC)
 WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, 
 ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

Просторовий індекс, який я використовую:

CREATE SPATIAL INDEX [SPATIAL_lidar] ON [dbo].[lidar] ([geom]) USING  GEOGRAPHY_GRID 
WITH (
GRIDS =(LEVEL_1 = MEDIUM,LEVEL_2 = MEDIUM,LEVEL_3 = MEDIUM,LEVEL_4 = MEDIUM), 
CELLS_PER_OBJECT = 16, PAD_INDEX  = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF,  
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

Ось запит, який я використовую:

declare @ms_at geography = 'POINT (-95.66 30.04)';
select TOP(1) nearPoints.geom.STAsText()as latlon 
from
(
select r.geom
from lidar r With(Index(SPATIAL_lidar))
where r.geom.STIntersects(@ms_at.STBuffer(1000)) = 1
) nearPoints

Ось зразок lat longs у моїй базі даних. дати уявлення про точність і щільність. Усі 70 мільйонів записів для одного міста (дані Лідара).

POINT (-95.669434934023087 30.049513838913736)

Тепер цей запит дає результати, як я описав вище, але я хочу максимально покращити продуктивність. Моя здогадка, налаштовуючи значення за замовчуванням просторового індексу, я можу бути вище, щоб краще оптимізувати продуктивність. Якісь підказки з цього приводу?

Я спробував змінити буфер від 10 до 1000, але з майже однаковими результатами.

Також вітаються будь-які інші пропозиції щодо підвищення продуктивності.

Ось система, якою я зараз користуюся:

Windows 7 64bit Professional
Intel(R) Core(TM)2 Quad CPU    Q9650  @ 3.00GHz (4 CPUs), ~3.0GHz
Ram: 8 GB
NVIDIA GeForce 9500 GT

1
Це дані про лідар? Якщо так, подумайте про те, щоб додати lidarтег.
Кірк Куйкендалл

2
Я не розмовляю на SQL Server, але мені здається, що ваш запит повинен знайти всі точки, що лежать в буфері на 1000 метрів від цільової точки. Ці тести на багатокутники будуть набагато повільнішими, ніж тести на близькість, які є основою для рішень, запропонованих у попередньому запитанні .
whuber

@whuber: Я спробував дистанційні запити та час у хвилинах. шлях до високого. Можливо, я десь помиляюся. Станом на цей момент у багатокутнику, це займає час у секундах. Навіть варіювання буфера від 10 до 10000 має мало уявлення про час.
Шаунак

1
@Shaunak Тоді щось має значення з запитами на основі відстані, оскільки теоретично їх можна зробити в середньому за мікросекунди (або краще) та в мілісекунди (найгірший випадок), використовуючи відповідні індекси, такі як дерева KD . Можливо, ви хочете подумати над їх вдосконаленням, а не шукати шляхи оптимізації пошуку «в точку буфера»
whuber

Це дані сітки? Чому б не використовувати растр?
Метью Снейп

Відповіді:


9

Спробуйте запустити збережену процедуру sp_help_spatial_geography_index, щоб отримати детальну інформацію про те, як використовується ваш просторовий індекс. Ви повинні мати можливість використовувати щось на кшталт:

declare @ms_at geography = 'POINT (-95.66 30.04)'
set @ms_at = @ms_at.STBuffer(1000).STAsText()
exec sp_help_spatial_geography_index 'lidar', 'SPATIAL_lidar', 0, @ms_at;

Опублікуйте результати у своєму запитанні, щоб побачити, чи щось виділяється. Значення кожного з пунктів можна знайти тут .

Якщо ваші координати проектувались, ви також можете виконати простий непросторовий запит на обчислених полях X, Y та перевірку X <MinX і X> MaxX тощо.

Проектування координат (у полі типу GEOMETRY) також дозволяє обмежити ваш просторовий індекс обсягом даних, які можуть значно прискорити продуктивність. Замініть розширення світу на розширення ваших даних:

CREATE SPATIAL INDEX [SPATIAL_lidar] ON [dbo].[lidar] ([geom]) USING  GEOMETRY_GRID 
WITH (
GRIDS =(LEVEL_1 = MEDIUM,LEVEL_2 = MEDIUM,LEVEL_3 = MEDIUM,LEVEL_4 = MEDIUM), 
CELLS_PER_OBJECT = 16, PAD_INDEX  = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF,  
ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON,
BOUNDING_BOX =(-90, -180, 90, 180),) ON [PRIMARY]

1
За technet.microsoft.com/en-us/library/bb934196.aspx в BOUNDING_BOX може бути використаний тільки для GEOMETRY_GRID, а НЕ GEOGRAPHY_GRID
Келсо

1
Оновлена ​​відповідь. Тип GEOMETRY повинен бути набагато швидшим, оскільки можна встановити BOUNDING_BOX.
geographika

1

Розглянемо спрощення буфера за допомогою BufferwithTolerance . Якщо точки щільно упаковані, система має визначити, чи точка є будь-якою стороною межі. Чим простіше ця лінія, тим менше роботи доводиться робити машині.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.