ฉันจะเพิ่มประสิทธิภาพ pgrouting เพื่อความเร็วได้อย่างไร


22

ฉันใช้ pgrouting ในฐานข้อมูล postgis ที่สร้างผ่าน osm2pgrouting มันทำงานได้ดีมากในชุดข้อมูลที่มีข้อ จำกัด (วิธี 3.5k เส้นทางที่สั้นที่สุดทั้งหมด A * ค้นหา <20 ms)

อย่างไรก็ตามเนื่องจากฉันได้นำเข้ากล่องขนาดใหญ่กว่า (122k วิธี) จาก europe.osm ประสิทธิภาพการทำงานก็ลดลงมาก (เส้นทางที่สั้นที่สุดมีค่าใช้จ่ายประมาณ 900ms)

ฉันคิดว่าการใช้ A * ส่วนใหญ่ของขอบเหล่านั้นจะไม่เคยถูกเยี่ยมชมเนื่องจากอยู่นอกเส้นทาง

สิ่งที่ฉันได้ทำไปแล้วเพื่อพยายามปรับปรุงความเร็ว:

  • วางดัชนีลงในคอลัมน์รูปทรงเรขาคณิต (ไม่มีเอฟเฟกต์ที่เห็นได้ชัดเจน)
  • เพิ่มหน่วยความจำของฉันจาก 8GB เป็น 16GB
  • เปลี่ยนการตั้งค่าหน่วยความจำ postgresql (shared_buffers, effective_cache_size) จาก (128MB, 128MB) เป็น (1GB, 2GB) (ไม่มีผลที่เห็นได้ชัดเจน)

ฉันมีความรู้สึกว่างานส่วนใหญ่กำลังทำอยู่ในห้องสมุด C Boost ที่ซึ่งกราฟกำลังทำอยู่ดังนั้นการปรับ postgresql ให้เหมาะสมจะไม่ให้ผลลัพธ์ที่ดีกว่า เนื่องจากฉันทำการเปลี่ยนแปลงเล็กน้อยในชุดของแถวที่ฉันเลือกสำหรับ A * สำหรับการค้นหาทุกครั้งฉันกลัวว่าห้องสมุดเพิ่มไม่สามารถแคชกราฟของฉันและต้องสร้างขอบ 122k ทั้งหมดทุกครั้ง (แม้ว่าจะใช้เพียง เซตย่อย จำกัด ทุกคำค้นหา) และฉันก็ไม่รู้เลยว่าจะใช้เวลาเท่าไหร่เมื่อเทียบกับการค้นหาเส้นทางที่สั้นที่สุด

คุณใช้ pgrouting ในชุดข้อมูล OSM 122k หรือมากกว่าหรือไม่ ฉันควรคาดหวังประสิทธิภาพอะไร การตั้งค่าใดที่ส่งผลต่อประสิทธิภาพมากที่สุด


2
ฉันไม่ใช่ผู้เชี่ยวชาญที่เริ่มต้น แต่คุณสามารถแคชผลลัพธ์ได้หรือไม่ถ้าคุณรู้ว่ามีการใช้เส้นทางย่อยทั่วไปอยู่เสมอคุณสามารถล้างมันได้หรือไม่ ดังนั้นคุณต้องค้นหาน้อยลงหรือไม่ นอกจากนี้คุณ จำกัด การค้นหาเฉพาะ Arterials และ collectors หรือไม่
dassouki

1
ฉันอนุญาตให้ค้นหาฟรี atm ดังนั้นฉันไม่คิดว่าฉันจะคิดอะไรมากมายสำหรับเส้นทางย่อย นอกจากนี้ฉันกำลังแคชผลการค้นหาของ x นาทีสุดท้าย แต่ไม่ได้ช่วยฉันในการค้นหาใหม่ ฉันมีความรู้สึกว่า A * ในขนาดนี้ยังคงเร็วมากตราบใดที่ฉันสามารถคงกราฟไว้ในหน่วยความจำ ต้องมีคนที่กำหนดเส้นทางด้วยวิธีนี้กับคนทั้งประเทศที่รู้วิธีปรับปรุงประสิทธิภาพ
mrg

1
อีกทางเลือกหนึ่งคือการสร้างเมทริกซ์ O / D (เมทริกซ์ต้นทาง / ปลายทาง) นี่เป็นเทคนิคที่เราใช้ในวิศวกรรมจราจร แบ่งเครือข่ายออกเป็นโซนดังนั้นสมมติว่าเมืองใหญ่มี 100 โซน แต่ละโซนจะมี centroid จำลอง เชื่อมต่อเซนทรอยด์กับเครือข่ายของคุณผ่านลิงค์จำลอง จากนั้นคุณสามารถสร้างเครือข่ายทั้งหมดของคุณใหม่เป็น 100 x 100 ครั้ง (ทั้งหมด 10,000 ครั้ง) เมื่อผู้ใช้ทำการค้นหาการเริ่มต้นต้องค้นหาเส้นทางที่ปิดไปยังเซนทรอยด์หรือลิงค์จำลองที่ด้านต้นทางและปลายทาง
dassouki

2
คุณไม่ได้ผลลัพธ์แปลก ๆ ถ้าใครบางคนต้องการที่จะเปลี่ยนจาก 1 โซนไปยังโซนถัดไป แต่พวกมันจะถูกส่งผ่านเซนทรอยด์? หรือคุณใช้สิ่งนี้เฉพาะเมื่อโซนนั้นอยู่ห่างไกลกันมากขึ้น? โซลูชันของคุณเหมาะสมที่สุดหากลูกค้าต้องการให้เร็วที่สุดจาก A ถึง B แต่ในกรณีของฉันฉันต้องจัดการกับลูกค้าที่ต้องการเดินปั่นจักรยาน ฯลฯ เพื่อการพักผ่อนและต้องการเลือกเส้นทางที่ไม่ซ้ำและไม่ถูกบังคับให้ไป ผ่านเส้นทางมาตรฐาน
mrg

3
หากคุณกำลังมองหาวิธีแก้ปัญหาต่อเนื่องหลายรูปแบบ (จักรยาน, เดิน, การขนส่งสาธารณะ, ขับรถ) คุณควรจะดูที่พอร์ตแลนด์ TriMet หลายเส้นทางของ TriMet ซึ่งใช้ OpenTripPlanner: trimet.org/news/releases/oct15-rtp htm
RyanDalton

คำตอบ:


10

เมื่อเผชิญกับงานเช่นนี้เป้าหมายหลักของคุณคือการมีเหตุผล อย่าเปลี่ยนพารามิเตอร์ตาม 'ความรู้สึกของลำไส้' ในขณะที่ลำไส้ดูเหมือนว่าจะใช้ได้กับฮอลลีวูด แต่ก็ไม่เหมาะกับเราที่อาศัยอยู่ในโลกแห่งความจริง อย่างน้อยก็ไม่ได้อุทรของฉัน ;-)

คุณควร:

  1. สร้างเมตริกที่สามารถใช้งานได้และทำซ้ำได้ (เช่นเวลาที่ต้องการโดยเคียวรี pgrouting)

  2. บันทึกผลการวัดในสเปรดชีตและหาค่าเฉลี่ย (ทิ้งให้ดีที่สุดและแย่ที่สุด) สิ่งนี้จะบอกคุณว่าการเปลี่ยนแปลงที่คุณทำนั้นกำลังดำเนินไปในทิศทางที่ถูกต้องหรือไม่

  3. ตรวจสอบเซิร์ฟเวอร์ของคุณโดยใช้ top และ vmstat (สมมติว่าคุณใช้ * nix) ในขณะที่การสืบค้นกำลังทำงานและมองหารูปแบบที่สำคัญ: io จำนวนมาก, cpu สูง, การแลกเปลี่ยน, ฯลฯ หาก cpu กำลังรอ i / o ให้ลองปรับปรุง ประสิทธิภาพของดิสก์ (ควรจะง่ายดูด้านล่าง) หากซีพียูอยู่ที่ 100% โดยไม่มีดิสก์ที่สำคัญคุณต้องหาวิธีในการปรับปรุงคิวรี (ซึ่งอาจเป็นไปได้ยากขึ้น)

เพื่อความเรียบง่ายฉันถือว่าเครือข่ายไม่ได้มีบทบาทสำคัญที่นี่

การปรับปรุงประสิทธิภาพของฐานข้อมูล

อัปเกรดเป็นเวอร์ชัน Postgres ล่าสุด เวอร์ชัน 9 นั้นดีกว่ารุ่นก่อน ๆ มาก เป็นฟรีดังนั้นคุณไม่มีเหตุผลไม่ได้

อ่านหนังสือที่ผมแนะนำแล้วที่นี่

คุณควรอ่านมันจริงๆ ฉันเชื่อว่าบทที่เกี่ยวข้องสำหรับกรณีนี้คือ 5,6,10,11

ปรับปรุงประสิทธิภาพของดิสก์

  1. รับไดรฟ์ SSD และใส่ฐานข้อมูลทั้งหมดลงไป ประสิทธิภาพการอ่านจะเป็นสี่เท่าที่เป็นไปได้มากที่สุดและประสิทธิภาพการเขียนก็ควรปรับปรุงอย่างรุนแรง

  2. กำหนดหน่วยความจำเพิ่มเติมเพื่อ postgres เป็นการดีที่คุณควรจะสามารถกำหนดหน่วยความจำให้เพียงพอเพื่อให้สามารถแคชทั้งหมด (หรือส่วนที่ร้อนที่สุด) ลงในหน่วยความจำ แต่ไม่มากเกินไปเพื่อให้การแลกเปลี่ยนเกิดขึ้น การแลกเปลี่ยนไม่ดีมาก สิ่งนี้ครอบคลุมในหนังสือที่อ้างถึงในย่อหน้าก่อนหน้า

  3. ปิดการใช้งาน atime บนดิสก์ทั้งหมด (เพิ่มตัวเลือกnoatimeเพื่อ fstab)

การปรับปรุงความสามารถในการสืบค้น

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

ปรับปรุง

หลังจากความคิดเห็นที่ฉันได้ดูซอร์สโค้ดสำหรับขั้นตอนการจัดเก็บ

https://github.com/pgRouting/pgrouting/blob/master/core/src/astar.c

และดูเหมือนว่าเมื่อแบบสอบถามได้รับการปรับจะมีที่ว่างไม่มากสำหรับการปรับปรุงเนื่องจากอัลกอริทึมทำงานอย่างสมบูรณ์ในหน่วยความจำ (และน่าเสียดายที่มีเพียงซีพียูตัวเดียว) ฉันกลัวทางออกเดียวของคุณคือค้นหาอัลกอริทึมที่ดีกว่า / เร็วกว่าหรือที่สามารถรันมัลติเธรดและรวมเข้ากับ postgres ด้วยการสร้างไลบรารี่เช่น pgrouting หรือใช้มิดเดิลแวร์เพื่อดึงข้อมูล (และแคชบางที) ป้อนไปยังอัลกอริทึม

HTH


ฉันได้อ่านบางส่วนของหนังสือที่คุณแนะนำ ชุดข้อมูลของฉันยังเล็กพอที่จะใส่ลงในหน่วยความจำทั้งหมดดังนั้นฉันคิดว่าประสิทธิภาพของดิสก์ไม่ควรเป็นปัญหาคอขวด (ฉันจะตรวจสอบทรัพยากรของฉันเมื่อทำการทดสอบเพื่อยืนยันสิ่งนี้) ฉันคิดว่า Postgresql จะเข้ามาเล่นในกระบวนการ pgrouting เมื่อมันเลือก * ง่ายๆจากตารางเพื่อป้อนไลบรารี C Boost ด้วยแถว / tuples เพื่อทำการค้นหาจริง ((มีคนยืนยันได้) ดังนั้นฉันจึงกลัวว่าจะไม่มี ได้มากใน Postgresql ตัวเองคำตอบของคุณดูเหมือนดีมากสำหรับประสิทธิภาพ Postgresql แต่อาจจะไม่ดีสำหรับการปรับประสิทธิภาพการทำงานที่เฉพาะเจาะจง
mrg

@ mrg ฉันคิดอย่างนั้นจริง ๆ แต่ฉันต้องการให้แน่ใจว่าคุณไม่ได้ออกผลไม้แขวนลอยต่ำ เมื่อคิดถึงมันคุณก็เปลี่ยนจาก 20ms เป็น 3.5k ถึง 900ms สำหรับ 122k ซึ่งก็คือ imho ไม่เลวเลย ขอให้โชคดี
unicoletti

โซลิดสเตตไดรฟ์เพิ่มประสิทธิภาพ (ความเร็วใกล้เคียงกับแคชอะไร)
Mapperz

จากประสบการณ์ของฉันถ้าใช้ pgrouting ในชุดข้อมูลทั้งหมด (ตาราง) แล้วไม่มีประโยชน์มากจากเครื่องยนต์ Postgres ดัชนีไม่ได้ใช้ดังนั้นไร้ประโยชน์ ในทุกตารางแบบสอบถามทั้งหมดจะถูกโหลดเข้าสู่หน่วยความจำ บัฟเฟอร์และแคชที่ใช้ร่วมกันไม่ได้ให้ประโยชน์ด้านประสิทธิภาพใด ๆ เพราะทุกแบบสอบถามโหลดตารางทั้งหมดลงในหน่วยความจำ หากใครประสบความสำเร็จในการนำข้อมูลที่โหลดมาใช้ซ้ำในหน่วยความจำสำหรับการสืบค้นครั้งต่อไปโปรดบอกเรา มีเพียงการเพิ่มประสิทธิภาพที่เป็นไปได้ที่ฉันเห็นในไดรฟ์ SDD แต่ฉันไม่เคยทดสอบเลย หน่วยความจำเพิ่มเติมอนุญาตเฉพาะแบบสอบถามที่เกิดขึ้นพร้อมกันเท่านั้นไม่ใช่ประสิทธิภาพ
Mario Miler

8

ฉันมีปัญหาเดียวกันและกำลังจะถามรายชื่ออีเมลดังนั้นขอบคุณทุกคน!

ฉันใช้Shooting Starมีหนึ่งล้านครึ่งแถวบนตารางเส้นทาง ใช้เวลาเกือบสิบวินาทีในการคำนวณ ด้วยแถว 20k ใช้เวลาเกือบสามวินาที ฉันต้องการ Shooting Star เพราะฉันต้องการข้อ จำกัด ในการเลี้ยว

นี่คือแนวคิดบางอย่างที่ฉันพยายามนำไปใช้:

  • บน SQL ที่ pgRouting หาวิธีใช้ st_bufferดังนั้นจึงไม่ได้รับทุกวิธี แต่เป็นวิธี "ใกล้เคียง":

    select * from shortest_path_shooting_star ('SELECT rout. * จากรูทการกำหนดเส้นทาง, (เลือก st_buffer (st_envelope (st_collect (เรขาคณิต)), 4)) เป็นเรขาคณิตจากการกำหนดเส้นทางโดยที่ id =' || source_ || 'หรือ id =' || เป้าหมาย | | ') e WHERE rout.geometry && e.geometry' แหล่งที่มาเป้าหมายจริงจริง);

มันปรับปรุงประสิทธิภาพ แต่ถ้าวิธีที่ต้องการออกไปข้างนอกบัฟเฟอร์มันสามารถส่งคืนข้อผิดพลาด "ไม่พบเส้นทาง" ดังนั้น ... บัฟเฟอร์ขนาดใหญ่? การเรียกหลายครั้งเพิ่มบัฟเฟอร์จนกว่าจะพบวิธี?

  • แคชเส้นทางเร็ว

เช่นเดียวกับ dassouki ที่แนะนำฉันจะแคชเส้นทาง "ที่มีประโยชน์" บางเส้นทางดังนั้นหากระยะทางยาวเกินไปก็สามารถผ่านเส้นทางที่รวดเร็วเหล่านี้ได้และต้องค้นหาวิธีเข้าและออกจากเส้นทางเหล่านั้น

  • ตารางพาร์ทิชันตามดัชนี GIS

แต่ฉันคิดว่าถ้ามันไปถึงความทรงจำมันไม่สำคัญหรอก ... ควรทดสอบด้วยล่ะ

กรุณาโพสต์ต่อไปหากคุณพบแนวคิดอื่น

นอกจากนี้คุณรู้หรือไม่ว่ามี pgRouting สำหรับ Postgres9 ที่รวบรวมไว้บ้างไหม?


+1 ดูเหมือนว่ามีความคิดที่เป็นประโยชน์และสร้างสรรค์ที่นี่ โปรดทราบว่าหากคุณต้องการที่จะตอบคำถามของคุณคุณควรกำหนดเป็นคำถามใหม่ คำถามที่พบบ่อยของเราจะบอกวิธีดำเนินการต่อไป
whuber

Délawenฉันยังคิดถึงความคิดแรกของคุณ (ST_Buffer) และคาดการณ์ปัญหาเดียวกันนี้ ข้อได้เปรียบอาจเป็น 2 ทาง: ชุดข้อมูลมีขนาดเล็กลงและเร็วขึ้นและเนื่องจากการประมวลผลจำนวนมากถูกดำเนินการใน Postgresql คุณมีวิธีอีกครั้งในการปรับให้เหมาะสม Atm ฉันใช้ Ubuntu 11 ที่ postgresql 8.4 เป็นรุ่นล่าสุด
mrg

mrg ฉันรวบรวม pgRouting บน Ubuntu ไม่ฝักใฝ่ฝ่ายใดสำหรับ PostgreSQL 9.0 โดยไม่มีปัญหามาก Postgis สำหรับ PostgreSQL 9.0 สามารถพบได้ที่นี่: ppa.launchpad.net/pi-deb/gis/ubuntu maverick / main amd64 แพ็คเกจ
Délawen

ฉันคิด 2 แนวคิด 1) การรวมกันของ 'เส้นทางที่รวดเร็วแคช' และ 'st_buffer' ด้วยวิธีนี้คุณรับประกันได้ว่าการค้นหาเส้นทางและผู้คนจะไม่ถูกบังคับในเส้นทางเดียวกัน 2) ใช้ postgis เพื่อเติมกราฟแบบคงที่เท่านั้น (ด้วย Boost (C), nx_spatial (Python), neo4j (Java), etc) และนำกราฟนั้นกลับมาใช้ใหม่สำหรับการค้นหาทุกครั้ง
mrg

สิ่งที่เกี่ยวกับการลดค่าใช้จ่าย (เช่นการเพิ่มการตั้งค่า) สำหรับขอบ 'เร็ว' เช่นทางหลวงเมื่อระยะห่างระหว่างจุดเริ่มต้นและจุดสิ้นสุดใหญ่กว่าขีด จำกัด ? ปัจจัยเร่งยังสามารถเกี่ยวข้องกับระยะทาง: ใหญ่กว่าสำหรับระยะทางยาว
unicoletti

5

เราเพิ่งสร้างสาขาในคอมไพล์สำหรับเส้นทางที่สั้นที่สุดที่ จำกัด การเลี้ยว @ https://github.com/pgRouting/pgrouting/tree/trsp

ขออภัยยังไม่มีเอกสาร แต่ถ้าคุณถามคำถามในรายการ pgRouting ฉันออกไปเที่ยวที่นั่นและจะตอบกลับ รหัสนี้ทำงานเร็วกว่าดาวตกมากและขึ้นอยู่กับอัลกอริทึม Dijkstra

สตีฟ


0

ฉันมีตารางเส้นทางต้นทางที่มีขอบ ~ 1200000 ใน i7 ของฉันกับ SSD ใช้เวลา 12 วินาทีในการสร้างเส้นทาง ความคิดของฉันในการเพิ่มประสิทธิภาพคือการแบ่งตารางขอบออกเป็นตารางระดับการซูมหลาย ๆ ฉันหมายถึงระดับที่เหมือนกับกระเบื้อง Google ยกตัวอย่างเช่นที่ระดับซูมที่ 8 ฉันมี 88 ตาราง แต่ละตารางประกอบด้วยส่วนย่อยของถนนและพื้นที่ของพวกเขาทับซ้อนกันเพื่อคำนวณเส้นทางระหว่างสองจุดที่อยู่ไม่ไกลจาก 290 กม. จากแต่ละอื่น ๆ ใช้เวลา 2 วินาที ในเวลา 9 ระดับการคำนวณลดลงถึง 0.25 วินาทีและเรามี 352 ตาราง การสันทนาการของกราฟทั้งหมดในกรณีที่เราแก้ไขถนนใช้เวลาไม่เกินหนึ่งชั่วโมง วิธีที่รุนแรงในการเพิ่มความเร็วของการกำหนดเส้นทางคือการใช้อัลกอริทึม Floyd-Warshall แต่ไม่มีใครรู้ว่าต้องใช้เวลาเท่าใดในการคำนวณเมทริกซ์รุ่นก่อนบนขอบจำนวนมาก

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