PostGIS ST_Intersects'te performans sorunu nasıl düzeltilir?


9

Ben postgis bir acemi ve sorgu performans bir sorun var.

Bu benim sorgu:

SELECT DISTINCT ON (userid) userid ,ST_AsText(position), timestamp  
FROM table1 
WHERE ST_Intersects ( ST_GeomFromText('a multiypolygon geom goes here',4326),position) 
ORDER BY userid, timestamp desc

ve sorun benim çokgen benim ÇOK büyük çokgenler (kelime doc 600 sayfa uzunluğunda!) içerir ve yürütmek için 2 saatten fazla sürdü!

Sorgumu optimize etmenin veya başka bir yol kullanmanın bir yolu var mı?

Lütfen yardımınız büyük beğeni topluyor!

Yanıtlar:


8

Yapmanız gereken büyük çokgengonunuzu tek çokgenler (ST_Dump ile) olarak bir tabloya koymak ve üzerine bir dizin koymaktır. Gibi bir şey:

CREATE TABLE big_polygon as
SELECT (ST_Dump( ST_GeomFromText('a multiypolygon geom goes here',4326))).geom as geom;

-- It is always great to put a primary key on the table
ALTER table big_polygon ADD Column gid serial PRIMARY KEY;

-- Create the index
CREATE INDEX idx_big_polygon_geom
on big_polygon
USING gist(geom);

-- To give the database some information about how the index looks
analyze big_polygon;

-- Then you go:
SELECT DISTINCT ON (userid) userid ,ST_AsText(position), timestamp  
FROM table1, big polygon WHERE ST_Intersects ( big_polygon.geom,position) 
ORDER BY userid, timestamp desc;

Bunun birkaç nedenden dolayı çok daha hızlı olması gerekir.


Bu harika cevap için teşekkürler Nicklas. Üzgünüm, birden fazla çokgenim olduğunu ve zaten dizin içeren bir tabloda saklandığını belirtmeyi özledim. Ancak geom verilerinin doğrudan daha hızlı olmasını sağladım. Ancak, önerdiğiniz şekilde deniyorum ama yine de çok uzun zaman alıyor! başka bir öneriniz var mı?
Sara

@Sara. Tamam, bu yüzden ST_Dump ile önerdiğim gibi çoklu geometrileri tek geometrilere bölmeyi denediniz mi?
Nicklas Avén

Kaç kullanıcı konumundan bahsediyoruz? Kaç büyük çokgen var? Big_polygons_table'dan SELECT ST_npoints'ten (geom) ne elde edersiniz?
Nicklas Avén

Üzgünüm, sizin için daha açık hale getirmek için tablolarım hakkında daha fazla açıklamama izin verin: Yaklaşık 230 satırı olan bir geom sütunu içeren table1'im var ve her satırda bir çokgen var (ülkeleri temsil ediyorlar, bu yüzden boyutlarına göre değişiyorlar) , ve the_geom sütununda dizin var. Konum sütunu (noktalar), zaman damgası, kullanıcı kimliği ve kimlik (pk) ve (konum, zaman damgası, kullanıcı kimliği) kullanılarak oluşturulan 3 dizin içeren Tablo2.Bu tablo yaklaşık 103496003 satır çok büyüktür Bu maksimum ST_npoints sayısı 1440430 ve minimum sayı 16. Seni şaşırtırsam özür dilerim ama gerçekten yardımına ihtiyacım var! Teşekkürler
Sara

2

Ne tür bir kaliteye bağlıdır - hassasiyete ihtiyacınız var. Http://postgis.net/docs/ST_Simplify.html kullanarak çokgenleri açıkça basitleştirebilirsiniz.

CBS başvurumun geliştirilmesi sırasında sık sık yaptığım şey, verileri en aza indirmenin en iyi yolunu düşünmekti. Örneğin. örneğin, sınır kutusundaki çokgenleri önceden seçin. - Zoomlevel'e bağlı olarak ultra hassas sonuçlara (st_simplify) ihtiyacınız yok ...

Umarım bu sana biraz yardımcı oldu!


Hızlı cevabınız için teşekkürler Martin. Benim sorunum çok doğru olması için sonuca ihtiyacım var, bu yüzden bu fonksiyonun burada bana yardım etmeyeceğini düşünüyorum! ama öneri için teşekkürler
Sara

0

Postgres ve / veya sql uzmanlığınıza bağlı olarak birkaç seçeneğiniz vardır:

  1. belirli bir darboğazda vurup vurmadığınızı öğrenmek için EXPLAIN komutuyla sorguyu analiz edin . Uyarı: bazen EXPLAIN çıktısının anlaşılması zor olabilir

  2. Eğer emin çoğu veya tablo1 de geometrilerin önemli bir bölümünü bekliyorsanız DEĞİL MultiPolygon kesiştiği sen (küçük parçalar halinde multiploygon kırarak yani) daha basit bir poligon karşı bir ön koşul uygulamak deneyin ve sonra yalnızca üzerinde ağır MultiPolygon kavşak çalıştırabilir bu sonuçlar. Örnek için aşağıya bakın.

  3. eğer ve CPU darboğaz yalnızca ben (yani sunucu sıkışmış işlem kavĢaklardır) dully Eğer daha büyük, daha hızlı, daha güçlü CPU almak önermek veya Amazon'un EC2 kapalı bir kerelik Yüksek CPU Örneği kira ve olduğunuzda onu yok tamam

2. madde için örnek sorgu:

SELECT DISTINCT ON (st1.userid) st1.userid ,ST_AsText(st1.position), st1.timestamp  
FROM (
    select userid, position, timestamp from table1 
    WHERE ST_Intersects ( YOUR_MULTIPOL_BOUNDS_HERE,position)
) as st1 
WHERE ST_Intersects ( ST_GeomFromText('a multiypolygon geom goes     here',4326),st1.position) 
ORDER BY st1.userid, st1.timestamp desc

Performansı artırmak için alt seçimi st1'i geçici olarak bir tablo olarak gerçekleştirebilirsiniz, böylece dizine ekleyebilirsiniz.

@Nicklas, yorumlarda 2. öneri örneğinin yardımcı olmaması gerektiğini belirtmek için haklıdır. Haklı, ama sanırım ben de (kısmen) haklıyım.

Aslında, geçen Kasım postgis ML'de çok benzer bir soru soruldu (ve cevaplandı):

http://postgis.refractions.net/pipermail/postgis-users/2011-November/031344.html

ve öneri, çokgenin aslında kırılmasıdır, böylece indeks, basit bir sınır kontrolü tarafından tetiklenecek yanlış kavşakları en etkili şekilde filtreleyebilir.


öneri 2 yardımcı olmamalıdır, çünkü indeks tam olarak bunu yapar. Böylece bu yapı bir kez daha aynısını yapacak.
Nicklas Avén

@ NicklasAvén haklısın, cevabı değiştirdim
unicoletti

0

kullanma ST_SubDivide()

Postgis'in 2.2 sürümü için kullanabilirsiniz ST_SubDivide.

ST_Subdivide - Kümedeki hiçbir geometrinin belirtilen sayıda köşeden fazla olmadığı bir geometri kümesi döndürür.

setof geometry ST_Subdivide(geometry geom, integer max_vertices=256);

Yapabilirsiniz Ayrıca

  • geçici tablo kullan
  • bir endeks

Burada ST_SubDivideçokgeni 10 veya daha az köşeye sahip alt poligonlara ayırmak için kullanıyoruz .

CREATE TEMP TABLE divided AS
SELECT ST_SubDivide(bigmultipolygon,10)::geometery AS t(geom);

CREATE INDEX divided_idx ON divided USING gist(geom);

Sonra

SELECT DISTINCT ON (userid) userid ,ST_AsText(position), timestamp  
FROM table1
JOIN divided AS d
  ON ST_Intersects( d.geom, position )
ORDER BY userid, timestamp desc;

Yukarıdakileri yapmayın, yuvarlama hataları sunar

Genel Ayar

Ayrıca dokümanlardaki Performans İpuçları başlıklı bölüme bakın . Uygun şekilde ayarlandığınızdan emin olun. max_parallel_workers_per_gatherParalelleştirmeden yararlanmak için yükseltmeyi düşünün (şu anda varsayılan olarak kapalıdır).

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.