Postgis 2.0'da GIST Index kullanarak en yakın Komşu sorunu (<-> işlevi)


25

Masamın her satırı için (cosn1) aynı sınıfın en yakın poligonuna olan mesafeyi hesaplamak için Postgis 2.0 yeni fonksiyonunu <-> (Geometry Distance Centroid) kullanmaya çalışıyorum.

Aşağıdaki kodu kullanmaya çalışıyordum:

WITH index_query AS (
  SELECT g1.gid As ref_gid, ST_Distance(g1.the_geom,g2.the_geom) As ENN    
    FROM "cosn1" As g1, "cosn1" As g2   
    WHERE g1.gid <> g2.gid AND g1.class = g2.class
    ORDER BY g1.gid, g1.the_geom <-> g2.the_geom) 
SELECT DISTINCT ON (ref_gid) ref_gid, ENN 
    FROM index_query
ORDER BY ref_gid, ENN;

Ama sonra uyarıyı anlıyorum:

Not: Dizin yalnızca, geometrilerden birinin sabit olması durumunda başlar (bir alt sorguda / altta değil). örneğin 'SRID = 3005; POINT (1011102 450541)' :: a.geom yerine geometri

İndeks hiç kullanılmayacak ve sorgu kullanmadan önce neredeyse aynı zaman alacaktır:

SELECT DISTINCT ON(g1.gid)  g1.gid As ref_gid, ST_Distance(g1.the_geom,g2.the_geom) As ENN    
    FROM "cosn1" As g1, "cosn1" As g2   
    WHERE g1.gid <> g2.gid AND g1.class = g2.class
    ORDER BY g1.gid, ST_Distance(g1.the_geom,g2.the_geom)

Biri bana sorgunun performansını iyileştirmeme izin veren bir geçici çözümü işaret edebilir mi?

Çok teşekkür ederim.


Henüz bir cevap verilmediğinde, bunu PostGIS posta listesinde sormak isteyebilirsiniz.
GIS-Jonathan

Zaten yaptım, ama aynı zamanda herhangi bir cevap da vermedim.
Alexandre Neto

3
Yapmanız gereken mesafe hesaplamalarının sayısını azaltacak olan cümlede, g1.gid> g2.gid komutunu kullanabilirsiniz. Ne yazık ki, <-> operatörü sabit olmadan çalışana kadar, bu tür bir sorguda çok fazla hız artışı göremeyiz.
John Powell,

John, "cosn1" tablomdaki çokgenlerin her biri için EEN'i güncellemem gerektiğinden, tekrarlananlar bile olsa tüm kılavuzları tutmam gerekiyor. Ama söylediklerin bana bir fikir verdi. Dediğiniz gibi, mesafe hesaplamalarını azaltmak için g1.gid> g2.gis kullanmak, ancak sonuçta g1.gid ve g2.gid tutmak. Bundan sonra, iki alt sorgusunu birleştirebilirim (biri gid olarak g1.gis, diğeri g2.gid ile). Teşekkürler
Alexandre Neto

Sabit sorunu gidermek için olası bir çözümün, SQL işlevinde <-> kullanmak, parametre olarak _geom kullanmak olacağını buldum. Bazı testler yaptım ve bazı durumlarda çok daha hızlı (). Ancak benim durumumda, mesafeler aynı tablonun içinde olduğu için, işlem sırasında birçok mesafe hesaplaması tekrarlanır ve bu da doğrudan sorguyu kullanmaktan daha yavaştır.
Alexandre Neto,

Yanıtlar:


2

Makinemde bazı testler yapan Hum, bu operatör gibi geliyormuş gibi <-> düzgün çalışmıyor. Bunun bir hata olduğundan emin değilim ama çakışan geometrilerde sıfır mesafe bildirildi. Hayır mı diyorsun?

Peki ya geleneksel geleneksel SQL sorgu optimizasyonları? Beklenmeyen sonuçlar <-> operatörüyle sonuçlandığından, onu st_centroid ile değiştiriyorum. Hız konusunda çok daha iyi sonuçlar aldım.

St_overlaps ile umut anlambilim aynı tutar. En azından bu, <-> ile ilgili belgelerden anladım.

Postigs'deki dokümanlardan <->

Diğer geometri türleri için, kayan nokta sınırlayıcı kutu centroidleri arasındaki mesafe döndürülür.

Test verilerime göre ~ 5.5k poligonları uzaysal indekslemeden ~ 1000 saniyeden ~ 5 saniyeye kadar hızlandı.

Yine de neden gruplama yapmak için DISTINCT ON kullanıyorsunuz? Bazı insanların onu kullandıklarını görüyorum, ancak çoğaltmaları ortadan kaldırmak için var olan grubu göremiyorum.

Sorulan st_centroid hatası olmadan standart SQL optimizasyonları ile sorgunuz

select g1.gid, min( st_distance( g1.the_geom, g2.the_geom ) ) AS enn
FROM 
  "cosn1" AS g1, "cosn1" AS g2
WHERE
  g1.gid <> g2.gid
  AND g1.class = g2.class
  AND g1.the_geom && g2.the_geom
GROUP BY
  g1.gid

Noel tatili kutlu olsun!


Üzgünüz ama cevabınız sorunu çözmüyor. Aslında çok daha hızlı, ancak sonuçlar doğru değil, çünkü nihai sonuç poligonların centroidleri kullanılarak gerçek geometrileri yerine hesaplandı. <->, aday arayışını en yakın komşuya ulaştırmayı amaçlar ancak sonunda en iyi adaylara olan mesafeyi hesaplamak için gerçek geometrileri kullanmalıdır. Ayrıca DISTINCT ON \ ORDER BY yerine MIN \ GROUP BY kullanmayı da denedim ve daha yavaş görünüyor.
Alexandre Neto

Ancak <-> operatörü için postgis el kitabı nokta dışı geometriler için centroid kullandığını belirtir. Böylece benim çözümüm size benzer sonuçlar verecektir. Size en iyi sorgunuzla aynı sonuçları vermelidir. Lütfen <-> operatörüyle ilgili sonuçların da doğru olup olmadığını kontrol edin. Test verilerimde sıfır uzunluklu geometriler rapor etti, böylece sonuçları kırılabilir ve bu çözüm daha doğru veriler verdi. Bazı pastie sitelerinde hataları gösteren bazı örnek kayıtları yayınlayabiliyorsanız, çözüm üzerindeki kusurları keşfedebiliriz.
cavila,

Sorgumu kontrol ederseniz, <-> operatörü yalnızca adayları sipariş etmek için kullanılır, nihai sonuç gerçek geometriler kullanılarak hesaplanır. Her neyse, daha önce söylediğim gibi, <-> performans artışı yalnızca sabit noktalarla çalışır. Orijinal sorum buydu.
Alexandre Neto,

Öyleyse, üst sorgunun alt sorgunun karşılığı olmadığını kabul ediyor musunuz? Sıra değişeceğinden, çünkü <-> operatörü SİPARİŞ st_centroid ve st_distance size farklı bir değer verecek mi? Farklı bir sıra, DISTINCT ON yan tümcesine geçen ilk satır olarak farklı bir sorgu getirebilir mi? Geçerli sorgu, hız iyileştirmesi gereken en düşük soru olur mu?
cavila,

Evet, ilk sorgu alttaki hızdaki hızı arttırma amaçlı. Ve evet, g1.geom <-> g2.geom centroidleri kullandığı için, biraz farklı bir sonuç verebilir. Bu, ilk sıranın daha yakın olamayacağı anlamına gelir. İşe yaraması için, sınır 10 deyince sıraya bir sınır koymak zorunda kalacağım ve sonra mesafenin gerçek değerlerini çıkarmak zorunda kalacağım olduğuna inanıyorum. Bunun yerine <#>, centroidler yerine sınırlayıcı kutuları kullananlar bile kullanılabilir.
Alexandre Neto,
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.