Tăng tốc truy vấn OpenStreetMap PostGIS


12

Tôi có dữ liệu OpenStreetMap cho Hà Lan được tải vào cơ sở dữ liệu PostGIS (PostgreQuery 8.3 / PostGIS 1.3.3) bằng cách sử dụng lược đồ thẩm thấu . Điều này có nghĩa là tất cả các thẻ được lưu trữ trong một trường hstore . Ngoài chỉ số GIST mà thẩm thấu tạo ra trên trường hình học, tôi đã tạo một chỉ mục GIST bổ sung trên trường thẻ.

Cố gắng truy vấn bằng cả ràng buộc không gian và ràng buộc trên trường thẻ, tôi thấy rằng nó chậm hơn tôi muốn. Một truy vấn như thế này:

SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n 
  INNER JOIN users AS u ON n.user_id = u.id 
  WHERE tags->'man_made'='surveillance' 
  AND ST_Within(geom, ST_GeomFromText('POLYGON((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326));

mất 22 giây để trả lại 78 hồ sơ.

Có khoảng 53 triệu hồ sơ trong bảng này.

Có cách nào để tăng tốc đáng kể điều này không? Tôi đã nghe nói rằng hstore được triển khai tốt hơn đáng kể trong PostgreSQL 9, liệu có nâng cấp được không?


Vì đây có vẻ là một câu hỏi định hướng cơ sở dữ liệu, tôi khuyến khích bạn hỏi trên dba.stackexchange.com
jcolebrand

Cập nhật cho năm 2015 - PostGIS đã thực hiện các cải tiến hiệu suất đáng kể kể từ khi câu hỏi này được hỏi, vì vậy hãy xem xét điều đó cũng như nâng cấp PostgreQuery.
Toby Speight

Câu trả lời:


5

Một phương pháp sẽ là truy vấn các thẻ bạn quan tâm và đặt các bản ghi đó vào một bảng mới. Sau đó, bạn sẽ chỉ cần truy vấn bảng mới thay vì tất cả 53 triệu bản ghi. Nếu bạn đang cố gắng cập nhật cơ sở dữ liệu của mình, bạn có thể chạy truy vấn này mỗi khi bạn nhận được dữ liệu mới từ OSM.


2
Thay vì tạo một bảng mới, bạn có thể xem xét việc tạo VIEW thay vào đó, theo cách đó bạn "truy vấn" được liên kết trực tiếp với dữ liệu nguồn gốc của bạn mà không cần sao chép dữ liệu theo nghĩa đen.
RyanKDalton

7
Một khung nhìn sẽ không nhất thiết phải cải thiện hiệu năng truy vấn, trừ khi đó là một khung nhìn cụ thể hóa hoặc tương đương (xem câu hỏi SO về chủ đề này). Tôi không tin Postgresql hỗ trợ các khung nhìn cụ thể hóa trực tiếp, nhưng chúng có thể được thực hiện bằng các kích hoạt.
Giáp Adam

2
Đây là cách giải quyết tôi đang sử dụng. Sau khi cập nhật các bảng thẩm thấu, tôi tạo lại một vài bảng được tối ưu hóa cho các truy vấn mà tôi muốn chạy. Tôi chỉ cảm thấy phải có một cách tốt hơn. Chủ đề kích hoạt gây tò mò cho tôi và cách bạn có thể sử dụng chúng để thực hiện các quan điểm quan trọng. @Adam Armor, bất kỳ cơ hội nào bạn có thể chia sẻ cái nhìn sâu sắc về điều này?
mvexel

4
@mvexel Hãy xem bài viết wiki này , bao gồm những điều cơ bản về quan điểm cụ thể hóa và chi tiết cách triển khai chúng trong PostgreQuery.
Giáp Adam

5

Bạn có thể thử tạo một chỉ mục cho cột hstore của bạn,

CREATE INDEX nodes_tags_idx ON nodes USING GIST(tags)

và sau đó sử dụng ?toán tử để giới hạn truy vấn chỉ các hàng đó:

SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n 
  INNER JOIN users AS u ON n.user_id = u.id 
  WHERE tags ? 'man_made'
  AND tags->'man_made'='surveillance' 
  AND ST_Within(geom, ST_GeomFromText('POLYGON((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326));

Cảm ơn! Tôi đã tạo chỉ mục đó, chỉ có tôi không sử dụng nó. Nó chỉ tăng tốc các hoạt động nhất định. Trong PostgreQuery 8.3 (mà tôi đang sử dụng) chỉ có @> và? , trong 9.0 đó là @>,?,? & và? | .
mvexel

1
Đối với bản ghi, truy vấn sử dụng ?toán tử mất 48 giây so với 88 giây cho truy vấn của tôi (Tôi không biết làm thế nào tôi có 72 giây ngày hôm qua, có thể lần này máy đã làm gì đó phức tạp trong khi tôi thực hiện các truy vấn). Vì vậy, đây vẫn không phải là hiệu suất mà tôi đang tìm kiếm, nhưng tôi đã hiểu sâu hơn về cách các chỉ mục GIST hoạt động trên các cột của cửa hàng. Tôi vẫn sẽ phải đi với giải pháp khác là tạo ra một khung nhìn cụ thể hóa để có được hiệu suất mà tôi muốn.
mvexel

3

Các hàm st_within và _st_within không được biết đến với tốc độ của chúng. Toán tử && có thể giúp vì nó sẽ kiểm tra bbox thay vì hình học

Bạn có thể thử như sau:

SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n 
  INNER JOIN users AS u ON n.user_id = u.id 
  WHERE tags ? 'man_made'
  AND tags->'man_made'='surveillance' 
  AND geom && ST_SetSRID('BOX3D(4 52,5 53)'::box3d,4326);

Để biết thêm mẹo về hiệu suất, hãy kiểm tra: http://postgis.refraction.net/docs/ch06.html


2

Vấn đề với truy vấn của bạn là tags->'man_made'='surveillance'mệnh đề. Điều này buộc Postgres phải mở rộng các thẻ hstore và không cho phép nó sử dụng chỉ mục. Nếu bạn viết lại bằng cách sử dụng @>(chứa) nó sẽ cho phép sử dụng chỉ mục.

Vì bạn đang truy vấn một hình chữ nhật, bạn có thể sử dụng &&thay vì ST_Within. Điều này sẽ có một mức tăng nhỏ, vì ST_Within không phức tạp để đánh giá và ST_Within hoàn toàn &&kiểm tra.

Việc tăng tốc độ bổ sung sẽ là sử dụng chỉ số GIN trên các thẻ thay vì chỉ số GIST. Các chỉ mục GIN mất nhiều thời gian hơn để xây dựng nhưng nhanh hơn.

Toàn bộ truy vấn sẽ là

SELECT n.geom,n.tags,n.tstamp,u.name FROM nodes AS n INNER JOIN users AS u ON n.user_id = u.id WHERE tags @> hstore('man_made', 'surveillance') AND geom && ST_GeomFromText('POLYGON((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))',4326);

Nếu bạn biết bạn sẽ truy vấn một thẻ cụ thể rất nhiều, bạn có thể tạo một chỉ mục một phần trên đó CREATE INDEX ON nodes ( tags->'man_made' ) WHERE (tags->'man_made' IS NOT NULL);.

Điều này sẽ cho phép điều kiện WHERE tags->'man_made'='surveillance'sử dụng chỉ mục. Thật không may, chỉ mục đó không thể giúp @>truy vấn và các chỉ mục GIN hoặc GIST không thể giúp tags->'foo'truy vấn, vì vậy bạn phải khớp các truy vấn với các chỉ mục bạn có.


Lời khuyên để sử dụng tags @>hstore()ồ ạt cải thiện truy vấn của tôi, cảm ơn.
alphabetasoup

1

thay vào đó hãy thử:

CHỌN n.geom, n.tags, n.tstamp, u.name TỪ các nút AS n INNER THAM GIA người dùng NHƯ u ON , ST_GeomFromText ('POLYGON ((4.0 52.0,5.0 52.0,5.0 53.0,4.0 53.0,4.0 52.0))', 4326));

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.