เร่งความเร็วการสืบค้น OpenStreetMap PostGIS


12

ผมมีข้อมูล OpenStreetMap เนเธอร์แลนด์โหลดลงในฐานข้อมูล PostGIS (PostgreSQL 8.3 / PostGIS 1.3.3) โดยใช้สคีออสโมซิ ซึ่งหมายความว่าแท็กทั้งหมดจะถูกเก็บไว้ในฟิลด์hstore นอกจากดัชนี GIST ที่ออสโมซิสสร้างขึ้นในฟิลด์เรขาคณิตฉันได้สร้างดัชนี GIST เพิ่มเติมในฟิลด์แท็ก

พยายามค้นหาโดยใช้ทั้งข้อ จำกัด เชิงพื้นที่และข้อ จำกัด ในฟิลด์แท็กฉันพบว่าช้ากว่าที่ฉันต้องการ แบบสอบถามแบบนี้:

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));

ใช้เวลา 22 วินาทีในการส่งคืน 78 บันทึก

มีประมาณ 53 ล้านบันทึกในตารางนี้

มีวิธีเร่งความเร็วนี้อย่างมีนัยสำคัญหรือไม่? ฉันได้ยินมาว่า hstore นั้นใช้งานได้ดีกว่าอย่างมากใน PostgreSQL 9 จะอัพเกรดความช่วยเหลือหรือไม่


เนื่องจากนี่เป็นคำถามเชิงฐานข้อมูลฉันขอแนะนำให้คุณสอบถามกับdba.stackexchange.com
jcolebrand

อัปเดตสำหรับปี 2558 - PostGIS ได้ทำการปรับปรุงประสิทธิภาพอย่างมีนัยสำคัญตั้งแต่มีการถามคำถามนี้ดังนั้นให้พิจารณาว่าเป็นการอัพเกรด PostgreSQL
Toby Speight

คำตอบ:


5

วิธีหนึ่งคือการค้นหาแท็กที่คุณสนใจและวางระเบียนเหล่านั้นในตารางใหม่ จากนั้นคุณจะต้องสืบค้นตารางใหม่แทนการบันทึก 53 ล้านรายการ หากคุณพยายามปรับปรุงฐานข้อมูลของคุณอยู่คุณสามารถให้คิวรีนี้รันทุกครั้งที่คุณได้รับข้อมูลใหม่จาก OSM


2
แทนที่จะสร้างตารางใหม่คุณอาจพิจารณาสร้างมุมมองแทนวิธีที่คุณ "ค้นหา" นั้นเชื่อมโยงอยู่กับแหล่งข้อมูลดั้งเดิมของคุณโดยไม่ต้องทำซ้ำข้อมูลตามตัวอักษร
RyanKDalton

7
มุมมองไม่จำเป็นต้องปรับปรุงประสิทธิภาพการค้นหายกเว้นว่าเป็นมุมมองที่ปรากฏหรือเทียบเท่า (ดูคำถาม SOในหัวข้อนี้) ฉันไม่เชื่อว่า Postgresql สนับสนุนมุมมองที่เป็นรูปธรรมโดยตรง แต่สามารถนำไปใช้งานได้โดยใช้ทริกเกอร์
อาดัมเกราะ

2
นี่เป็นวิธีแก้ปัญหาที่ฉันใช้อยู่ในปัจจุบัน หลังจากอัปเดตเป็นตาราง osmosis ฉันจะสร้างตารางขึ้นอีกสองสามตารางที่ปรับให้เหมาะกับคิวรีที่ฉันต้องการเรียกใช้ ฉันแค่รู้สึกว่าต้องมีวิธีที่ดีกว่า หัวข้อของการกระตุ้นให้เกิดความสนใจฉันและวิธีที่คุณสามารถใช้พวกเขาเพื่อใช้มุมมองเนื้อหา @Adam Armour โอกาสใดที่คุณสามารถแบ่งปันข้อมูลเชิงลึกเกี่ยวกับเรื่องนี้?
mvexel

4
@mvexel ดูที่บทความ wiki นี้ซึ่งครอบคลุมพื้นฐานของมุมมองที่เป็นรูปธรรมและรายละเอียดวิธีนำไปใช้ใน PostgreSQL
อดัมเกราะ

5

คุณสามารถลองสร้างดัชนีสำหรับคอลัมน์ hstore ของคุณ

CREATE INDEX nodes_tags_idx ON nodes USING GIST(tags)

จากนั้นใช้?โอเปอเรเตอร์เพื่อ จำกัด การสืบค้นเฉพาะแถวนั้น:

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));

ขอบคุณ! ฉันสร้างดัชนีนั้นแล้ว แต่ฉันไม่ได้ใช้ มันเร็วขึ้นการดำเนินงานบางอย่างเท่านั้น ใน PostgreSQL 8.3 (ที่ฉันใช้) เป็นเพียง@> และ? ใน 9.0 เป็น@>,?,? & และ? | .
mvexel

1
สำหรับการบันทึกแบบสอบถามที่ใช้?โอเปอเรเตอร์ใช้เวลา 48 วินาทีเมื่อเทียบกับ 88 วินาทีสำหรับการสืบค้นของฉัน (ฉันไม่รู้ว่าฉันได้ 72 วินาทีเมื่อวานนี้บางทีเครื่องกำลังทำอะไรซับซ้อนในขณะนี้ในขณะที่ฉันทำแบบสอบถาม) ดังนั้นยังไม่ได้แสดงที่ฉันกำลังมองหา แต่ฉันได้รับความเข้าใจที่ลึกซึ้งยิ่งขึ้นว่าดัชนี GIST ทำงานอย่างไรในคอลัมน์ hstore ฉันจะยังคงต้องไปกับโซลูชันอื่นของการสร้างมุมมอง materialized เพื่อให้ได้ประสิทธิภาพที่ฉันต้องการ
mvexel

3

ฟังก์ชัน st_within และ _st_within ไม่เป็นที่รู้จักสำหรับความเร็ว ผู้ประกอบการ && อาจช่วยได้เพราะจะทำเครื่องหมายเช็คบ็อกซ์แทนเรขาคณิต

คุณอาจลองทำสิ่งต่อไปนี้:

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);

สำหรับเคล็ดลับประสิทธิภาพเพิ่มเติมให้ตรวจสอบที่: http://postgis.refractions.net/docs/ch06.html


2

ปัญหาเกี่ยวกับการค้นหาของคุณคือtags->'man_made'='surveillance'ข้อ สิ่งนี้บังคับให้ Postgres ขยาย hstore ของแท็กและไม่อนุญาตให้ใช้ดัชนี หากคุณเขียนใหม่โดยใช้@>(มี) มันจะอนุญาตให้ใช้ดัชนี

เนื่องจากคุณกำลังสอบถามสี่เหลี่ยมคุณสามารถใช้&&แทน ST_ ภายในได้ นี่จะมีกำไรเล็กน้อยเนื่องจาก ST_ ภายในนั้นไม่ซับซ้อนในการประเมินและ ST_ ภายในนั้นจะทำการ&&ตรวจสอบโดยปริยาย

การเพิ่มความเร็วเพิ่มเติมคือการใช้ดัชนี GIN บนแท็กแทนดัชนี GIST ดัชนี GIN ใช้เวลาในการสร้างนานกว่า แต่เร็วกว่า

แบบสอบถามทั้งหมดจะเป็น

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);

CREATE INDEX ON nodes ( tags->'man_made' ) WHERE (tags->'man_made' IS NOT NULL);ถ้าคุณรู้ว่าคุณกำลังจะได้รับการสอบถามแท็กโดยเฉพาะอย่างยิ่งจำนวนมากที่คุณสามารถสร้างดัชนีบางส่วนเกี่ยวกับมันด้วย

สิ่งนี้จะทำให้เงื่อนไข WHERE tags->'man_made'='surveillance'ใช้ดัชนี น่าเสียดายที่ดัชนีนั้นไม่สามารถช่วย@>สืบค้นได้และดัชนี GIN หรือ GIST ไม่สามารถช่วยtags->'foo'สืบค้นได้ดังนั้นคุณต้องจับคู่แบบสอบถามกับดัชนีที่คุณมี


คำแนะนำในการใช้การtags @>hstore()ปรับปรุงแบบสอบถามของฉันอย่างหนาแน่นขอบคุณ
alphabetasoup

1

ลองทำสิ่งนี้แทน:

เลือก n.geom, n.tags, n.tstamp, u.name จากโหนดเป็น n ผู้ใช้ภายในเข้าร่วมเมื่อคุณอยู่ใน n.user_id = u.id WHERE tags @> 'man_made => surveillance' :: hstore และ 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));

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.