SQL Server 2008'de 70 milyon nokta bulutunda en yakın komşu sorgusunu optimize edin


16

Bir SQL Server 2008 R2 Express veritabanında yaklaşık 75 milyon kaydım var. Her biri bir değere karşılık gelen bir lat uzunluğudur. Tabloda coğrafya sütunu vardır. Belirli bir enlem boylam (nokta) için en yakın komşuyu bulmaya çalışıyorum. Zaten uzamsal dizin ile bir sorgu var. Ancak, örneğin ilk çeyrek veya son çeyrekte kaydın veritabanında nerede olduğuna bağlı olarak, sorgunun en yakın komşuyu bulmak yaklaşık 3 ila 30 saniye sürebilir. Bu sorgu veya uzamsal dizini optimize ederek çok daha hızlı sonuç vermek için optimize edilebilir hissediyorum. Şu anda varsayılan ayarlarla bazı uzamsal dizin uygulandı. İşte benim tablo ve sorgu böyle görünüyor.

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]

Kullandığım uzamsal Endeks:

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]

İşte kullanıyorum Sorgu:

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

İşte benim veritabanındaki lat longs bir örnek. doğruluk ve yoğunluk hakkında fikir vermek. Tüm 70 milyon kayıt bir şehir içindir (Lidar verileri).

POINT (-95.669434934023087 30.049513838913736)

Şimdi bu sorgu yukarıda açıkladığım gibi bana sonuç verir, ancak performansı mümkün olduğunca artırmak istiyorum. Tahminim, performansı daha iyi optimize etmek için yukarıda olabileceğim uzamsal indeksin varsayılan değerlerini değiştirerek. Bunun hakkında ipucu var mı?

Tamponu 10'dan 1000'e değiştirmeyi denedim ama neredeyse aynı sonuçlarla.

Ayrıca performansı artırmak için diğer önerilerinizi bekliyoruz.

İşte şu anda kullandığım sistem:

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
Bu lidar verisi mi? Öyleyse bir lidaretiket eklemeyi düşünün .
Kirk Kuykendall

2
SQL Server'ı konuşmuyorum, ancak sorgunuz hedef noktanın 1000 metrelik bir tamponu içinde yatan tüm noktaları bulmak zorunda, benim gözlenmemiş gözüme benziyor. Bunlar nokta, poligon içinde testleri olacak yolu yavaş sizin de sunulan çözümlerin temelini oluşturur yakınlık testler, daha önceki soruya .
whuber

@whuber: Mesafeye dayalı sorguları ve zamanı dakika cinsinden denedim. yüksek yol. Belki bazı yerlerde yanlış gidiyorum. Çokgendeki bu noktadan itibaren saniyeler içinde zaman alır. Tamponu 10'dan 10000'e değiştirmenin bile zamanında çok az etkisi vardır.
Shaunak

1
@Shaunak Öyleyse, mesafeye dayalı sorgular ile ilgili bir şey var, çünkü teorik olarak KD ağaçları gibi uygun indeksler kullanılarak ortalama olarak mikrosaniye (veya daha iyi) ve milisaniye (en kötü durumda) yapılabilirler . Arabellek içi aramayı optimize etmenin yollarını aramak yerine bunları iyileştirmeyi düşünmek isteyebilirsiniz.
whuber

Bu ızgara verileri mi? Neden bir raster kullanmıyorsunuz?
Matthew Snape

Yanıtlar:


9

Uzamsal dizininizin nasıl kullanıldığına ilişkin ayrıntılar için sp_help_spatial_geography_index saklı yordamını çalıştırmayı deneyin . Şöyle bir şey kullanabilmelisiniz:

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;

Öne çıkan bir şey olup olmadığını görmek için sonuçları sorunuza gönderin. Her bir öğenin anlamı burada bulunabilir .

Koordinatlarınız yansıtıldıysa, hesaplanan X, Y alanlarında ve X <MinX ve X> MaxX vb.

Koordinatlarınızı yansıtmak (GEOMETRY türü bir alanda), uzamsal endeksinizi, performansı önemli ölçüde hızlandırabilecek verilerle sınırlamanıza da olanak tanır. Dünya kapsamlarını verilerinizin kapsamlarıyla değiştirin:

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
Göre technet.microsoft.com/en-us/library/bb934196.aspx BOUNDING_BOX GEOMETRY_GRID değil GEOGRAPHY_GRID için sadece kullanılabilir
Kelso

1
Cevap güncellendi. GEOMETRY türü BOUNDING_BOX ayarlanabildiğinden çok daha hızlı olmalıdır.
geographika

1

BufferwithTolerance ile arabelleği basitleştirmeyi düşünün . Noktalar sıkıca paketlenmişse, sistemin bir noktanın sınırın her iki tarafında olup olmadığını tanımlaması gerekir. Bu çizgi ne kadar basitse, makinenin işi o kadar az olur.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.