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


16

У меня около 75 миллионов записей в базе данных SQL Server 2008 R2 Express. Каждый - это длинный лат, соответствующий некоторому значению. Таблица имеет столбец географии. Я пытаюсь найти ближайшего соседа для данной широты и долготы (точка). У меня уже есть запрос с пространственным индексом на месте. Но в зависимости от того, где запись находится в базе данных, например, в первом или последнем квартале, запрос может занять от 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

Вот образец лат длинных в моей базе данных. дать представление о точности и плотности. Все 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 может быть установлен.
География

1

Рассмотрим упрощение буфера с помощью BufferwithTolerance . Если точки плотно упакованы, система должна определить, находится ли точка по обе стороны от границы. Чем проще эта линия, тем меньше работы приходится выполнять машине.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.