Làm cách nào để khắc phục sự cố hiệu suất trong PostGIS ST_Intersects?


9

Tôi là người mới trong postgis và tôi gặp vấn đề trong hiệu năng truy vấn.

Đây là truy vấn của tôi:

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

và vấn đề là đa giác của tôi bao gồm RẤT NHIỀU đa giác lớn (dài 600 trang trong tài liệu word!) và phải mất hơn 2 giờ để thực thi!

Có cách nào để tối ưu hóa truy vấn của tôi hoặc sử dụng một cách khác?

Xin sự giúp đỡ của bạn được đánh giá rất cao!

Câu trả lời:


8

Những gì bạn nên làm là đặt đa giác lớn của bạn vào một bảng dưới dạng đa giác đơn (với ST_Dump) và đặt một chỉ mục trên đó. Cái gì đó như:

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;

Đó phải là cách nhanh hơn vì nhiều lý do.


Cảm ơn Nicklas cho câu trả lời tuyệt vời này. Xin lỗi tôi đã bỏ lỡ đề cập rằng tôi có nhiều hơn một đa giác và chúng đã được lưu trữ trong một bảng có chỉ mục. Nhưng tôi nghĩ rằng việc cung cấp dữ liệu geom trực tiếp sẽ nhanh hơn. Tuy nhiên, tôi thử theo cách bạn đề xuất nhưng vẫn mất nhiều thời gian! có đề nghị nào khác không?
Sara

@Sara. Ok, vậy bạn đã thử chia multigeoemtries thành các hình học đơn lẻ như tôi đề xuất với ST_Dump?
Nicklas Avén

Chúng ta đang nói về bao nhiêu vị trí người dùng? Có bao nhiêu đa giác lớn? Bạn nhận được gì từ CHỌN ST_npoint (geom) từ big_polygons_table;?
Nicklas Avén

Xin lỗi, tôi xin giải thích thêm về các bảng của mình để làm cho bạn rõ hơn: Tôi có bảng1 bao gồm một cột geom có ​​khoảng 230 hàng và trong mỗi hàng có một đa giác (chúng đại diện cho các quốc gia để chúng có kích thước khác nhau) và có chỉ mục trong col_geom col. Bảng 2 bao gồm cột vị trí (điểm), dấu thời gian, userid và id (pk) và 3 chỉ mục được tạo bằng cách sử dụng (vị trí, dấu thời gian, userid). Bảng này rất lớn khoảng 103496003 hàng Tha số lượng ST_npoint tối đa là 1440430 và số min là 16. Tôi xin lỗi nếu tôi làm bạn bối rối nhưng tôi thực sự cần sự giúp đỡ của bạn! Cảm ơn
Sara

2

Nó phụ thuộc vào loại chất lượng - độ chính xác bạn cần. Rõ ràng bạn có thể đơn giản hóa các đa giác bằng cách sử dụng: http://postgis.net/docs/ST_Simplify.html

Những gì tôi đã làm thường xuyên trong quá trình phát triển ứng dụng GIS của mình là suy nghĩ về cách tốt nhất để giảm thiểu dữ liệu. Ví dụ. chọn trước các đa giác trong hộp ranh giới chẳng hạn. - Tùy thuộc vào zoomlevel, bạn không cần kết quả cực kỳ chính xác (st_simplify), v.v.

Hy vọng rằng đã giúp bạn một chút!


Cảm ơn Martin đã phản hồi nhanh chóng của bạn. Vấn đề của tôi là tôi cần kết quả rất chính xác vì vậy tôi nghĩ chức năng này sẽ không giúp tôi ở đây! nhưng cảm ơn vì lời đề nghị
Sara

0

Tùy thuộc vào postgres và / hoặc sql chuyên môn của bạn, bạn có một số tùy chọn:

  1. phân tích truy vấn thông qua lệnh EXPLAIN để tìm hiểu xem bạn có đang gặp một nút cổ chai cụ thể không. Cảnh báo: đôi khi đầu ra của EXPLAIN có thể khó hiểu

  2. nếu bạn mong đợi rằng hầu hết hoặc một phần đáng kể của hình học trong bảng1 KHÔNG giao nhau với đa giác, bạn có thể thử áp dụng điều kiện sơ bộ đối với đa giác đơn giản hơn (nghĩa là bằng cách phá đa giác trong các phần nhỏ hơn) và sau đó chỉ chạy giao cắt đa giác nặng hơn những kết quả đó. Xem ví dụ bên dưới.

  3. nếu và chỉ nếu CPU là nút cổ chai (ví dụ máy chủ là nút giao thông máy tính bị mắc kẹt) Tôi thẫn thờ đề nghị bạn nhận được một lớn hơn, nhanh hơn, CPU mạnh hơn hoặc thuê một lần cao CPU Instance tắt EC2 của Amazon và tiêu diệt nó khi bạn đang làm xong

Ví dụ truy vấn cho mục 2:

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

Để cải thiện hiệu suất, bạn cũng có thể tạm thời cụ thể hóa subselect st1 dưới dạng bảng để bạn có thể lập chỉ mục cho nó.

@Nicklas là đúng để chỉ ra trong các ý kiến ​​mà ví dụ cho gợi ý 2 không nên giúp đỡ. Anh ấy đúng, nhưng tôi nghĩ tôi (một phần) cũng đúng.

Trong thực tế, có vẻ như một câu hỏi tương tự đã được hỏi (và trả lời) chỉ vào tháng 11 năm ngoái trên postgis ML:

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

và hóa ra gợi ý là thực sự phá vỡ đa giác để chỉ mục có thể lọc một cách hiệu quả nhất các giao điểm sai sẽ được kích hoạt bằng cách kiểm tra ranh giới đơn giản.


đề nghị 2 không nên giúp đỡ vì đó chính xác là những gì chỉ số đang làm. Vì vậy, cấu trúc đó sẽ chỉ làm lại một lần nữa.
Nicklas Avén

@ NicklasAvén bạn nói đúng, tôi đã sửa đổi câu trả lời
unicoletti

0

Sử dụng ST_SubDivide()

Đối với phiên bản 2.2 của Postgis, bạn có thể sử dụng ST_SubDivide.

ST_Subdivide - Trả về một tập hợp hình học trong đó không có hình học nào trong tập hợp có nhiều hơn số đỉnh được chỉ định.

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

Bạn cũng có thể

  • sử dụng bảng tạm thời
  • một chỉ số

Ở đây chúng tôi sử dụng ST_SubDivideđể phá vỡ đa giác thành subpolygons với 10 đỉnh hoặc ít hơn.

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

CREATE INDEX divided_idx ON divided USING gist(geom);

Sau đó

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;

Không làm như trên, nó giới thiệu lỗi làm tròn

Điều chỉnh chung

Cũng xem phần có tiêu đề Mẹo hiệu suất trong các tài liệu. Hãy chắc chắn rằng bạn đã điều chỉnh thích hợp. Xem xét nâng cao max_parallel_workers_per_gatherđể tận dụng song song (hiện đang mặc định tắt).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.