เหตุใดทิศทางของดัชนีจึงมีความสำคัญใน MongoDB


114

ในการอ้างอิงเอกสาร :

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

อย่างไรก็ตามฉันไม่เห็นเหตุผลว่าทำไมทิศทางของดัชนีจึงมีความสำคัญกับดัชนีผสม ใครช่วยให้คำอธิบายเพิ่มเติม (หรือตัวอย่าง) ได้ไหม

คำตอบ:


113

MongoDB เชื่อมต่อคีย์ผสมไม่ทางใดก็ทางหนึ่งและใช้เป็นคีย์ใน BTree

เมื่อพบรายการเดียว - ลำดับของโหนดในทรีไม่เกี่ยวข้อง

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

ด้วยดัชนีเขตข้อมูลเดียว - คำสั่งจะไม่สำคัญ ถ้าพวกเขาอยู่ใกล้กันจากน้อยไปมากพวกเขาก็จะอยู่ใกล้กันในลำดับจากมากไปหาน้อยเช่นกัน

เมื่อคุณมีคีย์ผสม - คำสั่งเริ่มมีความสำคัญ

ตัวอย่างเช่นหากคีย์คือ A จากน้อยไปมาก B ดัชนีอาจมีลักษณะดังนี้:

แถว AB
1 1 1
2 2 6
3 2 7 
4 3 4
5 3 5
6 3 6
7 5 1

ข้อความค้นหาสำหรับ A จากน้อยไปหามาก B จะต้องกระโดดไปรอบ ๆ ดัชนีเพื่อส่งกลับแถวและจะช้าลง ตัวอย่างเช่นจะส่งคืน Row1, 3, 2, 6, 5, 4, 7

แบบสอบถามที่อยู่ในลำดับเดียวกับดัชนีจะส่งคืนแถวตามลำดับตามลำดับที่ถูกต้อง

การค้นหาบันทึกใน BTree ใช้เวลา O (Log (n)) การค้นหาช่วงของระเบียนตามลำดับคือ OLog (n) + k เท่านั้นโดยที่ k คือจำนวนระเบียนที่จะส่งคืน

หากบันทึกไม่เป็นระเบียบค่าใช้จ่ายอาจสูงถึง OLog (n) * k


1
แถวผลลัพธ์น่าจะเป็น1, 3, 2, 6, 5, 4, 7?
johndodo

ฉันยังไม่เห็นเหตุผลที่มันช้าลง เฉพาะอัลกอริทึมเท่านั้นที่ควรแตกต่างกัน (สำหรับแต่ละกลุ่มของค่าใน A ควรข้ามไปที่จุดสิ้นสุดของกลุ่มและประมวลผลในลำดับย้อนกลับ) แต่เนื่องจากดัชนี MongoDB อยู่ในหน่วยความจำจึงไม่ควรมีผลต่อความเร็วอย่างเห็นได้ชัด นอกจากนี้ RDBMS ไม่รู้อะไรเกี่ยวกับทิศทางกับดัชนีและสถานการณ์ก็ค่อนข้างคล้ายกัน?
johndodo

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

1
การดึงโหนดจาก BTree ตามลำดับนั้นทำได้ง่ายเพียงแค่เลื่อนไปตามแต่ละใบจนกว่าจะหมดจากนั้นจึงขึ้นระดับและลงสาขาถัดไป มัน O (n) ไม่เป็นระเบียบมันใช้ CPU มากขึ้น
Jared Kells

ขอบคุณสำหรับคำชี้แจงเพิ่มเติม ฉันตรวจสอบเอกสารสำหรับดัชนี MySQL - เป็นไปได้ที่จะระบุทิศทางดัชนี แต่การตั้งค่าจะถูกละเว้น
johndodo

46

คำตอบง่ายๆที่คุณกำลังมองหาคือว่าทิศทางเท่านั้นที่สำคัญเมื่อคุณมีการเรียงลำดับในสองคนหรือมากกว่าสาขา

หากคุณกำลังจัดเรียง{a : 1, b : -1}:

ดัชนี{a : 1, b : 1}จะช้ากว่าดัชนี{a : 1, b : -1}


1
@MarkPieszak เพราะการเรียงลำดับทั้งหมดจะต้องทำในหน่วยความจำทำให้ดัชนีไร้ประโยชน์
Sammaye

@Sammaye ฉันคิดว่านั่นเป็นความคิดที่ถูกต้องแม้ว่าฉันจะไม่แน่ใจว่าเป็นการเรียงลำดับทั้งหมด ฉันจะต้องมองไปที่การดำเนินการที่จะรู้ว่าวิธีการทำงานจริงๆ แต่ฉันคิดว่าผลที่ได้อาจจะดึงกลับมาเรียงโดยคนเดียวแล้วเพิ่มเติมเรียงลำดับจะต้องทำในหน่วยความจำ
Zaid Masud

1
อืมแปลกครั้งที่แล้วที่ฉันตรวจสอบรหัสมันลดลงบางส่วนเนื่องจากการเรียงลำดับเป็นอย่างไร แต่ฉันอาจจะเปลี่ยนไป
Sammaye

จะเกิดอะไรขึ้นถ้าฉันเรียงลำดับ{a: -1, b: -1}ฉันควรมี{a: -1, b: -1}ดัชนีหรือจะ{a: 1, b: 1}เพียงพอ
Hussain

@ ฮัสเซนในตัวอย่างของคุณ{a: 1, b: 1}ดัชนีควรเพียงพอเนื่องจากการกลับดัชนีอย่างสมบูรณ์นั้นดี เช่น Index on {a: 1}สามารถใช้สำหรับการเรียงลำดับบน{a: -1}
Zaid Masud

12

ทำไมต้องจัดทำดัชนี

ทำความเข้าใจประเด็นสำคัญสองประเด็น

  1. แม้ว่าดัชนีจะดีกว่าไม่มีดัชนี แต่ดัชนีที่ถูกต้องนั้นดีกว่าอย่างใดอย่างหนึ่ง
  2. MongoDB จะใช้เพียงดัชนีเดียวต่อหนึ่งแบบสอบถามทำให้ดัชนีผสมกับฟิลด์ที่เหมาะสมเพื่อเรียงลำดับสิ่งที่คุณอาจต้องการใช้

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

ดัชนีอย่างไร

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

ทำไมต้องจัดเรียง

คำถามของคุณอาจต้องมีการเรียงลำดับ แต่การจัดเรียงอาจเป็นการดำเนินการที่มีราคาแพงดังนั้นจึงเป็นเรื่องสำคัญที่จะต้องปฏิบัติต่อเขตข้อมูลที่คุณกำลังเรียงลำดับเช่นเดียวกับเขตข้อมูลที่คุณกำลังสืบค้น ดังนั้นจะเร็วกว่าถ้ามีดัชนี แม้ว่าจะมีข้อแตกต่างที่สำคัญอย่างหนึ่งคือฟิลด์ที่คุณกำลังเรียงลำดับจะต้องเป็นฟิลด์สุดท้ายในดัชนีของคุณ ข้อยกเว้นเพียงประการเดียวของกฎนี้คือถ้าช่องนั้นเป็นส่วนหนึ่งของข้อความค้นหาของคุณด้วยก็จะไม่ใช้กฎ must-be-last-rule

วิธีการจัดเรียง

คุณสามารถระบุการเรียงลำดับบนคีย์ทั้งหมดของดัชนีหรือในชุดย่อย อย่างไรก็ตามคีย์การจัดเรียงจะต้องอยู่ในลำดับเดียวกับที่ปรากฏในดัชนี ตัวอย่างเช่นรูปแบบคีย์ดัชนี {a: 1, b: 1} สามารถรองรับการจัดเรียงบน {a: 1, b: 1} แต่ไม่รองรับบน {b: 1, a: 1}

การเรียงลำดับต้องระบุทิศทางการจัดเรียงเดียวกัน (เช่นจากน้อยไปมาก / มากไปหาน้อย) สำหรับคีย์ทั้งหมดเป็นรูปแบบคีย์ดัชนีหรือระบุทิศทางการจัดเรียงย้อนกลับสำหรับคีย์ทั้งหมดเป็นรูปแบบคีย์ดัชนี ตัวอย่างเช่นรูปแบบคีย์ดัชนี {a: 1, b: 1} สามารถรองรับการจัดเรียงบน {a: 1, b: 1} และ {a: -1, b: -1} แต่ไม่รองรับ {a: -1 , b: 1}

สมมติว่ามีดัชนีเหล่านี้:

{ a: 1 }
{ a: 1, b: 1 }
{ a: 1, b: 1, c: 1 }

Example                                                    Index Used
db.data.find().sort( { a: 1 } )                            { a: 1 }
db.data.find().sort( { a: -1 } )                           { a: 1 }
db.data.find().sort( { a: 1, b: 1 } )                      { a: 1, b: 1 }
db.data.find().sort( { a: -1, b: -1 } )                    { a: 1, b: 1 }
db.data.find().sort( { a: 1, b: 1, c: 1 } )                { a: 1, b: 1, c: 1 }
db.data.find( { a: { $gt: 4 } } ).sort( { a: 1, b: 1 } )   { a: 1, b: 1 }

ผมเข้าใจว่าเป็นตัวอย่าง แต่ถ้ามีดัชนี{ a: 1, b: 1, c: 1 }คุณต้องดัชนีจริงๆ{ a: 1}และ{ a: 1, b: 1}หรือดัชนี{ a: 1, b: 1, c: 1 }ครอบคลุมทุกกรณี? หากคำค้นหาใช้การเรียงลำดับเดียวกันเสมอ: 1 no sorts in query with -1
Lukas Liesis

1
หากมีแบบสอบถามจำนวนมากที่ทำงานกับคุณสมบัติ 'a' เพียงอย่างเดียวการค้นหาด้วยดัชนีที่มีคุณสมบัติ 'a' สำหรับเครื่องมือฐานข้อมูลจะเร็วกว่าการค้นหาด้วยดัชนีที่มีคุณสมบัติ 3 อย่าง 'a', 'b', 'c' เนื่องจากขนาดดัชนีจะเพิ่มขึ้นและการนับก็เพิ่มขึ้นด้วย เช่น หากมี 20 บทในหนังสือ ดังนั้นจึงเร็วกว่าที่จะไปที่บทที่ 3 จากนั้นไปที่หน้าเฉพาะ @LukasLiesis
Somnath Muluk
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.