Tìm kiếm giải pháp nhanh nhất cho Điểm trong phân tích Đa giác 200 triệu điểm [đã đóng]


35

Tôi có một CSV chứa 200 triệu quan sát với định dạng sau:

id,x1,y1,x2,y2,day,color
1,"-105.4652334","39.2586939","-105.4321296","39.2236632","Monday","Black"
2,"-105.3224523","39.1323299","-105.4439944","39.3352235","Tuesday","Green"
3,"-104.4233452","39.0234355","-105.4643990","39.1223435","Wednesday","Blue"

Đối với mỗi bộ tọa độ (x1 / y1 và x2 / y2), tôi muốn chỉ định Vùng điều tra dân số hoặc Khối điều tra dân số Hoa Kỳ nằm trong đó (Tôi đã tải xuống shapefile đường điều tra dân số tại đây: ftp : //ftp2.c tắc.gov / địa lý / hổ / TIGER2011 / TRACT / tl_2011_08_tract.zip ). Vì vậy, tôi cần thực hiện thao tác điểm đa giác hai lần cho mỗi lần quan sát. Điều quan trọng là các trận đấu phải rất chính xác.

Cách nhanh nhất để làm điều này, bao gồm thời gian để tìm hiểu phần mềm là gì? Tôi có quyền truy cập vào máy tính có 48GB Bộ nhớ - trong trường hợp đó có thể là một hạn chế có liên quan.

Một số chủ đề khuyên bạn nên sử dụng PostGIS hoặc Spatialite (Spatialite có vẻ dễ sử dụng hơn - nhưng nó có hiệu quả như PostGIS không?). Nếu đó là những lựa chọn tốt nhất, có bắt buộc phải đưa ra Chỉ số không gian (RTree không?)? Nếu vậy, làm thế nào để người ta làm như vậy (ví dụ: sử dụng Shapefile Tract Tract Tract)? Tôi sẽ vô cùng biết ơn về bất kỳ đề xuất nào bao gồm mã ví dụ (hoặc một con trỏ tới mã ví dụ).

Nỗ lực đầu tiên của tôi (trước khi tìm thấy trang web này) bao gồm việc sử dụng ArcGIS để thực hiện liên kết không gian (chỉ x1 / y1) mẫu phụ của dữ liệu (100.000 điểm) trên Khối điều tra dân số Hoa Kỳ. Điều đó mất hơn 5 giờ trước khi tôi giết quá trình. Tôi hy vọng một giải pháp có thể được thực hiện trên toàn bộ tập dữ liệu trong thời gian dưới 40 giờ tính toán.

Xin lỗi vì đã hỏi một câu hỏi đã được hỏi trước đây - Tôi đã đọc qua các câu trả lời và tôi không biết làm thế nào để thực hiện các khuyến nghị. Tôi chưa bao giờ sử dụng SQL, Python, C và chỉ mới sử dụng ArcGIS một lần trước đây - Tôi là người mới bắt đầu hoàn chỉnh.


3
40 giờ sẽ tương đương với gần 2800 điểm hoạt động đa giác mỗi giây. Nó chỉ không có âm thanh trong tâm trí của tôi. Tôi không biết phần mềm nào (ArcGIS, PostGIS, Spatialite, v.v.) là nhanh nhất, nhưng không nghi ngờ gì về chỉ số không gian.
Uffe Kousgaard

1
Sẽ không có vấn đề gì nếu đa giác không phức tạp. Mức tăng từ chỉ số (trong PostGIS) sẽ phụ thuộc vào mức độ đa giác lớn. Các đa giác càng nhỏ (hộp giới hạn càng nhỏ) thì các chỉ mục sẽ càng giúp ích. Có lẽ là có thể.
Nicklas Avén

1249 đa giác với ~ 600 điểm mỗi đa giác.
Uffe Kousgaard

3
@Uffe Kousgaard, vâng, điều đó là hoàn toàn có thể. Bạn làm cho tôi một thử. Se trả lời dưới đây.
Nicklas Avén

Kudos cho tăng đến thách thức! Trong một số bài kiểm tra băng ghế dự bị, SpatialLite thực sự hoạt động nhanh hơn PostGIS, nhưng bạn phải cẩn thận với cách bạn thiết lập RTrees. Tôi cũng thường thấy ArcGIS chậm hơn khi chạy từ 'bên trong' nhưng nhanh hơn khi chạy với mô-đun ArcPy 'độc lập' bên ngoài '.
MappaGnosis

Câu trả lời:


27

ST_DWithin đã nhanh hơn trong thử nghiệm của tôi so với ST_Intersects. Đó là điều đáng ngạc nhiên, đặc biệt là vì thuật toán hình học đã chuẩn bị được cho là sẽ khởi động trong những trường hợp như thế này. Tôi nghĩ có khả năng điều này sẽ nhanh hơn khá nhiều so với những gì tôi thể hiện ở đây.


Tôi đã làm thêm một số bài kiểm tra và hai điều gần gấp đôi tốc độ. Đầu tiên, tôi đã thử trên một máy tính mới hơn, nhưng vẫn là một máy tính xách tay khá bình thường, có thể ngoại trừ từ ssd -disks của SATA3.

Sau đó, truy vấn dưới đây mất 18 giây thay vì 62 giây trên máy tính xách tay cũ. Tiếp theo tôi thấy rằng tôi đã hoàn toàn sai trước đây khi tôi viết rằng chỉ số trên bảng điểm là không cần thiết. Với chỉ số đó, ST_Intersects hoạt động như mong đợi và mọi thứ trở nên rất nhanh. Tôi đã tăng số điểm trong bảng điểm lên 1 triệu điểm và truy vấn:

CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id 
FROM imported_ct , t WHERE ST_Intersects(imported_ct.geom , t.geom);

chạy trong 72 giây. Vì có 1249 đa giác, 1249000000 thử nghiệm được thực hiện trong 72 giây. Điều đó làm cho khoảng 17000000 bài kiểm tra mỗi giây. Hoặc kiểm tra gần 14000 điểm so với tất cả các đa giác mỗi giây.

Từ bài kiểm tra này, 400000000 điểm của bạn để kiểm tra sẽ mất khoảng 8 giờ mà không gặp bất kỳ rắc rối nào với việc phân phối tải cho một số lõi. PostGIS không bao giờ dừng lại để gây ấn tượng với tôi :-)


Trước tiên, để trực quan hóa kết quả, bạn có thể thêm hình dạng điểm vào bảng kết quả, ví dụ mở nó trong QGIS và định kiểu nó với các giá trị duy nhất trên trường import_ct.

Thứ hai, vâng, bạn cũng có thể nhận được các điểm nằm ngoài bất kỳ đa giác nào bằng cách sử dụng nối phải (hoặc trái) như thế này:

CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id 
FROM imported_ct right join t ON ST_Intersects(imported_ct.the_geom , t.geom);

Tôi đã thực hiện một số thử nghiệm để xác minh xem có vẻ như PostGIS có thể.

Điều đầu tiên tôi không hiểu. Bạn có hai điểm mỗi hàng. Luôn luôn là cả hai điểm trong cùng một đa giác? Sau đó, nó là đủ để làm các tính toán trên một trong những điểm. Nếu chúng có thể ở hai đa giác khác nhau, bạn sẽ cần một cách để kết nối một hàng điểm với hai đa giác.

Từ các thử nghiệm có vẻ như có thể thực hiện được, nhưng bạn có thể cần một số giải pháp sáng tạo để phân tán tải trên nhiều lõi.

Tôi đã thử nghiệm trên một máy tính xách tay 4 năm tuổi với cpu lõi kép (khoảng 2,2 GHz tôi nghĩ), RAM 2 GB. Nếu bạn có 48 BG RAM, tôi đoán bạn cũng có nhiều năng lượng cpu hơn.

Những gì tôi đã làm là tạo một bảng điểm ngẫu nhiên với 100000 điểm như thế này:

CREATE TABLE t AS
WITH r AS
(SELECT ST_Extent(the_geom)::geometry ext FROM imported_ct)
SELECT ST_Point(x,y) AS geom FROM 
(SELECT GENERATE_SERIES(1,100000)) s,
(SELECT ST_Xmin(ext)+(random()*(ST_Xmax(ext)-ST_Xmin(ext))) x, ST_Ymin(ext)+(random()*(ST_Ymax(ext)-ST_Ymin(ext))) y FROM r
) f;

Sau đó thêm một gid như:

ALTER TABLE t ADD COLUMN GID SERIAL;

Sau đó chạy:

CREATE TABLE points_ct AS
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE ST_Dwithin(imported_ct.the_geom , t.geom,0);

mất khoảng 62 giây (so với kết quả ArcGIS của bạn với cùng số điểm). Kết quả là một bảng kết nối các điểm trong bảng t của tôi với gid trong bảng với đường điều tra dân số.

Với tốc độ đó, bạn sẽ làm được 200 điểm trong khoảng 34 giờ. Vì vậy, nếu nó là đủ với việc kiểm tra một trong những điểm, máy tính xách tay cũ của tôi có thể làm điều đó với một lõi.

Nhưng nếu bạn cần kiểm tra cả hai điểm thì có thể khó hơn.

Vì vậy, bạn có thể phân phối tải theo cách thủ công đến nhiều lõi bằng cách bắt đầu nhiều phiên dựa trên db và chạy các truy vấn khác nhau.

Trong ví dụ của tôi với 50000 điểm và hai lõi cpu tôi đã thử:

CREATE TABLE t1 as
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE t.gid >50000 and  ST_Dwithin(imported_ct.the_geom , t.geom,0);

trên một phiên db cùng lúc với khi chạy:

CREATE TABLE t2 as
SELECT imported_ct.gid as ct_gid, t.gid as point_id FROM imported_ct , t WHERE t.gid <=50000 and  ST_Dwithin(imported_ct.the_geom , t.geom,0);

trên một phiên db khác.

Điều đó mất khoảng 36 giây nên chậm hơn một chút so với ví dụ đầu tiên có lẽ phụ thuộc vào việc ghi đĩa cùng một lúc. Nhưng vì các lõi của bith đang hoạt động cùng một lúc nên tôi không mất hơn 36 giây.

Để liên minh bảng t1 và t2 a đã thử:

CREATE TABLE t3 AS 
SELECT * FROM t1
UNION ALL
SELECT * FROM t2;

sử dụng khoảng nửa giây.

Vì vậy, với phần cứng mới hơn và phân phối tải trên nhiều lõi, điều này hoàn toàn có thể xảy ra ngay cả khi thế giới thực sẽ chậm hơn trường hợp thử nghiệm.

Có thể đáng chú ý rằng ví dụ này là từ Linux (Ubuntu). Sử dụng Windows sẽ là một câu chuyện khác. Nhưng tôi có tất cả các ứng dụng hàng ngày khác đang chạy nên máy tính xách tay được tải khá nhiều từ trước đó. Vì vậy, điều đó có thể mô phỏng trường hợp cửa sổ khá tốt, có thể, không mở bất cứ thứ gì ngoại trừ pgadmin.


1
Tôi vừa đổi tên .tl_2011_08_trac thành import_ct vì nó dễ viết hơn. Vì vậy, chỉ cần thay đổi import_ct trong truy vấn của tôi thành .tl_2011_08_trac và bạn sẽ ổn.
Nicklas Avén

2
@meer BTW, không nên sử dụng template_postgis_20 như bất kỳ thứ gì khác ngoài mẫu cho cơ sở dữ liệu trong tương lai. Vì dường như bạn có PostGIS 2.0, nếu bạn cũng có PostgreQuery 9.1, bạn có thể chỉ cần tạo một db mới và chạy "CREATE EXTENSION POSTGIS;"
Nicklas Avén

1
Vâng, đó là một lỗi đánh máy mà tôi nghĩ rằng tôi đã sửa một vài phút trước đây. Xin lỗi vì điều đó. Ngoài ra, hãy thử phiên bản ST_Intersects, điều đó sẽ nhanh hơn khá nhiều.
Nicklas Avén

1
@meer Lý do không phải mọi điểm đều bị ảnh hưởng là các điểm ngẫu nhiên được đặt trong một hình chữ nhật và tôi đoán bản đồ không chính xác là một hình chữ nhật. Tôi sẽ thực hiện một chỉnh sửa trong bài để hiển thị cách xem kết quả.
Nicklas Avén

1
@Uffe Kousgaard, Vâng, tôi đoán bạn có thể đặt nó theo cách đó. Nó mất một đa giác tại một thời điểm và chuẩn bị nó bằng cách xây dựng một cây các cạnh. Sau đó, nó kiểm tra tất cả các điểm (rằng chỉ mục đã được sắp xếp là xâm nhập bằng cách đặt các hộp chồng lên nhau) đối với đa giác đã chuẩn bị đó.
Nicklas Avén

4

Có lẽ cách dễ nhất là với PostGIS. Có một số hướng dẫn trên internet về cách nhập dữ liệu điểm csv / txt vào PostGIS. Liên kết1

Tôi không chắc chắn về hiệu suất của các tìm kiếm điểm trong đa giác trong PostGIS; nó phải nhanh hơn ArcGIS. Chỉ số không gian GIST mà PostGIS sử dụng là khá nhanh. link2 Link3

Bạn cũng có thể kiểm tra chỉ số không gian địa lý MongoDB . Nhưng điều này đòi hỏi ít thời gian hơn để bắt đầu. Tôi tin rằng MongoDB có thể rất nhanh. Tôi chưa thử nghiệm nó với các tìm kiếm đa giác điểm nên không thể chắc chắn.

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.