MySQL 哈希索引

哈希索引基于哈希表实现,适用于精确匹配查询。MySQL的Memory引擎支持哈希索引,它通过计算索引列的哈希码来快速定位数据行。哈希冲突可能导致链式存储或溢出桶,不支持排序和部分列匹配,仅限于等值查询。

哈希索引基于哈希表实现,只有精确匹配索引所有列的查询才有效。对于每一行数据,存储引擎都会对所有的索引列计算一个哈希码,哈希码是一个较小的值,并且不同键值计算出来的哈希码也不同。哈希索引将所有哈希码存放在索引中,同时在哈希表存放指向数据行的指针。

在哈希索引中,采用桶(bucket)来表示一条或多条记录的存储单元。令K表示搜索码的集合,B表示所有桶地址的集合。哈希函数h是一个从K中的找出B中的一个桶地址。

插入一条搜索码为的数据行,计算,得出一个哈希码,该哈希码能够索引到能够存放该数据行的桶的地址,如果桶不满。

搜索一条搜索码为的数据行,计算,得出一个哈希码,该哈希码能够索引该数据行所存放桶的地址。如果有两个搜索码和,它们计算的哈希码一致,如果该哈希码索引的桶能够存放这两个数据行,则在索引到的桶中查找和 。

在MySQL中,只有Memory引擎显示支持哈希索引,这也是Memory引擎搜索表的默认索引类型。

有如下表:

CREATE DATABASE Student;
CREATE TABLE Student
( 
  id    int      NOT NULL ,
  name  char(10) NOT NULL ,
  score float(1) NULL ,
  KEY USING HASH(id)
)ENGINE=MEMORY;

INSERT INTO Student 
(
  id,name,score
)
VALUES 
( 78, 'Crick',97.6 ),
( 125,'Katz', 85.3 ),
( 634,'Gold', 66.6 );
+-----+-------+-------+
| id  | name  | score |
+-----+-------+-------+
|  78 | Crick |  97.6 |
| 125 | Katz  |  85.3 |
| 634 | Gold  |  66.6 |
+-----+-------+-------+

主键id采用哈希索引的方式,因此假设进行对id计算后得到的hash code如下:

h(78)= 0;

h(125) = 2;

h(634) = 1;

采用哈希表的方式进行存储



如果此时插入一行且该主键的计算出的哈希码的值与前面的某行计算出的哈希

码一致,会产生哈希冲突。例如:

h(35) = 2


查询id=35的数据行,计算35的哈希码,根据哈希码索引出该数据行的指针,但是该哈希码对应的两个按照链式存储的数据行指针,还需要在该链上进行查找。

也可以采用桶进行存储,假设每个桶能存储三个数据行的指针,如果每个数据行的主键计算所得哈希码相同,存放在一个桶中。如果发生桶溢出,则会在该桶后面以链式进行链接一个溢出桶。溢出桶大小与刚才的桶一致。

哈希索引并不是按照索引值索引值顺序存储,所以也就无法用于排序。

哈希索引也不支持部分索引列匹配查找,因为哈希索引始终使用索引列的全部内容来计算哈希值的。

哈希索引只支持等值比较查询,包括=,IN,<=>,也不支持范围查询。

当出现哈希冲突时,存储引擎必须遍历链表所有数据行指针,逐行比较,直到找出符合条件的数据行。

如果哈希冲突很多,一些索引维护操作代价也很高。


<think> 我们之前已经详细讨论了哈希索引B+树索引的定义、特性及区别。现在用户进一步询问关于聚簇索引非聚簇索引的信息,并且参考了站内引用内容。根据引用[2],聚簇索引非聚簇索引与B+树索引密切相关,特别是在InnoDB存储引擎中。 用户的问题:我想了解MySQL哈希索引、B+树索引、聚簇索引非聚簇索引的相关信息 因此,我们需要在回答中涵盖以下内容: 1. 哈希索引(已介绍过,可简要回顾) 2. B+树索引(已介绍过,可简要回顾) 3. 聚簇索引(Clustered Index) 4. 非聚簇索引(Secondary Index,也称为辅助索引或二级索引) 根据引用[2]:每个InnoDB表都有一个聚簇索引,聚簇索引使用B+树构建,叶子节点存储整行记录。聚簇索引一般等同于主键索引,如果没有主键,则InnoDB会自动创建一个ROWID来构建。 同时,非聚簇索引(二级索引)也是使用B+树,但其叶子节点存储的是主键值(而不是整行数据),因此通过二级索引查询数据需要回表操作。 回答结构建议: 1. 先简要回顾哈希索引B+树索引(因为之前已经详细讨论,这里可以简洁) 2. 重点介绍聚簇索引非聚簇索引 - 定义 - 结构(结合B+树) - 区别(存储内容、查询过程等) 3. 给出示例(建表语句等) 4. 对比总结 另外,注意系统指令要求: - 行内数学表达式用$...$ - 独立公式用$$...$$并单独成段 - 使用中文 - 生成相关问题 - 引用标识自然添加 同时,由于用户的问题中引用了站内内容,我们应在适当的地方标注引用,如[^2]提到聚簇索引的定义。 注意:哈希索引在InnoDB中默认是不直接支持的(除了自适应哈希索引),而MEMORY引擎支持显式哈希索引。聚簇索引非聚簇索引则是InnoDB中基于B+树实现的两种索引组织方式。 我们开始组织回答: </think> ### MySQL索引深度解析:哈希索引、B+树索引、聚簇索引与非聚簇索引 #### 1. **哈希索引(Hash Index)** 基于哈希表实现,通过哈希函数将键值映射到固定大小的桶中。**核心特性**: - **查询类型**:仅支持精确匹配(`=`,`IN`),不支持范围查询或排序[^1][^3] - **时间复杂度**:$O(1)$ 的等值查询效率 - **存储结构**: ```mermaid graph LR A[键值] --> B(哈希函数) B --> C[桶地址] C --> D[数据行指针] ``` - **局限性**: - 哈希冲突需链表解决,高冲突率时性能下降 - **InnoDB的自适应哈希索引**仅自动为高频访问数据创建[^1] #### 2. **B+树索引(B+ Tree Index)** 多路平衡搜索树,MySQL默认索引结构。**核心特性**: - **查询支持**:等值、范围查询(`>`,`<`)、排序(`ORDER BY`)、前缀匹配 - **时间复杂度**:$O(\log n)$ - **结构设计**: - **叶子节点**:存储完整数据(聚簇索引)或主键值(非聚簇索引) - **非叶子节点**:仅存键值子节点指针 - **有序链表**:叶子节点双向链接,加速范围扫描[^2][^3] - **数学原理**: 设分支因子为$b$,树高为$h$,数据量上限满足: $$n \leq (b-1)(b^{h+1}-1)/(b-1)$$ #### 3. **聚簇索引(Clustered Index)** - **定义**:数据行物理存储顺序与索引顺序一致 - **实现方式**: - InnoDB默认用**主键**构建B+树 - 无主键时自动生成`ROWID`作为聚簇索引[^2] - **存储特性**: - **叶子节点直接存储行数据** - 每表仅有一个聚簇索引 - **优势**: - 范围查询高效(物理连续存储) - 避免"回表"操作(数据与索引同位置) #### 4. **非聚簇索引(Secondary Index)** - **定义**:索引顺序独立于数据物理存储 - **实现方式**: - B+树叶子节点存储**主键值**而非行数据 - 通过主键二次查找数据(**回表**) - **示例**: ```sql CREATE TABLE users ( id INT PRIMARY KEY, -- 聚簇索引(主键) email VARCHAR(255), INDEX idx_email (email) -- 非聚簇索引(二级索引) ); ``` 查询`SELECT * FROM users WHERE email='a@b.com'`需: ```mermaid graph LR A[通过idx_email定位主键] --> B[通过主键回表查行数据] ``` --- ### 核心对比总结 | **索引类型** | 数据结构 | 存储内容 | 查询特性 | |----------------|------------|----------------------|-----------------------------| | **哈希索引** | 哈希表 | 数据行指针 | 仅精确匹配 | | **B+树索引** | 多路平衡树 | 键值+指针/数据 | 支持所有查询类型 | | **聚簇索引** | B+树 | 数据行 | 避免回表,范围查询高效 | | **非聚簇索引** | B+树 | 主键值 | 需回表,适合点查过滤 | --- ### 工程实践示例 **场景优化**:高频等值查询(如会话管理) ```sql -- 使用MEMORY引擎哈希索引加速精确匹配 CREATE TABLE user_sessions ( session_id CHAR(32) PRIMARY KEY USING HASH, user_data JSON ) ENGINE=MEMORY; ``` **复合索引设计**(B+树非聚簇索引): ```sql -- 联合索引避免回表(覆盖索引) CREATE TABLE orders ( id INT PRIMARY KEY, user_id INT, status ENUM('paid','pending'), INDEX idx_user_status (user_id, status) -- 直接包含查询字段 ); ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值