4.7. B-Trees โครงสร้าง tree ที่กล่าวถึงมาแล้วนั้น อยู่บนสมมติฐานที่ว่าโครงสร้างทั้งหมดสามารถจัดเก็บอยู่ในหน่วยความจำของเครื่องคอมพิวเตอร์ได้ ถ้า จำนวนข้อมูลมีปริมาณมากเกินกว่าที่จะเก็บไว้ใน หน่วยความจำ ของเครื่องได้ทั้งหมด ก็หมายความว่าต้องเก็บมันไว้ในแผ่นจานแม่เหล็ก ซึ่งกรณีเช่นนี้ การประมาณค่า running time ต้องนำ เวลา การเข้าถึงข้อมูลในแผ่นจานแม่เหล็ก มาคำนึงถึงด้วย
พิจารณาข้อเท็จจริงต่อไปนี้ 4.7. B-Trees พิจารณาข้อเท็จจริงต่อไปนี้ ถ้าเครื่องคอมพิวเตอร์เป็นเครื่องขนาด 25 MIPs ก็หมายความว่ามันมีขีดความสามรถการประมวลผลที่เป็นไปได้ คือ 25 ล้าน instructions/sec. และ ถ้าเครื่องนี้มี disk drive ความเร็ว 3600 RPM (ที่เร็วกว่านี้ก็มี คือ 7500, ถึง 10000 RPMs) นั่นคือ หนึ่งรอบการหมุนใช้เวลา 1/60 วินาที หรือ 16.7 mSec. และถ้าเราคิดว่าโดยเฉลี่ยแล้วต้องใช้การหมุนครึ่งรอบจึงจะได้ข้อมูลที่ต้องการและถ้าเราไม่คำนึงถึงปัจจัยอื่น ๆ เลย ก็หมายความว่าเราต้องใช้เวลา 8.3 mSec. เพื่อให้ได้ข้อมูล ผลก็คือเราสามารถเข้าถึงได้ 120 ครั้งต่อวินาที ซึ่งไม่น้อย แต่หากเปรียบเทียบกับ 25 ล้าน instructions/sec แล้ว เทียบกันไม่ได้เลย
การทำงานสำหรับ search tree ในแผ่นจานแม่เหล็ก โดยทั่วไป: 4.7. B-Trees การทำงานสำหรับ search tree ในแผ่นจานแม่เหล็ก โดยทั่วไป: ถ้ามี 10 ล้านหน่วยข้อมูล แต่ละหน่วยใช้เนื้อที่ 32 ไบต์ และแต่ละระเบียนใช้ 256 ไบต์ และถ้าข้อมูลทั้งหมดไม่สามารถบรรจุลงในหน่วยความจำได้ทั้งหมดในคราวเดียว ถ้าให้เราเป็นผู้ใช้งานระบบ 1 ใน 20 คน (ดังนั้นเราจะสามารถใช้ทรัพยากรของระบบได้เป็น 1/20) ใน 1 วินาทีจะ execute คำสั่งได้หนึ่งล้าน instructions หรือเข้าถึงแผ่นจานแม่เหล็กได้ 6 ครั้ง
การใช้ binary search tree ที่ไม่สมดุลเป็นสิ่งไม่พึงประสงค์ 4.7. B-Trees การใช้ binary search tree ที่ไม่สมดุลเป็นสิ่งไม่พึงประสงค์ กรณี worst case มี depth เป็น linear และต้องใช้การเข้าถึง disk จำนวน 10 ล้านครั้ง กรณีเฉลี่ย, การค้นหาค่าที่ประสบความสำเร็จต้องใช้การเข้าถึง disk จำนวน 1.38 log N ครั้ง— ประมาณ 32 ครั้ง หรือ 5 วินาที ถ้าใช้ AVL tree, กรณี worst case ใช้การเข้าถึง disk จำนวน 1.44 log N ครั้ง โดยทั่วไปจะใกล้เคียงกับ log N ดังนั้นต้องใช้การเข้าถึง disk ประมาณ 25 ครั้งโดยเฉลี่ย หรือประมาณ 4 วินาที
ประเด็นคือเราไม่สามารถทำได้ดีกว่า log N ในการใช้ Binary Tree 4.7. B-Trees ประเด็นคือเราไม่สามารถทำได้ดีกว่า log N ในการใช้ Binary Tree ทางแก้ คือ ถ้าเรามี branch ของ node มากขึ้น ก็หมายความว่า height ก็จะน้อยลงไปด้วย ขณะที่ perfect binary tree ที่มี 31 โนด มี 5 ระดับนั้นถ้าเป็น 5-ary tree ที่มี 31 โนดเท่ากันนั้น มีเพียง 3 ระดับเท่านั้น
Figure 4.58 5-ary tree ที่มี 31 โนด M-ary search tree มี M branch Branch เพิ่มทำให้ depth ลดลง complete M-ary tree มี height ประมาณ logM N ใน M-ary search tree, เราใช้ค่า M – 1 ค่าในการตัดสินใจเลือก branch ที่จะเดินทางต่อไปใน tree
B-tree ที่มี order M คือ M-ary tree ที่มีโครงสร้างดังนี้: 4.7. B-Trees B-tree ที่มี order M คือ M-ary tree ที่มีโครงสร้างดังนี้: หน่วยข้อมูลเก็บอยู่ที่ leaves Node ที่ไม่ใช่ leaf เก็บค่าได้ M – 1 ค่าเพื่อเป็นค่าชี้แนะในการค้นหา ค่าที่ i เป็นค่าที่น้อยที่สุดใน subtree ที่ i + 1 Root อาจเป็นตัว leaf เอง หรือมี child ได้ระหว่าง 2 ถึง M Node ที่ไม่ใช่ leaf ทั้งหมด (ยกเว้น root) มี child ได้ตั้งแต่ M/2 ถึง M node Leaves ทั้งหมดอยู่ในระดับเดียวกัน และมีค่าข้อมูลตั้งแต่ L/2 ถึง L, สำหรับค่า L ใด ๆ
Figure 4.59 B-tree order 5 and L=5 8 10 12 14 16 2 4 6 18 20 22 24 26 28 30 31 32 35 36 37 38 39 48 49 50 41 42 44 46 51 52 53 54 56 58 59 72 73 74 76 66 68 69 70 78 79 81 83 84 85 92 93 95 87 89 90 97 98 99 Node ที่ไม่ใช่ leaf ทุกตัวมี child ตั้งแต่ 3 ถึง 5 ( ดังนั้นมันมีค่าตั้งแต่ 2 ถึง 4 ค่า); root อาจมี child ได้น้อยสุด 2 โนด เนื่องจาก L = 5 ดังนั้นแต่ละ leaf จึงมีค่าข้อมูลได้ตั้งแต่ 3 ถึง 5 ค่า
สมมุติให้หนึ่ง block มีขนาด 8192 ไบต์ 4.7. B-Trees ถ้าแต่ละ node แทนหนึ่ง disk block เราจะเลือกค่า M และ L โดยใช้ขนาดของหน่วยข้อมูลที่จะจัดเก็บเป็นตัวพิจารณา สมมุติให้หนึ่ง block มีขนาด 8192 ไบต์ จากตัวอย่างที่แล้ว แต่ละค่าใช้ 32 ไบต์ B-tree ที่มี order M เราจะมีค่าในโนดได้ M – 1 ค่า, ทั้งหมดจึงเป็น 32M – 32 ไบต์ บวกกับขนาดกิ่งอีก M กิ่ง ถ้าขนาดกิ่งใช้ 4 ไบต์ ดังนั้นจำนวนกิ่งทั้งหมดของโนดจึงใช้ 4M ไบต์ ขนาดหน่วยความจำทั้งหมดที่ต้องการสำหรับ node ที่ไม่ใช่ leaf คือ 36M – 32
เลือก M = 228 (ได้จาก 36M – 32 < 8192) 4.7. B-Trees เลือก M = 228 (ได้จาก 36M – 32 < 8192) เนื่องจากหนึ่งระเบียนใช้ 256 ไบต์ จึงบรรจุได้ 32 ระเบียนในหนึ่งบล็อก จึงเลือก L = 32 แต่ละ leaf มีข้อมูลได้ตั้งแต่ 16 ถึง 32 ระเบียนข้อมูลและใน internal node (ยกเว้นราก) มีกิ่งแยกได้อย่างน้อยที่สุด 114 ทาง เนื่องจากเรามี 10 ล้านระเบียน, ดังนั้นจึงใช้ leaf อย่างมากที่สุด 625000 leaves (10 ล้าน หารด้วย 16) ผลที่ได้คือ ในกรณี worst case จำนวนการเข้าถึงโนดที่ต้องใช้ คือ log M/2 N ( ประมาณ 3 )
NOTE** Bayer & McCreight (1972), Comer (1979), and others define the order of B-tree as the minimum number of keys in a non-root node. Folk & Zoellick (1992) points out that terminology is ambiguous because the maximum number of keys is not clear. An order 3 B-tree might hold a maximum of 6 keys or a maximum of 7 keys. Knuth (1998, p. 483) avoids the problem by defining the order to be maximum number of children (which is one more than the maximum number of keys). The term leaf is also inconsistent. Bayer & McCreight (1972) considered the leaf level to be the lowest level of keys, but Knuth considered the leaf level to be one level below the lowest keys (Folk & Zoellick 1992, p. 363). There are many possible implementation choices. In some designs, the leaves may hold the entire data record; in other designs, the leaves may only hold pointers to the data record. Those choices are not fundamental to the idea of a B-tree.[5]
Insertion All insertions start at a leaf node. To insert a new element, search the tree to find the leaf node where the new element should be added. Insert the new element into that node with the following steps: If the node contains fewer than the maximum legal number of elements, then there is room for the new element. Insert the new element in the node, keeping the node's elements ordered. Otherwise the node is full, evenly split it into two nodes so:
Insertion Otherwise the node is full, evenly split it into two nodes so: A single median is chosen from among the leaf's elements and the new element. Values less than the median are put in the new left node and values greater than the median are put in the new right node, with the median acting as a separation value. The separation value is inserted in the node's parent, which may cause it to be split, and so on. If the node has no parent (i.e., the node was the root), create a new root above this node (increasing the height of the tree). If the splitting goes all the way up to the root, it creates a new root with a single separator value and two children, which is why the lower bound on the size of internal nodes does not apply to the root.
กรณีต้องการบรรจุค่า 57 เข้าใน B-tree ในรูป Figure 4.59 The insertion กรณีต้องการบรรจุค่า 57 เข้าใน B-tree ในรูป Figure 4.59 8 10 12 14 16 2 4 6 18 20 22 24 26 28 30 31 32 35 36 37 38 39 48 49 50 41 42 44 46 51 52 53 54 56 57 58 59 72 73 74 76 66 68 69 70 78 79 81 83 84 85 92 93 95 87 89 90 97 98 99 Figure 4.60 หลังการบรรจุค่า 57
การบรรจุ 55 เข้าในรูป Figure 4.60: leaf ที่จะบรรจุค่า 55 เต็มแล้ว The insertion การบรรจุ 55 เข้าในรูป Figure 4.60: leaf ที่จะบรรจุค่า 55 เต็มแล้ว เนื่องจากมีค่าอยู่ L + 1 ค่า, จึงต้องแยก leaf ออกเป็น 2 ตัว และแต่ละตัวมีข้อมูล 3 ข้อมูล ต้องเปลี่ยนค่าและ branch ของ parent ของมัน 8 10 12 14 16 2 4 6 18 20 22 24 26 28 30 31 32 35 36 37 38 39 48 49 50 41 42 44 46 51 52 53 54 55 56 72 73 74 76 66 68 69 70 78 79 81 83 84 85 92 93 95 87 89 90 97 98 99 57 58 59 Figure 4.61 After insertion of 55
บรรจุ 40 เข้าในรูป Figure 4.61: leaf ที่จะบรรจุ 40 เต็มแล้ว The insertion บรรจุ 40 เข้าในรูป Figure 4.61: leaf ที่จะบรรจุ 40 เต็มแล้ว เราต้องแยก leaf ที่มีค่า 35 ถึง 39 อยู่, (และ 40) ออกเป็นสอง leaves ซึ่งจะทำให้ parent ของมันมี child เป็น 6 node โดยที่อนุญาตให้มีได้เพียง 5 เท่านั้น ดังนั้นจึงต้องทำการแยก parent พร้อมทั้งปรับปรุงค่าในตัว parent และใน parent ของ parent ดู Figure 4.62 กรณีที่ parent มีจำนวน node ลูกค่าเต็มค่าจำกัด เราจะทำการแยก node เป็นลำดับขึ้นไปใน tree จนกระทั่งถึง node ที่อยู่ในค่าจำกัดหรือจนกระทั่งถึง root ถ้าจำเป็นต้องแยก root เราสามารถทำได้โดยการสร้าง root ใหม่และมี node ทั้งสองที่แยกมานั้นเป็นchild ของ root ใหม่นี้
Figure 4.62 บรรจุ 40 ลงใน Figure 6.41 8 10 12 14 16 2 4 6 18 20 22 24 26 41 66 87 72 73 74 76 68 69 70 78 79 81 83 84 85 92 93 95 89 90 97 98 99 48 49 50 42 44 46 51 52 53 54 55 56 57 58 59 28 30 31 32 35 36 37 38 39 40 Figure 4.62 บรรจุ 40 ลงใน Figure 6.41
Deletion There are two popular strategies for deletion from a B-tree. Locate and delete the item, then restructure the tree to retain its invariants, OR Do a single pass down the tree, but before entering (visiting) a node, restructure the tree so that once the key to be deleted is encountered, it can be deleted without triggering the need for any further restructuring https://en.wikipedia.org/wiki/B-tree
The algorithm below uses the former strategy. There are two special cases to consider when deleting an element: The element in an internal node is a separator for its child nodes Deleting an element may put its node under the minimum number of elements and children Deletion from a leaf node Search for the value to delete. If the value is in a leaf node, simply delete it from the node. If underflow happens, rebalance the tree as described in section "Rebalancing after deletion" below.
Deletion from an internal node Each element in an internal node acts as a separation value for two subtrees, therefore we need to find a replacement for separation. Note that the largest element in the left subtree is still less than the separator. Likewise, the smallest element in the right subtree is still greater than the separator. Both of those elements are in leaf nodes, and either one can be the new separator for the two subtrees. Algorithmically described below: Choose a new separator (either the largest element in the left subtree or the smallest element in the right subtree), remove it from the leaf node it is in, and replace the element to be deleted with the new separator. The previous step deleted an element (the new separator) from a leaf node. If that leaf node is now deficient (has fewer than the required number of nodes), then rebalance the tree starting from the leaf node.
Rebalancing after deletion If the deficient node's right sibling exists and has more than the minimum number of elements, then rotate left Copy the separator from the parent to the end of the deficient node (the separator moves down; the deficient node now has the minimum number of elements) Replace the separator in the parent with the first element of the right sibling (right sibling loses one node but still has at least the minimum number of elements) The tree is now balanced Otherwise, if the deficient node's left sibling exists and has more than the minimum number of elements, then rotate right Copy the separator from the parent to the start of the deficient node (the separator moves down; deficient node now has the minimum number of elements) Replace the separator in the parent with the last element of the left sibling (left sibling loses one node but still has at least the minimum number of elements)
Rebalancing after deletion (con’t) Otherwise, if both immediate siblings have only the minimum number of elements, then merge with a sibling sandwiching their separator taken off from their parent Copy the separator to the end of the left node (the left node may be the deficient node or it may be the sibling with the minimum number of elements) Move all elements from the right node to the left node (the left node now has the maximum number of elements, and the right node – empty) Remove the separator from the parent along with its empty right child (the parent loses an element) If the parent is the root and now has no elements, then free it and make the merged node the new root (tree becomes shallower) Otherwise, if the parent has fewer than the required number of elements, then rebalance the parent
ต้องการลบค่า 95 ออกจาก tree ในรูป Figure 4.62. Deletion ต้องการลบค่า 95 ออกจาก tree ในรูป Figure 4.62. 8 10 12 14 16 2 4 6 18 20 22 24 26 41 66 83 72 73 74 76 68 69 70 78 79 81 87 89 90 84 85 92 93 97 98 99 48 49 50 42 44 46 51 52 53 54 55 56 57 58 59 28 30 31 32 35 36 37 38 39 40
https://www.cs.usfca.edu/~galles/visualization/BTree.html