หากคุณตั้งสมมติฐานเล็กน้อยเกี่ยวกับจำนวนการทับซ้อนกันในช่วงคำนำหน้าของคุณ คุณสามารถทำสิ่งที่คุณต้องการได้อย่างเหมาะสมที่สุดโดยใช้ MongoDB หรือ MySQL ในคำตอบของฉันด้านล่าง ฉันจะอธิบายด้วย MongoDB แต่ควรจะง่ายพอที่จะย้ายคำตอบนี้ไปยัง MySQL
ก่อนอื่น เรามาเรียบเรียงปัญหากันใหม่สักหน่อย เมื่อคุณพูดถึงการจับคู่ "ช่วงคำนำหน้า" ฉันเชื่อว่าสิ่งที่คุณกำลังพูดถึงคือการค้นหาช่วงที่ถูกต้องภายใต้การเรียงลำดับ พจนานุกรม (โดยสังหรณ์ใจ นี่เป็นเพียงการเรียงลำดับสตริงตามตัวอักษรตามธรรมชาติ) ตัวอย่างเช่น ชุดตัวเลขที่คำนำหน้าตรงกับ 54661601 ถึง 54661679 นั้นเป็นชุดตัวเลขที่เมื่อเขียนเป็นสตริง จะมีค่าพจนานุกรมมากกว่าหรือเท่ากับ "54661601" แต่ในทางพจนานุกรมน้อยกว่า "54661680" ดังนั้นสิ่งแรกที่คุณควรทำคือเพิ่ม 1 เข้าไปในขอบเขต สูง ทั้งหมดของคุณ เพื่อที่คุณจะสามารถแสดงความคิดเห็นในลักษณะนี้ได้ ในภาษามองโก เอกสารของคุณจะมีลักษณะประมาณนี้
{low: "54661601", high: "54661680", bin: "a"}
{low: "526219100", high: "526219200", bin: "b"}
{low: "4305870404", high: "4305870405", bin: "c"}
ตอนนี้ปัญหากลายเป็น: เมื่อพิจารณาจากชุดของช่วงเวลาหนึ่งมิติของรูปแบบ [ต่ำ, สูง) เราจะค้นหาได้อย่างรวดเร็วว่าช่วงใดมีจุดที่กำหนด ? วิธีที่ง่ายที่สุดในการทำเช่นนี้คือให้ดัชนีอยู่ในช่อง ต่ำ หรือ สูง ลองใช้ฟิลด์ สูง ในเปลือก Mongo:
db.coll.ensureIndex({high : 1})
สำหรับตอนนี้ สมมติว่าช่วงเวลาไม่ทับซ้อนกันเลย หากเป็นกรณีนี้ สำหรับจุดสืบค้นที่กำหนด "x" ช่วงเวลาเดียวที่เป็นไปได้ที่มี "x" คือช่วงที่มีค่า สูง น้อยที่สุดมากกว่า "x" ดังนั้นเราจึงสามารถค้นหาเอกสารนั้นและตรวจสอบว่าค่า ต่ำ ของเอกสารนั้นน้อยกว่า "x" หรือไม่ ตัวอย่างเช่น ระบบจะพิมพ์ช่วงเวลาการจับคู่ออกมา หากมี:
db.coll.find({high : {'$gt' : "5466160179125211"}}).sort({high : 1}).limit(1).forEach(
function(doc){ if (doc.low <= "5466160179125211") printjson(doc) }
)
สมมติว่าตอนนี้แทนที่จะสมมติว่าช่วงต่างๆ ไม่ทับซ้อนกันเลย คุณถือว่าทุกช่วงซ้อนทับกันโดยมีช่วงใกล้เคียงน้อยกว่า k (ฉันไม่รู้ว่าค่าของ k จะทำให้สิ่งนี้เป็นจริงสำหรับคุณ แต่หวังว่ามันจะเป็นเรื่องเล็ก) ในกรณีนั้น คุณสามารถแทนที่ 1 ด้วย k ใน "ขีดจำกัด" ด้านบนได้ เช่น
db.coll.find({high : {'$gt' : "5466160179125211"}}).sort({high : 1}).limit(k).forEach(
function(doc){ if (doc.low <= "5466160179125211") printjson(doc) }
)
อัลกอริทึมนี้ใช้เวลาทำงานเท่าใด ดัชนีจะถูกจัดเก็บโดยใช้ B-trees ดังนั้น หากมีช่วง n ในชุดข้อมูลของคุณ จะต้องใช้เวลา O(log n) ในการค้นหาเอกสารแรกที่ตรงกันโดย < ค่า strong>สูง จากนั้นจึงใช้เวลา O(k) เพื่อวนซ้ำเอกสาร k ถัดไป รวมเป็น O(log n em> + k) เวลา ถ้า k เป็นค่าคงที่ หรือจริงๆ แล้วมีค่าน้อยกว่า O(log n) นี่จะเป็นค่าที่เหมาะสมที่สุดเชิงกำกับเชิงกำกับ (นี่คือแบบจำลองมาตรฐานของการคำนวณ ฉันไม่ นับจำนวนการถ่ายโอนหน่วยความจำภายนอกหรืออะไรแฟนซี)
กรณีเดียวที่การแบ่งส่วนนี้คือเมื่อ k มีขนาดใหญ่ เช่น ถ้าช่วงขนาดใหญ่บางช่วงมีช่วงอื่นๆ เกือบทั้งหมด ในกรณีนี้ เวลาทำงานคือ O(n) หากข้อมูลของคุณมีโครงสร้างเช่นนี้ คุณอาจต้องการใช้วิธีการอื่น แนวทางหนึ่งคือการใช้การจัดทำดัชนี "2d" ของ mongo โดยมีค่า ต่ำ และ สูง ของคุณในการเข้ารหัสพิกัด x และ y . จากนั้นการสืบค้นของคุณจะสอดคล้องกับการสืบค้นจุดในภูมิภาคที่กำหนดของระนาบ x - y สิ่งนี้อาจทำได้ดีในทางปฏิบัติ แม้ว่าในปัจจุบันมีการใช้การจัดทำดัชนีแบบ 2 มิติ แต่กรณีที่แย่ที่สุดยังคงเป็น O(n)
มีผลลัพธ์ทางทฤษฎีจำนวนหนึ่งที่ได้รับประสิทธิภาพ O(log n) สำหรับค่าทั้งหมดของ k พวกมันใช้ชื่อต่างๆ เช่น ทรีการค้นหาลำดับความสำคัญ ทรีเซ็กเมนต์ ทรีช่วงเวลา ฯลฯ อย่างไรก็ตาม โครงสร้างข้อมูลเหล่านี้เป็นโครงสร้างข้อมูลสำหรับวัตถุประสงค์พิเศษที่คุณต้องนำไปใช้ด้วยตนเอง เท่าที่ฉันรู้ ขณะนี้ไม่มีฐานข้อมูลยอดนิยมใดที่นำไปใช้งาน
person
matulef
schedule
16.06.2012