SQL INDEX - มันทำงานอย่างไร?


19

ความรู้เกี่ยวกับฐานข้อมูลและSQLของฉันขึ้นอยู่กับชั้นเรียนของมหาวิทยาลัยเป็นส่วนใหญ่ อย่างไรก็ตามฉันใช้เวลาสองสามเดือน (เกือบปี) ใน บริษัท ที่ฉันทำงานกับฐานข้อมูล

ฉันได้อ่านหนังสือไม่กี่เล่มและผมได้มีส่วนร่วมในไม่กี่ฝึกอบรมเกี่ยวกับฐานข้อมูลเช่นMySQL, PostgreSQL, SQLite, Oracleและไม่กี่nonSQL dbวินาทีเช่นเราMongoDB, Redis, ElasticSearchฯลฯ

เช่นเดียวกับที่ฉันพูดฉันเป็นคนขอทานด้วยความรู้มากมาย แต่วันนี้มีคนบอกอะไรบางอย่างกับสิ่งที่เป็นความรู้ของผู้ขอทานของฉัน

ให้ฉันอธิบาย ลองใช้ฐานข้อมูลSQLและสร้างตารางง่ายๆPersonโดยมีเรคคอร์ดไม่กี่ตัวที่อยู่ภายใน:

id | name   | age
-----------------
1  | Alex   | 24
2  | Brad   | 34
3  | Chris  | 29
4  | David  | 28
5  | Eric   | 18
6  | Fred   | 42
7  | Greg   | 65
8  | Hubert | 53
9  | Irvin  | 17
10 | John   | 19
11 | Karl   | 23

ตอนนี้มันเป็นส่วนหนึ่งที่ผมอยากจะมุ่งเน้นไปที่ - เป็นidINDEX

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

จัดกลุ่มทีละ:

1    ... N
N+1  ... 2N
     ...
XN+1 ... (X+1)N

ดังนั้นสำหรับตัวอย่างของฉันด้วยsize = 11 elementsและN = 3มันจะเป็นเช่นนี้:

id | name   | age
-----------------
1  | Alex   | 24     // group0
2  | Brad   | 34     // group0
3  | Chris  | 29     // group0
4  | David  | 28     // group1
5  | Eric   | 18     // group1
6  | Fred   | 42     // group1
7  | Greg   | 65     // group2
8  | Hubert | 53     // group2
9  | Irvin  | 17     // group2
10 | John   | 19     // group3
11 | Karl   | 23     // group3

ดังนั้นเมื่อฉันใช้คิวรีSELECT * FROM Person WHERE id = 8มันจะทำการคำนวณง่าย ๆ8 / 3 = 2ดังนั้นเราต้องมองหาวัตถุนี้group2และจากนั้นแถวนี้จะถูกส่งกลับ:

8  | Hubert | 53

ป้อนคำอธิบายรูปภาพที่นี่

วิธีการนี้จะทำงานในเวลาที่O(k) k << sizeแน่นอนการจัดเรียงแถวเป็นกลุ่มนั้นซับซ้อนกว่านี้มาก แต่ฉันคิดว่าตัวอย่างง่ายๆนี้แสดงมุมมองของฉัน

ดังนั้นตอนนี้ฉันอยากจะนำเสนอวิธีการอื่นซึ่งได้รับการแสดงให้ฉันเห็นในวันนี้

ลองตารางนี้อีกครั้ง:

id | name   | age
-----------------
1  | Alex   | 24
2  | Brad   | 34
3  | Chris  | 29
4  | David  | 28
5  | Eric   | 18
6  | Fred   | 42
7  | Greg   | 65
8  | Hubert | 53
9  | Irvin  | 17
10 | John   | 19
11 | Karl   | 23

ตอนนี้เรากำลังสร้างบางสิ่งที่คล้ายกับHashmap(อันที่จริงแล้วเป็น Hash Map) ซึ่งแมปidไปยังaddressแถวที่มี ID นี้ สมมติว่า:

id | addr 
---------
1  | @0001
2  | @0010
3  | @0011
4  | @0100
5  | @0101
6  | @0110
7  | @0111
8  | @1000
9  | @1001
10 | @1010
11 | @1011

ดังนั้นตอนนี้เมื่อฉันเรียกใช้แบบสอบถามของฉัน: SELECT * FROM Person WHERE id = 8

มันจะแมปโดยตรงid = 8ไปยังที่อยู่ในหน่วยความจำและแถวจะถูกส่งกลับ O(1)แน่นอนความซับซ้อนของที่นี่คือ

ดังนั้นตอนนี้ฉันมีคำถามสองสามข้อ

1. อะไรคือการผจญภัยและความไม่ลงรอยกันของทั้งสองวิธี?

2. อันไหนที่ได้รับความนิยมมากขึ้นในการใช้ฐานข้อมูลปัจจุบัน? ดีบีเอสที่แตกต่างกันอาจใช้วิธีการที่แตกต่างกันอย่างไร

3. มันมีอยู่ใน nonSQL dbs หรือไม่?

ขอบคุณล่วงหน้า


เปรียบเทียบ

               |      B-tree     |   Hash Table
----------------------------------------------------
----------------   one element   -------------------
----------------------------------------------------
SEARCHING      |  O(log(N))      | O(1) -> O(N)  
DELETING       |  O(log(N))      | O(1) -> O(N)
INSERTING      |  O(log(N))      | O(1) -> O(N)
SPACE          |  O(N)           | O(N)
----------------------------------------------------
----------------    k elements   -------------------
----------------------------------------------------
SEARCHING      |  k + O(log(N))  | k * O(1) -> k * O(N)
DELETING       |  k + O(log(N))  | k * O(1) -> k * O(N)
INSERTING      |  k + O(log(N))  | k * O(1) -> k * O(N)
SPACE          |  O(N)           | O(N)

N - จำนวนเรคคอร์ด

ฉันถูกไหม? สิ่งที่เกี่ยวกับค่าใช้จ่ายในการบูรณะB ต้นไม้และตารางแฮหลังจากแต่ละแทรก / ลบ ? ในกรณีของต้นไม้ Bเราต้องเปลี่ยนพอยน์เตอร์บางส่วน แต่ในกรณีของต้นไม้ b-balanceมันต้องใช้ความพยายามมากขึ้น นอกจากนี้ในกรณีของตารางแฮชที่เราต้องทำการดำเนินงานไม่กี่โดยเฉพาะอย่างยิ่งถ้าการดำเนินการของเราสร้างความขัดแย้ง


2
ในวิธีที่สองคุณกำลังอธิบายดัชนีแฮช ส่วนที่เกี่ยวกับO(1)คุณทำให้ถูกต้อง! ในวิธีแรกดูเหมือนว่าคุณกำลังอธิบายดัชนีต้นไม้ B แต่คุณมีความเข้าใจผิดบางอย่าง ไม่มีการคำนวณ (หารด้วย 3 หรืออะไรก็ได้) มันซับซ้อนกว่าเนื่องจากต้นไม้มีระดับมากขึ้น (เป็นต้นไม้มีกิ่งใหญ่เล็กเล็กกิ่งไม้ ... แล้วออกจาก :)
ypercubeᵀᴹ

3
BTrees: en.m.wikipedia.org/wiki/B-treeประหลาดใจที่ไม่มีหลักสูตรขั้นตอนวิธีที่มหาวิทยาลัยของคุณที่อธิบายสิ่งนี้
Philᵀᴹ

@ypercube สวัสดีขอบคุณสำหรับคำตอบของคุณ เช่นเดียวกับที่ฉันเขียน: Of course, an alghoritm to organise rows in groups is for sure much more complicated but I think this simple example shows my point of view.แน่นอนฉันรู้ว่ามันซับซ้อนกว่ามาก ดังนั้นในที่สุดเมื่อฉันพูดในรหัสของฉันINDEXซึ่งโซลูชั่นของฉัน (ที่1หรือที่2 ) อยู่ใกล้กับของจริงนี้ INDEXและสิ่งที่เกี่ยวกับเวลาที่จำเป็นในการเข้าถึงการบันทึกอยู่บนพื้นฐานของ มันจริงO(1)เหรอ? มีค่าดัชนี B O(log2(N))ต้นไม้มันเสียงเหมือน ฉันถูกไหม?
ruhungry

@ FreshPhilOfSO ฉันเดา (ยิ่งกว่านั้นฉันก็แน่ใจ) มันเป็นการบรรยายเกี่ยวกับเรื่องนั้น อาจเป็นไปได้ว่าฉันพลาดอะไรบางอย่าง ...
ruhungry

ElasticSearch ใช้ดัชนีแบบกลับด้านซึ่งแตกต่างจาก B-trees elastic.co/blog/found-elasticsearch-from-the-bottom-up
Lluis Martinez

คำตอบ:


12

คุณกำลังอธิบายดัชนีต้นไม้ B และดัชนีแฮช พวกเขาทั้งคู่มีสถานที่ แต่ทั้งคู่เหมาะที่สุดสำหรับงานที่แตกต่างกัน

ข้อดีและข้อเสีย

B-tree (และ B + -tree) ดัชนีมักจะมีความสมดุล ซึ่งหมายความว่าการค้นหาค่าจะใช้เวลาเท่ากันเสมอไม่ว่าต้นไม้จะตกลงไปที่ใด (O (log n)) โดยทั่วไปจำนวนระดับในต้นไม้มี จำกัด ดังนั้นจึงมีแนวโน้มที่จะ "กว้างขึ้น" ไม่ "ลึก" สำหรับชุดข้อมูลขนาดเล็กค่าใช้จ่ายในการบำรุงรักษาและการใช้ทรี B สามารถทำได้มากกว่าการอ่านแถวทั้งหมด ดัชนี B-tree นั้นดีสำหรับชุดข้อมูลขนาดใหญ่ชุดข้อมูลที่มีการเลือกต่ำหรือชุดข้อมูลที่คุณต้องการเลือกช่วงของวัตถุไม่ใช่แค่วัตถุเดียว

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

ความนิยม

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

NoSQL

ฐานข้อมูล NoSQL รองรับดัชนีอย่างแน่นอน ส่วนใหญ่สนับสนุน B-tree หรือการเปลี่ยนแปลงบน B-tree ส่วนใหญ่ดูเหมือนจะสนับสนุนดัชนีที่แฮชเช่นกัน


4
ฉันไม่คิดว่าจำนวนของระดับใน B + ต้นไม้จะได้รับการแก้ไข อย่างน้อยไม่ได้อยู่ใน SQL-Server เท่าที่ฉันรู้
ypercubeᵀᴹ

1
นั่นเป็นเรื่องจริง ทรี B อาจมีหลายระดับ แต่โดยทั่วไปจะ จำกัด ไว้ที่ 3 หรือ 4 ฉันแก้ไขคำตอบของฉัน
sarme

สวัสดี @sarme ฉันชอบคำตอบของคุณ มันอธิบายได้มากมาย คุณไม่รังเกียจถ้าฉันเริ่มรับรางวัลสำหรับคำถามนี้หรือไม่? บางทีอาจมีบางคนเพิ่มสิ่งที่น่าสนใจ
ruhungry

1
คุณหมายถึง cardinality ต่ำสำหรับดัชนีบิตแมปหรือไม่?
หมดเวลา

1
ถูกต้องความสำคัญต่ำ ฉันต้องหยุดตอบคำถามก่อนนอน :) อัปเดตคำตอบแล้ว
sarme

4

อะไรคือการผจญภัยและความสิ้นหวังของการแก้ปัญหาทั้งสอง? โซลูชันที่สองไม่สามารถสแกนช่วงได้ เป็นการดีสำหรับการเลือก ID เดียว แต่ถ้าคุณต้องการรหัส 3 ถึง 8 ล่ะ มันจะต้องคว้าบันทึกทั้งหมดที่อยู่ในโลกแห่งความเป็นจริงไม่ใช่แค่ O (1) * 6 เพื่อที่จะดึงข้อมูล ในฐานข้อมูลขนาดใหญ่ที่มีดัชนี HashMap คุณจะได้รับบันทึกในหน้าต่างๆทำให้คุณต้องกดดิสก์และอ่านหน้าเว็บหกหน้าในหน่วยความจำ

ในโครงสร้าง B-Tree เช่นเดียวกับที่สถานการณ์แรกของคุณจะถูกนำไปใช้จริงรหัสจะเป็นลำดับบนดิสก์และหน้าเดียวน่าจะถือรหัส 3 - 8 เพิ่มความเร็วของการสแกนช่วงจะทำให้การเข้าถึงแต่ละ O (log n) .

สิ่งใดที่ได้รับความนิยมมากขึ้นในการใช้ฐานข้อมูลปัจจุบัน ดีบีเอสที่แตกต่างกันอาจใช้วิธีการที่แตกต่างกันอย่างไร ฉันไม่มีประสบการณ์มากมายในฐานข้อมูลที่แตกต่างกันมากมาย ฉันรู้ว่าเซิร์ฟเวอร์ sql ใช้ B-Trees ส่วนใหญ่ แต่ SQl 2014 มีดัชนีแฮชใหม่บางอย่างที่คุณสามารถใช้ในตารางที่แน่นอน ฉันได้ยินมาว่าไม่มีฐานข้อมูล SQL และฐานข้อมูลแคชที่สร้างจากการดึงข้อมูลแต่ละรายการใช้ดัชนีแฮชเช่นกัน วิธีนี้เหมาะสมสำหรับแคชเนื่องจากคุณต้องการบันทึกสำหรับผู้ใช้ A หน้า 11 และไม่จำเป็นต้องสแกนแบบช่วง

มันมีอยู่ใน nonSQL dbs หรือไม่? ใช่. ลองดูที่การสร้างเอกสารดัชนีสำหรับ postgressql ฉันเห็นว่ามันรองรับทั้งดัชนี Hash และ B-Tree รวมถึงดัชนีอื่น ๆ

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