In computer science, B-tree is a self-balancing tree data structure that keeps data sorted and enables search, sequential access, insertion, and deletion in logarithmic time. B-tree is a generalization of a binary search tree where nodes can have more than two children. Unlike a self-balancing binary search tree, B-tree is perfect for storage systems that read and write relatively large blocks of data, such as discs. These are typically used in database and file systems.
What, if any, the B abbreviation has never been set.
Video B-tree
Ikhtisar
In B-tree, the internal (non-leaf) node can have a variable number of child nodes in some predefined range. When data is inserted or deleted from the node, the number of child nodes changes. To maintain a predetermined range, internal nodes can be merged or separated. Since multiple child nodes are allowed, B-tree does not need to re-balance as often as other self-balancing search trees, but may waste space, because nodes are not fully loaded. The lower and upper limits on the number of child nodes are usually set for a particular implementation. For example, in 2-3 B-trees (often referred to as 2-3 tree ), each internal node may have only 2 or 3 child nodes.
Each internal B-tree node contains a number of keys. The key acts as the separation value that divides the subtrees. For example, if the internal node has 3 child nodes (or subtasks) then it must have 2 keys: a 1 /sub>. All values ââin the leftmost subtree will be smaller than a 1 , all values ââin the middle subtree will be between a sub> and a 2 , and all the values ââin the far right subtree will be greater than a 2 .
The number of branches (or child nodes) of a node will be one more than the number of keys stored in the node. In 2-3 B-tree, the internal node will store one key (with two child nodes) or two keys (with three child nodes). B-tree is sometimes depicted with parameters - or simply with the highest branching order, .
The B-tree is balanced by requiring all leaf nodes to be at the same depth. This depth will increase slowly when the element is added to the tree, but the overall depth increase is rare, and produces all leaf nodes into one node further from the root.
B-tree has great advantages over alternative implementations when the time to access data from a node greatly exceeds the time spent processing the data, because then the cost of accessing the node can be amortized through multiple operations within the node. This usually occurs when the data nodes are in secondary storage such as disk drives. By maximizing the number of keys in each internal node, the tree height decreases and the number of expensive node access decreases. In addition, rebalancing of trees is less common. The maximum number of child nodes depends on the information that should be stored for each child node and the size of the full disk block or analog size in the secondary storage. While 2-3 B trees are more easily explained, the practical B trees that use secondary storage require a large number of child knots to improve performance.
Variant
The term B-tree may refer to a particular design or may refer to a general design class. In a narrow sense, the B-tree stores keys in its internal nodes but there is no need to store them in the leaf notes. Common classes include variations such as B trees and B * trees.
- In tree B, the copy of the key is stored in the internal node; keys and records stored in leaves; In addition, the leaf node may include a pointer to the next leaf node to speed up sequential access.
- Tree B * balances the adjacent internal node to keep the internal node closer. This variant ensures the non-root node is at least 2/3 full rather than 1/2 (Knuth 1998, p.Ã, 488). As the most expensive part of the operation entering the nodes in the B-tree is the divide node, B * -trees made to delay the separation operation as long as they can. To maintain this, instead of directly separating the node when it is full, the key is shared with the adjacent node. This spill operation is cheaper than a split, because it only needs to shift the key between existing nodes, not allocating memory for new ones. To enter, first check whether the node has some empty space in it, and if so, the new key is only inserted into the node. However, if the full node (has m - 1 key, where m is the order of trees as the maximum number of pointers to subtrees of one node) it needs to be checked if the right relative exists and has some empty space. If the right sibling has j & lt; m - 1 key, then the key is redistributed between two vertices of peers as equally as possible. For this purpose, the m key of the current node plus the new key is inserted, one key from the main node and the j key of your node appears as a sequence of m j 1 . The array becomes split in two, so ? ( m j 1)/2? the lowest key stays in the current node, the next (middle) key is inserted into the parent and the rest goes to the right sibling. (The key you just entered may end up in one of three places.) The situation when the sibling is completely full, and the left can not be analogized. When both nodes are full, then the two nodes (current node and sibling) are divided into three and one key is moved up the tree, to the parent node. If the parent is full, then the spill/split operation spreads to the root node. Removing a node is somewhat more complicated than entering.
- The B-tree can be converted into an order statistics tree to allow quick search for N records in key sequences, or calculate the number of recordings between any two records, and various other related operations.
Maps B-tree
Use of B-tree in database
Time to search for sorted files
Normally, sorting and searching algorithms are characterized by a number of comparison operations that must be performed using command notation. Binary searches from tables sorted with N records, for example, can be done in approximately ? log 2 N ? comparison. If the table has 1,000,000 records, then special records can be found with at most 20 comparisons: ? log 2 (1,000,000)? = 20 .
Large databases have historically been stored on disk drives. The time to read the note on the disk drive far exceeds the time it takes to compare the key after the recording is available. Time to read notes from disk drives involves search time and rotation delays. The search time may be 0 to 20 milliseconds or more, and the average rotation delay is about half the rotation period. For a 7200 RPM drive, the rotation period is 8.33 milliseconds. For drives such as Seagate ST3500320NS, the track-to-track search time is 0.8 milliseconds and the average search reading time is 8.5 milliseconds. For simplicity, consider reading from disk takes about 10 milliseconds.
Then, naively, the time to find one record of one million will take 20 disks read every time 10 milliseconds per disk is read, ie 0.2 seconds.
Time will not be too bad because individual records are grouped together in a block disk. The disk block may be 16 kilobytes. If each record is 160 bytes, then 100 records can be stored in each block. The disk read time above is actually for the entire block. After the disk head is in position, one or more disk blocks can be read with little delay. With 100 notes per block, 6 or more recent comparisons do not need to do disk readings - all comparisons in the last disk block readings.
To speed up further searches, the first 13 to 14 comparisons (each requiring disk access) should be accelerated.
Index accelerates search
Significant improvement can be done with the index. In the example above, the initial reading disk narrows the search range by a factor of two. It can be substantially increased by creating an additional index that contains the first recording on each disk block (sometimes called the sparse index). This additional index will be 1% of the original database size, but can be searched faster. Finding an entry in the additional index will tell us which blocks to look for in the main database; after searching for additional indexes, we have to search for only one block from the main database - at the cost of one disk read. The index will hold 10,000 entries, so it will require at most 14 comparisons. Like the primary database, 6 or more recent comparisons in the aux index will be on the same disk block. The index can be searched in about 8 disks read, and the desired record can be accessed in 9 disks read.
Tricks create additional indexes that can be repeated to create additional indexes to additional indexes. It will create aux-aux index which will require only 100 entries and will fit in a single disk block.
Instead of reading 14 disk blocks to find the desired recording, we only need to read 3 blocks. Reading and searching the first (and only) block of the aux-aux index identifies the relevant blocks in the aux-index. Reading and searching the aux-index blocks identifies the relevant blocks in the main database. Instead of 150 milliseconds, we only need 30 milliseconds to get the recording.
The additional index has changed the search problem from a binary search that takes approximately log 2 N logs to one that only needs log < sub> b N disk read where b is the blocking factor (number of entries per block: b = 100 entries per block in our example; log 100 1.000.000 = 3 read).
In practice, if the main database is frequently searched, the aux-aux and many indexes of the aux index may be in the disk cache, so they will not read the disk.
Insertion and deletion
If the database does not change, then the index compilation is easy to do, and the index does not need to be changed. If there are changes, then managing the database and its index becomes more complicated.
Deleting records from database is relatively easy. The index may remain the same, and the recording can only be marked as deleted. The database remains in sorted order. If there are many deletions, search and storage becomes less efficient.
Insertion can be very slow in sorted sequential files because the space for inserted records must be created. Inserting records before the first recording requires the transfer of all recordings down. Such operations are too expensive to be practical. One solution is to leave some space. Instead of packing all the records in blocks, blocks can have some blank space to allow for subsequent insertion. The spaces will be marked as if it were a "deleted" note.
Fast insertion and deletion as long as space is available in blocks. If the insertion will not fit on the block, then some free space in some nearby block must be found and additional index adjusted. The hope is that adequate space is available nearby, so many blocks need not be reorganized. Alternatively, some out-of-sequence disk blocks may be used.
Benefits of using B-tree for database
Tree B uses all of the ideas described above. Specifically, B-tree:
- stores keys in sorted order for consecutive redirects
- uses a hierarchical index to minimize the number of disk readings
- uses partial full blocks to speed up insertion and deletion
- create an index balanced with recursive algorithms
In addition, B-trees minimize waste by making sure the interior nodes are at least half full. B-tree can handle arbitrary insertion and deletion counts.
Technical description
Terminology
The B-tree literature is not uniform in its terminology (Folk & amp; Zoellick 1992, p.Ã, 362).
Bayer & amp; McCreight (1972), Comer (1979), and others define the order of B-tree as the minimum number of keys in the non-root node. Folk & amp; Zoellick (1992) suggests that terminology is unclear because the maximum number of keys is unclear. The order of 3 B-trees may save a maximum of 6 keys or a maximum of 7 keys. Knuth (1998, p.Ã, 483) avoids the problem by defining order as the maximum number of children (which is more than the maximum number of keys).
The terms leaf are also inconsistent. Bayer & amp; McCreight (1972) considers the leaf rate to be the lowest level of the key, but Knuth considers the leaf level to be one level below the lowest key (Folk & Zoellick 1992, p363). There are many possible implementation options. In some designs, leaves can store all data records; in another design, the leaf may just save the pointer to the data record. Those choices are not fundamental to the idea of ââtree B.
There is also an unfavorable option such as using the k variable to represent the number of children when k can be confusing with the number of keys.
For simplicity, most authors assume there are a fixed number of fixed keys in a node. The basic assumption is that the key size is fixed and the size of the node is fixed. In practice, variable length keys can be used (Folk & Zoellick 1992, p 379).
Definition
By Knuth's definition, B-tree of order m is a tree that satisfies the following properties:
- Each node has at most m children.
- Any non-leaf node (except root) has at least? m /2? children.
- Root has at least two children if not a leaf node.
- Leafless node with k children contains k -1 key.
- All the leaves appear on the same level
Each internal key node acts as a separation value that divides its subtrees. For example, if the internal node has 3 child nodes (or subtrees) then it should have 2 keys: a 1 and a 2 . All values ââin the leftmost subtree will be less than a 1 , all values ââin the middle subtree will be between a 1 and a 2 , and all values ââin the rightmost subtree will be greater than a 2 .
- Internal node
- The internal nodes of all nodes except for leaf node and root node. They are usually represented as a series of child elements and bookmarks sorted. Each internal node contains maximum child U and minus of L children. Thus, the number of elements is always 1 less than the number of child pointers (number of elements between L -1 and U -1). U should be 2 L or 2 L -1; therefore each internal node is at least half full. The relationship between U and L implies that two half-full nodes can be combined to create legal nodes, and one complete node can be divided into two legal nodes (if there is space to push one element into the parent). This property allows to delete and insert new values ââinto B-tree and customize the tree to maintain the B-tree property.
- Root node
- The root number of children has the same upper limit as the internal node, but does not have a lower bound. For example, when there are fewer than L -1 elements in the entire tree, the root will be the only node in the tree with no children at all.
- Leaf node
- Leaf nodes have the same limits on the number of elements, but no children, and no child pointers.
B-tree of depth n 1 can hold about U many items as B-tree of depth n , but the cost of search operation, enter, and delete grows with the depth of the tree. Just like a balanced tree, the cost grows much slower than the number of elements.
Some balanced trees store values ââonly on leaf nodes, and use different types of vertices for leaf nodes and internal nodes. B-tree stores values ââin each node in the tree, and may use the same structure for all nodes. However, since leaf nodes never have children, B-trees benefit from increased performance if they use a special structure.
Best case and worst case altitude
Let h be the height of the classic B tree. Leave n & gt; 0 being the number of entries in the tree. Let m be the maximum number of children the node can have. Each node can have at most m -1 keys.
Hal ini dapat ditunjukkan (dengan induksi misalnya) bahwa B-tree of height h dengan semua node yang terisi penuh memiliki n = m < sup> h -1 entri. Oleh karena itu, tinggi case B-tree yang terbaik adalah:
Biarkan menjadi jumlah minimum anak-anak yang bisa dimiliki oleh simpul internal (bukan-root). Untuk B-tree biasa,
Comer (1979, p.Ãâ 127) dan Cormen et al. (2001, pp.Ãâ 383-384) memberikan tinggi kasus terburuk dari pohon-B (dimana simpul akar dianggap memiliki tinggi 0) sebagai
Algoritma
Cari
Searching is similar to searching binary search tree. Starting from the root, the tree is recursively passed from top to bottom. At each level, the search reduces the viewing area to the child pointer (subtree) whose range includes the search value. The subtree range is determined by the value, or key, contained in the parent node. These limiting values ââare also known as separation values.
Binary searches are usually (but not necessarily) used in nodes to find separation values ââand child interest trees.
Insertion
All insertions start from the leaf node. To insert a new element, find the tree to find the leaf node where the new element should be added. Insert new elements into the node with the following steps:
- If the node contains less than the maximum number of elements allowed, then there is room for the new element. Enter a new element in the node, keeping the node elements ordered.
- Otherwise, the full node, evenly divide it into two nodes so:
- A single median is selected from among leaf elements and new elements.
- A value less than the median is inserted into the new left node and the value is greater than the median placed in the new right node, with the median acting as a separation value.
- The separation value is entered into the parent node, which can cause it to be separated, and so on. If the node has no parent (that is, the node is root), create a new root above this node (increase the tree height).
If the separation goes to the root, it creates a new root with a single separator value and two children, which is why the lower limit on the size of the internal node does not apply to root. The maximum number of elements per node is U -1. When a node is split, one element moves to its parent, but one element is added. Thus, it should be possible to divide the maximum number of U -1 elements into two legal nodes. If this number is odd, then U = 2 L and one of the new nodes contains ( U -2)/2 = L -1 elements, and hence a legal node, and the other contains one more element, and therefore also legal. If U -1 is even, then U = 2 L -1, so there are 2 L -2 elements at the node. Half of these numbers are L -1, which is the minimum number of elements allowed per node.
The enhanced algorithm supports one feed down the tree from root to node where insertion will occur, splitting every full node encountered in the path. This prevents the need to remember the parent node into memory, which may be expensive if the nodes are in secondary storage. However, to use this enhanced algorithm, we must be able to send one element to the parent and separate the remaining U -2 elements into two legal nodes, without adding new elements. This requires U = 2 L instead of U = 2 L -1, which explains why some textbooks impose conditions this in defining the B-tree.
Deletion
There are two popular strategies to remove from B-tree.
- Find and delete items, then restructure the tree to maintain its invariant, OR
- Do one pass under the tree, but before entering a node, restructure the tree so once the key to be deleted is encountered, it can be removed without triggering the need for further restructuring
The algorithm below uses the previous strategy.
There are two special cases to consider when deleting an element:
- The element in the internal node is the separator for its derived node
- Deleting an element can place its vertices below the minimum number of elements and children
The procedures for these cases are as follows.
Removal from the leaf node
- Find the value to be deleted.
- If the value is in the leaf node, simply delete it from the node.
- If the underflow occurs, rebalance the tree as described in the "Rebalancing after deletion" section below.
Removal from internal node
Each element in the internal node acts as a separation value for two subtrees, therefore we need to find a substitute 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 larger than the separator. Both elements are in a leaf node, and one of them can be a new separator for two subtrees. The algorithm is described below:
- Select the new separator (either the largest element in the left subtree or the smallest element in the right subtree), delete it from the leaf node it contains, and replace the element to be deleted with the new separator.
- The previous step removes the element (new separator) from the leaf node. If the leaf node is now deficient (having less than the number of vertices required), then rebalance the tree starting from the leaf node.
Re-balance after deletion
Rebalancing starts from the leaves and continues to the roots until the tree is balanced. If removing elements from a node has brought it below the minimum size, then some elements must be redistributed to bring all nodes to a minimum. Typically, redistribution involves moving an element of a sibling node that has more than the minimum number of nodes. The redistribution operation is called rotation . If no brother can save the element, then the deficient node must be merged with siblings. Merging causes the parent to lose the separating element, so that the parent can become deficient and need to rebalance. Merging and rebalancing can continue to the root. Since the minimum number of elements does not apply to root, making root the only less node is not a problem. The algorithm for rebalancing trees is as follows:
- If the right brother of the existing node is short and has more than the minimum number of elements, then turn left
- Copy the separator from the host 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 brother (right sibling loses one node but still has at least the minimum number of elements)
- The tree is now balanced
- Otherwise, if you left the missing node exists and has more than the minimum number of elements, then turn right
- Copy the parent's separator to the beginning of the deficient node (the separator moves down; the deficient node now has a 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)
- The tree is now balanced
- Otherwise, if both siblings directly have only the minimum number of elements, then join the siblings that attach their separation taken from their parents
- Copy the separator to the end of the left node (the left node may be a deficient node or possibly a sibling with a minimum number of elements)
- Move all elements from right node to left node (left node now has maximum number of elements, and right node - empty)
- Remove the separator from the parent along with its empty right child (parent losing element)
- If the parent is root and now does not have an element, then empty it and create a node that is merged with a new root (the tree becomes more shallow)
- Otherwise, if the parent has an element number less than the required number, then rebalance the parent
- Note : The balancing operation is different for tree B (for example, the rotation is different because the parent has a copy of the key) and B * - tree (eg, three siblings combined into two siblings).
Access in sequence
While newly loaded databases tend to have good sequential behavior, this behavior becomes more difficult to maintain as the database grows, resulting in more random I/O and performance challenges.
Initial construction
A typical custom case is to add large amounts of pre-sorted pre-sorted data into the originally empty B-tree. While it is possible to only do a series of consecutive inserts, it enters the results of the ordered data in a tree composed almost entirely from the half-full node. Instead, special "mass-loading" algorithms can be used to produce more efficient trees with higher branching factors.
When the input is sorted, all insertions are on the far right edge of the tree, and especially whenever a node is split, we guarantee that no insertion will occur on the left half. When loading mass, we take advantage of this, instead of dividing the overfull nodes evenly, dividing it up as uneven possible: leaving the left node completely full and creating the right node with the key zero and one child (breaking the usual B-tree rule).
At the end of the bulk load, the tree is composed almost entirely of fully-filled nodes; only the rightmost node on each level may be less than full. Since the vertices may be less than half full, to redefine the normal B-tree rule, join the nodes with their left (full-secured) sibling and divide the key to generate two nodes at least half full. (The only knot that does not have full siblings is its root, which is allowed to be less than half full.)
In the file system
In addition to its use in the database, B-tree (or Ã,çÃ, Variants) is also used in file systems to allow quick random access to random blocks in certain files. The basic issue is to rotate the file block addresses to the address of the disk block (or possibly to the cylinder-head-sector).
Some operating systems require the user to allocate the maximum file size when a file is created. The file can then be allocated as an adjacent disk block. In this case, to convert the file block address to the disk block address, the operating system simply adds the file block address to the first disk block address that compiles the file. The scheme is simple, but the file can not exceed the size created.
Other operating systems allow files to grow. The resulting disk blocks may not be adjacent, thus mapping the logical blocks to more physically involved blocks.
MS-DOS, for example, uses a simple File Allocation Table (FAT). FAT has an entry for each disk block, and the entry identifies whether the block is used by the file and if so, which block (if any) is the next disk block of the same file. Thus, the allocation of each file is represented as a linked list in the table. To find the disk address of the block file , the operating system (or disk utility) must sequentially follow the linked list of files in FAT. Worse, to find free disk blocks, it has to sequentially scan FAT. For MS-DOS, it's not a big penalty because disks and small files and FATs have relatively few file entries and file chains. In the FAT12 file system (used on floppy disks and initial hard disks), there are no more than 4080 entries, and FAT will usually be stored in memory. As the disk gets larger, the FAT architecture begins to face punishment. On large disks using FAT, it may be necessary to perform a disk reading to study the disk location of the file block to read or write.
TOPS-20 (and possibly TENEX) uses a level 0 to 2 tree that is similar to the B-tree. The disk block is 512 36-bit words. If the file matches the word block 512 (2 9 ), then the file directory will point to that physical disk block. If the file corresponds to 2 18 , then the directory will point to the aux index; 512 words from that index would be NULL (block not allocated) or point to the physical address of the block. If the file corresponds to 2 27 words, the directory will point to the block holding the aux-aux index; each entry will be NULL or point to the aux index. As a result, physical disk blocks for word files 2 27 can be found in two disks read and read on all three.
The Apple HFS file system, Microsoft NTFS, AIX (jfs2) and some Linux filesystems, such as btrfs and Ext4, use B-tree.
B * -trees are used in HFS file systems and Reiser4.
The HAMMER file system of DragonFly BSD uses a modified B -ree.
Variations
Concurrency access
Lehman and Yao show that all read keys can be avoided (and thus concurrent access increases rapidly) by linking tree blocks at each level along with the "next" pointer. This produces a tree structure where both insertion and search operations descend from root to leaf. Write keys are only required when tree blocks are modified. This maximizes access concurrency by many users, an important consideration for other ISAM B-tree-based database and/or storage methods. The cost associated with this increase is that blank pages can not be removed from btree during normal operation. (However, look at strategies for implementing node integration, and source code in.)
United States Patent 5283894, granted in 1994, seems to show how to use the 'Meta Access Method' to allow access and modification of B trees simultaneously without a key. This technique accesses 'up' trees for searches and updates using an in-memory additional index that points to blocks at each level in the block cache. There is no reorganization to remove the necessary and no 'next' pointer in every block like in Lehman and Yao.
Etymology
Source of the article : Wikipedia