Skip to content

达梦数据库索引类型:不止 B+ 树

提到数据库索引,你脑子里是不是立刻浮现出 B+ 树?

但如果你只了解 B+ 树,那你对达梦数据库的索引体系只了解了一半

达梦支持多种索引类型,每种都有它的用武之地。选错索引类型,就像用螺丝刀拧螺丝——能用,但费劲。

B 树索引:老牌劲旅

达梦的默认索引类型,与 MySQL、Oracle 类似,采用 B+ 树结构。

sql
-- 单列索引
CREATE INDEX idx_name ON employee(name);

-- 复合索引(最左前缀原则)
CREATE INDEX idx_dept_salary ON employee(dept_id, salary);

-- 唯一索引
CREATE UNIQUE INDEX idx_emp_no ON employee(emp_no);

B 树索引的适用场景:

  • 等值查询(WHERE name = '张三'
  • 范围查询(WHERE salary BETWEEN 5000 AND 10000
  • 排序操作(ORDER BY name
  • 前缀匹配(WHERE name LIKE '张%'

B 树索引的底层结构:

B+ 树是一种多路平衡查找树,叶子节点存储所有数据(或者指向数据的指针),非叶子节点只存储索引键。树的高度通常控制在 3-4 层,这意味着查询最多只需 3-4 次 I/O。

java
// B 树索引查询的 Java 模拟
public class BTreeIndexSearch {

    /**
     * 模拟 B 树索引的查找过程
     * 实际上,数据库会沿着根节点 -> 非叶子节点 -> 叶子节点的路径查找
     */
    public Integer search(int targetKey, List<Integer> indexKeys) {
        // 第一层:根节点查找,确定目标在哪个子树
        int node = findRootNode(targetKey, indexKeys);

        // 第二层:叶子节点查找
        // 实际数据库中,叶子节点之间有双向链表,便于范围扫描
        return binarySearch(node, targetKey);
    }
}

HASH 索引:等值查询的火箭

HASH 索引通过哈希函数直接定位数据,理论时间复杂度是 O(1)。

sql
-- 创建 HASH 索引
CREATE INDEX idx_session ON user_session(session_token) USING HASH;

HASH 索引的适用场景:

  • 等值查询:如 WHERE session_token = 'abc123'
  • 唯一性校验:适合高选择性的列
  • 内存数据库:In-Memory HASH 索引查询速度极快

HASH 索引的致命弱点:

  1. 不支持范围查询WHERE id > 100 无法使用 HASH 索引
  2. 不支持排序:无法用于 ORDER BY 操作
  3. 哈希冲突:极端情况下性能会退化

位图索引:枚举类型的杀手锏

达梦支持位图索引(Bitmap Index),特别适合低基数列(枚举值少)。

sql
-- 为性别、状态等低基数列创建位图索引
CREATE BITMAP INDEX idx_gender ON employee(gender);
CREATE BITMAP INDEX idx_status ON order_header(status);

位图索引的工作原理:

假设有 100 万条员工记录,其中 gender 只有两个值:男、女。

男:0 1 0 0 1 1 0 ... (0 表示女,1 表示男)
女:1 0 1 1 0 0 1 ... (与男相反)

每个值对应一个位图,查询时直接用位运算:

java
// 位图索引的 AND 运算模拟
public class BitmapIndexExample {

    // 模拟位图:假设 8 条记录
    int[] maleBitmap = {0b01001100};   // 男员工位图
    int[] activeBitmap = {0b10101010}; // 在职员工位图

    // 查询:在职男员工
    // 男性 AND 在职 = 01001100 & 10101010 = 00001000
    public int[] andOperation(int[] bitmap1, int[] bitmap2) {
        int[] result = new int[bitmap1.length];
        for (int i = 0; i < bitmap1.length; i++) {
            result[i] = bitmap1[i] & bitmap2[i];
        }
        return result;
        // 结果位图中为 1 的位置,就是符合条件的记录
    }
}

位图索引的适用场景:

  • 枚举类型列(性别、状态、类别)
  • 多条件组合查询(位运算极快)
  • 数据仓库的 OLAP 场景

位图索引的问题:

  • 更新代价高:插入/删除一条记录需要更新多个位图
  • 不适合高并发写入的 OLTP 系统

函数索引:让计算结果可索引

有时候需要索引的不是列本身,而是计算结果

sql
-- 索引 email 列的大写形式(忽略大小写的查询)
CREATE INDEX idx_email_upper ON employee(UPPER(email));

-- 索引日期的年份(按年份查询时高效)
CREATE INDEX idx_year ON orders(YEAR(order_date));

-- 表达式索引
CREATE INDEX idx_total ON order_detail(quantity * unit_price);
java
// 函数索引的使用示例
public class FunctionIndexUsage {

    // 查询时自动使用函数索引
    public void queryExample() {
        String sql = "SELECT * FROM employee WHERE UPPER(email) = 'ZHANG@EXAMPLE.COM'";
        // Oracle、达梦等会使用 idx_email_upper 索引
        // 普通 B 树索引无法用于 UPPER(column) 的查询
    }
}

索引类型选择指南

索引类型适用场景不适用场景
B 树索引等值、范围、排序、前缀匹配枚举类、低选择率列
HASH 索引等值查询、高性能内存数据库范围查询、排序
位图索引枚举列、组合查询、OLAP高并发写入、基数高
函数索引计算列查询、大小写不敏感查询普通查询

面试追问方向

  • 什么情况下复合索引会失效?达梦的复合索引有什么特点?
  • 位图索引在高并发写入场景下会有什么问题?如何解决?

一句话总结

索引不是越多越好,也不是只有 B+ 树。选对索引类型,等值查询用 HASH、枚举查询用位图、表达式查询用函数——让每一分索引都花在刀刃上。

基于 VitePress 构建