จัดเรียงอัลกอริทึมที่ทำงานกับข้อมูลจำนวนมาก


12

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

ผู้สมัครคนเดียวที่ฉันพบจนถึงขณะนี้คือการเรียงลำดับการผสาน: คุณสามารถใช้อัลกอริทึมในลักษณะที่จะสแกนชุดข้อมูลของคุณในแต่ละการผสานโดยไม่ต้องเก็บข้อมูลทั้งหมดในหน่วยความจำหลักในครั้งเดียว การเปลี่ยนแปลงของ merge sort ฉันมีในใจได้อธิบายไว้ในบทความนี้ในส่วนของการใช้งานด้วยเทปไดรฟ์

ฉันคิดว่านี่เป็นทางออกที่ดี (มีความซับซ้อน O (nx log (n)) แต่ฉันอยากรู้ว่ามีวิธีการเรียงลำดับอื่น ๆ (เร็วกว่า) เรียงลำดับที่สามารถทำงานกับชุดข้อมูลขนาดใหญ่ที่ไม่เหมาะกับหน่วยความจำหลัก

แก้ไข

นี่คือรายละเอียดเพิ่มเติมตามคำตอบที่ต้องการ:

  • ข้อมูลจะต้องมีการเรียงลำดับเป็นระยะเช่นหนึ่งครั้งในหนึ่งเดือน ฉันไม่จำเป็นต้องแทรกบางระเบียนและมีการเรียงลำดับข้อมูลที่เพิ่มขึ้น
  • ไฟล์ข้อความตัวอย่างของฉันมีขนาดประมาณ 1 GB UTF-8 แต่ฉันต้องการแก้ปัญหาโดยทั่วไปแม้ว่าไฟล์จะเป็น 20 GB ก็ตาม
  • ไม่ได้อยู่ในฐานข้อมูลและเนื่องจากข้อ จำกัด อื่น ๆ จึงไม่สามารถทำได้
  • ข้อมูลถูกทิ้งโดยผู้อื่นเป็นไฟล์ข้อความฉันมีรหัสของตัวเองเพื่ออ่านไฟล์ข้อความนี้
  • รูปแบบของข้อมูลเป็นไฟล์ข้อความ: อักขระบรรทัดใหม่เป็นตัวคั่นเร็กคอร์ด

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


1
ข้อมูลประเภทใด ชุดข้อมูลที่แตกต่างกันอาจหมายถึงอัลกอริธึมที่แตกต่างกันซึ่งเหมาะกับวัตถุประสงค์ของคุณที่สุด
whatsisname

มันเป็นไฟล์ข้อความและฉันต้องเรียงลำดับบรรทัด บรรทัดไม่คงที่ความยาว แต่ความยาวไม่แตกต่างกันมากเกินไป (ประมาณ 50 ตัวอักษรต่อเรคคอร์ด)
Giorgio

3
ฉันไม่รู้จักสภาพแวดล้อมหรือข้อ จำกัด ของคุณ แต่ฉันจะใช้ฐานข้อมูลสำหรับการเรียงลำดับทุกครั้งที่ทำได้ นี่เป็นเพราะมันเป็นข้อผิดพลาดเกือบ 100% และจะมีประสิทธิภาพมากกว่าโค้ดของฉัน
NoChance

ฉันกำลังทำงานกับ Linux / Java ฉันใช้การเรียงลำดับผสานและดูเหมือนว่าจะทำงานได้ค่อนข้างราบรื่น การเรียงลำดับหลายล้านบรรทัดใช้เวลาค่อนข้างนาน แต่ฉันจำเป็นต้องทำเช่นนี้เป็นครั้งคราว
Giorgio

@Giorgio เป็นสิ่งที่ดีที่คุณได้ใช้อัลกอริทึมดังกล่าว สำหรับงานผลิตฉันยังคงแนะนำให้คุณใช้ฐานข้อมูล ไม่เพียง แต่สำหรับความเร็ว แต่ยังเพื่อความน่าเชื่อถือและความสะดวกในการบำรุงรักษา
NoChance

คำตอบ:


13

การอ้างอิงแบบบัญญัติเกี่ยวกับการเรียงลำดับและการค้นหาคือKnuth, Vol. 3 . เริ่มที่นั่น

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


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

อัลกอริธึมของ Knuth นั้นมีประโยชน์เสมอ ตัวอย่างเช่นการเรียงลำดับการผสานกับบัฟเฟอร์การเรียงลำดับฮีปสามารถมีประสิทธิภาพมากและใช้งานง่ายมาก
Sulthan

4
ไม่ใช่คำตอบที่มีประโยชน์มากเพราะเนื้อหาที่อ้างถึงไม่ฟรี สำหรับ OP ฉันแนะนำ googling สำหรับคำตอบ คุณไม่จำเป็นต้องเปลือก $ 50 bucks เพื่อรับหนังสือเมื่อข้อมูลประเภทนี้คุณสามารถค้นหาได้โดยการขุดในเว็บ แน่นอนว่าคุณสามารถดาวน์โหลดได้ฟรีจาก ( อะแฮ่ม ) บางไซต์เช่นกัน สมควรได้รับคำตอบที่ยอมรับได้ยาก
Thomas Eding

1
@ThomasEding มีสิ่งเหล่านี้เรียกว่า "ห้องสมุด" ที่มีจำนวนมากของการจัดเก็บข้อมูลที่ล้าสมัยและอุปกรณ์การดึงที่เรียกว่า "หนังสือ" "ห้องสมุด" ทำ "หนังสือ" พร้อมให้ยืมฟรี หาก "ห้องสมุด" เฉพาะของคุณไม่มี "หนังสือ" ที่คุณต้องการพวกเขายังเสนอบริการฟรีที่เรียกว่า "ยืมระหว่างห้องสมุด" ซึ่งช่วยให้ "ห้องสมุด" ยืม "หนังสือ" จาก "ห้องสมุด" อื่นเพื่อให้พวกเขาสามารถ ยืมมาให้คุณ
John R. Strohm

6

การรวม R-Way ภายนอกเช่นเดียวกับในsortคำสั่งUNIX เป็นทางเลือกที่ดี จากสูตรของคุณฉันไม่แน่ใจว่าเป็นอัลกอริธึมที่คุณหมายถึง "การจัดเรียงผสาน" และถ้าคุณไม่รู้ก็ลองดูสิ


ขอบคุณ การผสาน R-Way ภายนอกดูเหมือนแตกต่างจากที่ฉันนึกไว้ การอ่านที่น่าสนใจ
Giorgio

4

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

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

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

หากคุณต้องการทำเพียงครั้งเดียวและกำลังมองหาการแฮ็คที่รวดเร็วมากดูเหมือนว่าการผสานภายนอกนั้นจะเป็นการเริ่มต้นที่ดีถ้าคุณใช้ระบบปฏิบัติการยูนิกซ์

หากคุณต้องเก็บไว้ในคำสั่งและมักจะเพิ่มระเบียนเดียวแล้วการเรียงลำดับการแทรกจะมีความจำเป็น

คุณสามารถควบคุมรหัสที่ "อ่าน" ข้อมูลได้หรือไม่? ถ้าเป็นเช่นนั้นการจัดทำดัชนีหลายรูปแบบ (แทนที่จะเรียงลำดับด้วยการย้ายข้อมูลไปรอบ ๆ ดิสก์) จะช่วยได้มาก (จริงๆแล้วจะเป็นข้อกำหนดที่แน่นอน)

ดังนั้น:

  • ในสถานที่หรือหลายไฟล์?
  • ครั้งเดียวเป็นครั้งคราวหรือเก็บมันเรียงตลอดเวลา?
  • มีขนาดใหญ่กว่าหน่วยความจำเท่าใด (โหลดหน่วยความจำได้กี่ชุดเพื่อรับข้อมูลทั้งหมด)
  • มันอยู่ในฐานข้อมูลหรือไม่? เป็นไปได้ไหม
  • คุณควบคุมรหัสที่อ่านข้อมูลหรือไม่หรือคนอื่นจะทิ้งไฟล์โดยตรงหรือไม่
  • รูปแบบไฟล์? (ข้อความ? แก้ไขเรคคอร์ด?)
  • สถานการณ์พิเศษอื่น ๆ ที่ฉันไม่ได้ถาม

ขอบคุณสำหรับคำตอบ. คุณหมายถึงอะไร "ในสถานที่หรือหลายระเบียน"
Giorgio

ขออภัยควรมีหลักฐานอ่านคำตอบของฉัน - ฉันหมายถึงหลายไฟล์ ในสถานที่สวยมากหมายถึงขนาดบันทึกคงที่และการจัดทำดัชนี ณ จุดที่คุณอาจต้องการฐานข้อมูล
Bill K

ไม่ไม่ได้อยู่ในตำแหน่ง: บันทึกไม่ได้กำหนดขนาด ฉันใช้ไฟล์ชั่วคราวสี่ไฟล์สำหรับการติดตั้งปัจจุบัน
Giorgio

คุณสามารถตีความผลลัพธ์ด้วยรหัสหรือต้องอยู่ในรูปแบบเฉพาะ (ไฟล์ข้อความแบบแบนได้หรือไม่) ต้องเรียงลำดับบ่อยแค่ไหนทุกครั้งที่มีการเพิ่มหรือเพิ่มบางครั้ง เมื่อมีการเพิ่มบางสิ่งมันจะต่อท้ายหรือคุณสามารถเขียนรหัสที่เพิ่มได้หรือไม่
Bill K

แต่ละบรรทัดสามารถแยกวิเคราะห์เป็นเรคคอร์ด (ไฟล์เป็นไฟล์ CSV) แต่ฟิลด์ส่วนใหญ่เป็นข้อความ จำเป็นต้องเรียงลำดับเป็นระยะ ๆ (เช่นทุกเดือน) และใช้เวลาประมาณ 1 ชั่วโมงในการจัดเรียงตามการใช้งานปัจจุบันของฉัน สำหรับการแทรกบรรทัดฉันสามารถเขียนโค้ดที่แทรกบรรทัดในตำแหน่งที่ถูกต้อง: ด้วยรหัสที่ฉันมีจนถึงตอนนี้ฉันใช้เวลา 20 นาทีในการเขียนเครื่องมือเช่นนี้
Giorgio

3

หากคุณต้องการโซลูชันที่ปรับขนาดได้จริง ๆ คุณควรดูที่ TeraSort การใช้การเรียงลำดับแบบมาตรฐานพร้อมแผนที่ลด รายละเอียดเพิ่มเติมใน StackOverflow


1
+1: ลิงก์ที่น่าสนใจ ไม่ผสานเรียงตัวอย่างแผนที่ / ย่อแผนที่ที่สอดคล้องกับการเรียงลำดับรายการย่อยและลดสอดคล้องกับการผสานหรือไม่
Giorgio

อาจเห็นได้ แต่คุณสามารถใช้ Hadoop ทำสิ่งนี้ให้คุณแทนการเขียนด้วยตัวเอง
m3th0dman

1

คุณอาจจะสนใจในการจัดเรียงถัง ประสิทธิภาพของเคสโดยเฉลี่ยคือเวลาเชิงเส้น

= O (n + d) n: จำนวนองค์ประกอบและ d = ความยาวของจำนวนมากที่สุดหากคุณมีสัญชาตญาณเกี่ยวกับข้อมูลของคุณเช่น หากคุณรู้ว่า 'ตัวเลข' มีความยาวได้กี่ตัว ดังนั้นถ้าคุณมีตัวเลข 2 ล้าน 6 หลัก => 0 (n) ดังนั้นจึงเป็นเส้นตรง


0

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

อาจเป็นวิธีที่ดีที่สุดคือการสร้างดัชนี / ไฟล์การแมปของคุณเองหากการเพิ่มขึ้นมีขนาดเล็ก

  1. สั่ง "ฐานข้อมูล" ของคุณอย่างใด
  2. กำหนดจำนวนเต็มให้กับทุกรายการ (1, 2, 3, 4, ... , n) (ดีกว่า: ใช้ดัชนีกระจัดกระจาย)
  3. เมื่อเพิ่มการเพิ่มเพียงแค่ค้นหาช่องว่างที่หมายเลขด้านซ้ายน้อยกว่าหรือเท่ากับและหมายเลขด้านขวามีค่ามากกว่าหรือเท่ากัน (มันไม่ควรยากที่จะแก้ไขด้วยการค้นหาแบบไบนารี่บางรุ่น)
  4. แทรกในขณะที่ช่องว่างมีขนาดใหญ่พอสมควรถ้าไม่ใช่: เพียงสร้างดัชนีใหม่ (ไม่ต้องเรียงลำดับอีกครั้ง) :-)

0

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

ฉันสามารถเรียงลำดับข้อมูล 128GB (แต่ละรายการ 100 ไบต์) ใน 9 ชั่วโมงบนเครื่องเดียวแล้วค้นหาแบบไบนารีที่เรียงลำดับข้อมูลโดยแทบไม่มีเวลา

นี่คือโพสต์เกี่ยวกับวิธีการค้นหาข้อมูลขนาดใหญ่โดยใช้คิวโอเพนซอร์สขนาดใหญ่และโครงสร้างอาร์เรย์ขนาดใหญ่ของฉัน

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