首页 > 数据库 >【SQL】选择⽤ B+ 树,⽽不是普通⼆叉树的原因

【SQL】选择⽤ B+ 树,⽽不是普通⼆叉树的原因

时间:2024-07-08 13:56:07浏览次数:16  
标签:search int public 选择 普通 key SQL root 节点

使用 B+ 树而不是普通二叉树(BST)有几个关键的原因,特别是在数据库和文件系统中,B+ 树的设计更适合高效的数据存储和检索。以下是一些主要原因:

1. 磁盘I/O效率

B+ 树的节点包含多个键和指针,使其高度比普通二叉树更低。这意味着在查找某个键时,需要访问的节点数量更少,从而减少了磁盘I/O操作。磁盘I/O操作的成本非常高,因此减少I/O操作能显著提高性能。

2. 减少树的高度

B+ 树是多路平衡树,每个节点可以有多个子节点,而不仅仅是两个子节点。这样,B+ 树的高度比普通二叉树要低得多。在数据库中,树的高度通常是3到4层,这意味着大部分查询只需要3到4次磁盘I/O操作。

3. 叶节点链表

B+ 树的所有实际数据都存储在叶节点中,并且所有叶节点通过链表链接。这使得B+ 树在范围查询和顺序访问时非常高效,因为只需要顺序遍历叶节点即可。

4. 缓存友好

由于B+ 树的节点大小通常与磁盘块大小一致,一次读取一个节点的数据就可以利用磁盘块的全部空间,这样可以有效地利用磁盘读取的数据,并减少不必要的磁盘访问。

5. 平衡特性

B+ 树是一棵自平衡的树,确保所有叶节点在同一层。这意味着插入、删除操作后,树的高度几乎保持不变,从而保持了高效的查询性能。

6. 索引效率

B+ 树的内部节点只包含键(不包含实际数据),而叶节点包含实际数据。这使得内部节点非常紧凑,可以在一个节点中存储更多的键,从而减少树的高度。

示例对比

假设有一个包含1000个元素的集合:

  • 二叉搜索树(BST)

    • 最坏情况下,如果BST退化成链表,查找某个元素需要最多1000次比较。
    • 平衡的BST,查找某个元素需要约 log2(1000) ≈ 10 次比较。
  • B+ 树(假设每个节点有100个子节点)

    • 查找某个元素需要最多 log100(1000) ≈ 2 次比较。
    • 实际情况下,由于每个节点包含多个键,比较次数会稍多,但仍显著少于BST。

示例代码:模拟B+树和BST的查找效率

以下是一个简单的Java示例,展示了B+树和BST的查找操作:

import java.util.*;

class BTreeNode {
    int[] keys;
    BTreeNode[] children;
    boolean isLeaf;
    int n;

    public BTreeNode(int t, boolean leaf) {
        this.isLeaf = leaf;
        this.keys = new int[2 * t - 1];
        this.children = new BTreeNode[2 * t];
        this.n = 0;
    }

    public void traverse() {
        for (int i = 0; i < this.n; i++) {
            if (!this.isLeaf) {
                this.children[i].traverse();
            }
            System.out.print(" " + this.keys[i]);
        }
        if (!this.isLeaf) {
            this.children[this.n].traverse();
        }
    }

    public BTreeNode search(int k) {
        int i = 0;
        while (i < this.n && k > this.keys[i]) {
            i++;
        }
        if (this.keys[i] == k) {
            return this;
        }
        if (this.isLeaf) {
            return null;
        }
        return this.children[i].search(k);
    }
}

class BTree {
    BTreeNode root;
    int t;

    public BTree(int t) {
        this.root = null;
        this.t = t;
    }

    public void traverse() {
        if (this.root != null) {
            this.root.traverse();
        }
    }

    public BTreeNode search(int k) {
        if (this.root == null) {
            return null;
        } else {
            return this.root.search(k);
        }
    }
}

class BSTNode {
    int key;
    BSTNode left, right;

    public BSTNode(int item) {
        this.key = item;
        this.left = this.right = null;
    }
}

class BinaryTree {
    BSTNode root;

    public BinaryTree() {
        this.root = null;
    }

    public BSTNode search(BSTNode root, int key) {
        if (root == null || root.key == key) {
            return root;
        }
        if (root.key > key) {
            return search(root.left, key);
        }
        return search(root.right, key);
    }
}

public class TreeExample {
    public static void main(String[] args) {
        int[] keys = {10, 20, 5, 6, 12, 30, 7, 17};

        BTree bTree = new BTree(3); // B+ tree with minimum degree 3
        BinaryTree binaryTree = new BinaryTree();

        for (int key : keys) {
            // Insertions (pseudo-code, actual insertion logic is omitted)
            // bTree.insert(key);
            // binaryTree.insert(key);
        }

        int searchKey = 6;
        // B+ tree search
        BTreeNode result = bTree.search(searchKey);
        System.out.println("B+ Tree Search Result: " + (result != null ? "Found" : "Not Found"));

        // Binary search tree search
        BSTNode bstResult = binaryTree.search(binaryTree.root, searchKey);
        System.out.println("Binary Tree Search Result: " + (bstResult != null ? "Found" : "Not Found"));
    }
}

总结

B+ 树相比普通二叉树在磁盘I/O效率、范围查询、顺序访问等方面有显著优势,因此在数据库和文件系统中广泛使用。B+ 树的设计使其非常适合处理大量数据的高效存储和检索。

标签:search,int,public,选择,普通,key,SQL,root,节点
From: https://blog.csdn.net/hui_zai_/article/details/139869520

相关文章

  • DDP:微软提出动态detection head选择,适配计算资源有限场景 | CVPR 2022
    DPP能够对目标检测proposal进行非统一处理,根据proposal选择不同复杂度的算子,加速整体推理过程。从实验结果来看,效果非常不错来源:晓飞的算法工程笔记公众号论文:ShouldAllProposalsbeTreatedEquallyinObjectDetection?论文地址:https://arxiv.org/abs/2207.03520......
  • MySQl数据库课程设计 学生宿舍管理系统
    表的创建(1)createtabledormitory( #宿舍信息表  dormitory_idvarchar(15)notnull,#宿舍号    capacityint,#宿舍人数    bed_idint,#床号    student_namevarchar(20),#姓名    student_sexvarchar(5)#性别);(2)createtablesug......
  • Oracle PL/SQL 循环批量执行存储过程
    1.查询存储过程        根据数据字典USER_OBJECTS查询出所有存储过程。2.动态拼接字符串(参数等)    根据数据字典USER_ARGUMENTS动态拼接参数。3.动态执行    利用EXECUTEIMMEDIATE动态执行无名块。4.输出执行信息    利用DBMS_OUT......
  • Mysql数据同步ES的4种方式
    1、同步双写 通过应用服务,直接为数据库及ES写如数据。 优点:业务逻辑简单;实时性高缺点:业务耦合,耦合大量数据同步代码硬编码,有需要写入MySQL的地方都需要添加写入ES的代码;影响性能,写入两个存储,响应时间变长不便扩展:搜索可能有一些个性化需求,需要对数据进行聚合,这......
  • windows mysql执行sql文件
    背景快速导入数据表或者数据库。解决直接执行sql文件。虽然直接复制内容也行,但是还是执行文件更好一些。登录mysql-uroot-p-Dxxx-D指定数据库的名称。如果不写,可以在进入mysql命令行后,使用usexxx来使用数据库。执行sourcexxx.sql特别注意,哪怕路径里有空......
  • Spring Boot3整合Mybatis Plus,数据库为MySQL
    项目结构如下:注意不需要任何XML文件1.导入依赖除了SpringBoot创建时自带的依赖,还需要加入:<!--MybatisPlus依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><version>3.5.7</version&g......
  • 插入记录(二)(sql练习)
    现有一张试卷作答记录表exam_record,结构如下表,其中包含多年来的用户作答试卷记录,由于数据越来越多,维护难度越来越大,需要对数据表内容做精简,历史数据做备份。表exam_record:FiledTypeNullKeyExtraDefaultCommentidint(11)NOPRIauto_increment(NULL)自增IDuidint(11)NO(NULL)用......
  • sql 索引
    SQL中的索引分为两种,一种为聚集索引和非聚集索引,下面介绍两者的异同。一、聚集索引与非聚集索引:1、聚集索引:聚集索引的意思可以理解为顺序排列,比如一个主键自增的表即为聚集索引,即id为1的存在于第一条,id为2的存在于第二条...假使数据库中是使用数组来存放的这张表中的数据,那么......
  • Spark_06 SparkSQL补充知识点
    说明:本章主要分享Spark自定义函数的使用,catalyst以及sparksql与hive的联动自定义函数分类UDF:一对一关系,输出一行数据得到一行结果,可以自定义UDAF:聚合函数,多对一关系,输入多行数据经过函数以后输出一行计算结果,通常与groupBy联合使用UDTF:一对多的关系,输入一行数据经过函......
  • NoSQL之Redis集群
    目录1.Redis主从复制(1)Redis主从复制工作原理(2)搭建Redis主从复制2.Redis哨兵模式(1)Redis哨兵工作原理(2)搭建Redis哨兵模式3.Redis集群模式(1)集群模式的工作原理(2)集群模式的特点(3)搭建Redis群集模式(4)集群模式与哨兵模式的主要区别1.Redis主从复制(1)Redis主从复制工作原理1.......