0

0

MySQL源码:索引相关的数据结构(前篇)_MySQL

php中文网

php中文网

发布时间:2016-06-01 13:13:52

|

1172人浏览过

|

来源于php中文网

原创

本文将尝试介绍mysql索引存储相关的数据结构。程序=数据结构+算法,了解数据结构,然后就可以进一步了解mysql源码中如何使用索引,如何选择自己的执行计划。

1. MYSQL如何描述某个数据表的索引

MySQL使用TABLE对象来描述一个数据表,那么数据表的索引是如何描述,索引的统计信息又是如何存储的呢? 例如我们有如下数据表:

CREATE TABLE `users` (`id` int(11) NOT NULL,`nick` varchar(32) DEFAULT NULL,`reg_date` datetime DEFAULT NULL,PRIMARY KEY (`id`),KEY `IND_NICK` (`nick`),KEY `IND_REGDATE` (`reg_date`))

CREATETABLE`users`(

`id`int(11)NOTNULL,

`nick`varchar(32)DEFAULTNULL,

`reg_date`datetimeDEFAULTNULL,

PRIMARYKEY(`id`),

KEY`IND_NICK`(`nick`),

KEY`IND_REGDATE`(`reg_date`)

)

该表有索引,PRIMARY KEY、IND_NICK、IND_REGDATE,我们来看看MySQL内部是如何存储这三个索引,以及如何使用这些索引的统计信息的。下图,描述了存储一个数据表索引的主要结构:

fff

  • MySQL使用TABLE对象描述一个数据表,他的成员key_info(类型为KEY)描述这个表的全部索引
  • key_info是一个数组,每一个元素是一个KEY(vim -t KEY查看)对象,代表了一个索引,顺序的,整个数组代表了这个表的全部索引
  • key_info(KEY对象)的成员key_part,是指向KEY_PART_INFO数组的指针,该数组描述了某个索引所有的索引列信息,数组的每个元素代表了一个索引列
  • 最后,key_part的成员field指向该索引列对应的数据表字段

2. GDB打印观察索引信息

2.1 打印索引基本信息

某个索引(例如IND_NICK)的基本信息是存储在KEY结构(table->key_info数组)中,这里,我们来打印索引IND_NICK的基本信息来观察KEY结构:

(gdb) p s->table->key_info[1]$26 = {key_length = 67, flags = 104, key_parts = 1, extra_length = 3, usable_key_parts = 1, block_size = 1024, algorithm = HA_KEY_ALG_UNDEF, {parser = 0x0, parser_name = 0x0}, key_part = 0x7f6514020860, name = 0x7f651401fc11 "IND_NICK", rec_per_key = 0x7f651401fa68, handler = {bdb_return_if_eq = 0}, table = 0x7f6514023d30}

(gdb)ps->table->key_info[1]

$26={key_length=67,flags=104,key_parts=1,

extra_length=3,

usable_key_parts=1,

block_size=1024,

algorithm=HA_KEY_ALG_UNDEF,

{parser=0x0,

parser_name=0x0

},

key_part=0x7f6514020860,

name=0x7f651401fc11"IND_NICK",

rec_per_key=0x7f651401fa68,

handler={

bdb_return_if_eq=0

},

table=0x7f6514023d30

}

key_length = 67: 表示这个索引入口长为67(不包括rowid),32*2 + 1(NULL) + VARCHAR变成信息

flags = 104 这是一个索引信息的标志位,存储了这个索引的一些重要属性,例如是不是唯一索引,索引中有没有变长字段,是不是一个全文索引等,104表示为二进制,即是1101000,也等于8+32+64,也就是HA_VAR_LENGTH_KEY|HA_BINARY_PACK_KEY|HA_NULL_PART_KEY

更多flags类型:

#define HA_NOSAME 1 /* Set if not dupplicated records */#define HA_PACK_KEY 2 /* Pack string key to previous key */#define HA_SPACE_PACK_USED 4 /* Test for if SPACE_PACK used */#define HA_VAR_LENGTH_KEY 8#define HA_AUTO_KEY 16#define HA_BINARY_PACK_KEY 32 /* Packing of all keys to prev key */#define HA_NULL_PART_KEY 64#define HA_FULLTEXT 128 /* For full-text search */#define HA_UNIQUE_CHECK 256 /* Check the key for uniqueness */#define HA_SPATIAL 1024 /* For spatial search */#define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */#define HA_GENERATED_KEY 8192 /* Automaticly generated key */key_part = 0x7f6514020860 这个指针指向一个KEY_PART_INFO数组,存储

#define HA_NOSAME 1 /* Set if not dupplicated records */

#define HA_PACK_KEY 2 /* Pack string key to previous key */

#define HA_SPACE_PACK_USED 4 /* Test for if SPACE_PACK used */

#define HA_VAR_LENGTH_KEY 8

#define HA_AUTO_KEY 16

#define HA_BINARY_PACK_KEY 32 /* Packing of all keys to prev key */

#define HA_NULL_PART_KEY 64

#define HA_FULLTEXT 128 /* For full-text search */

#define HA_UNIQUE_CHECK 256 /* Check the key for uniqueness */

#define HA_SPATIAL 1024 /* For spatial search */

#define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */

#define HA_GENERATED_KEY 8192 /* Automaticly generated key */

key_part=0x7f6514020860这个指针指向一个KEY_PART_INFO数组,存储

了索引各个列的信息。

2.2 打印索引某一列的基本信息

(gdb) p s->table->key_info[1]->key_part[0]$29 = {field = 0x7f6514020588, offset = 5, null_offset = 0, length = 64, store_length = 67, key_type = 32768, fieldnr = 2, key_part_flag = 24, type = 15 '/017', null_bit = 1 '/001'}

(gdb)ps->table->key_info[1]->key_part[0]

$29={

field=0x7f6514020588,

offset=5,null_offset=0,length=64,

store_length=67,

kgogoprime
kgogoprime

KGOGOMall 是一套采用 Php + MySql 开发的基于 WEB 应用的 B/S 架构的B2C网上商店系统。具有完善的商品管理、订单管理、销售统计、新闻管理、结算系统、税率系统、模板系统、搜索引擎优化,数据备份恢复,会员积分折扣功能,不同的会员有不同的折扣,支持多语言,模板和代码分离等,轻松创建属于自己的个性化用户界面。主要面向企业和大中型网商提供最佳保障,最大化满足客户目前及今后的独立

下载

key_type=32768,

fieldnr=2,

key_part_flag=24,

type=15'/017',

null_bit=1'/001'

}

field = 0x7f6514020588 指向这个索引列使用数据表的那一列

offset = 5 改索引列从索引串的第一个偏移开始

null_offset = 0 null信息存储偏移

length = 64, 索引串长度

store_length = 67, 整个索引入口长度

2.3 打印索引某列详情

(gdb) p *s->table->key_info[1]->key_part[0]->field$36 = {...table = 0x7f6514023d30, ...field_name = 0x7f651401fcf4 "nick", ...key_start = {map = 2}, part_of_key = {map = 2}, part_of_key_not_clustered = {map = 2}, part_of_sortkey = {map = 2}, ...}

(gdb)p *s->table->key_info[1]->key_part[0]->field

$36={...

table=0x7f6514023d30,

...

field_name=0x7f651401fcf4"nick",

...key_start={map=2},part_of_key={map=2},

part_of_key_not_clustered={

map=2},

part_of_sortkey={

map=2},...}

table = 0x7f6514023d30 指向该列所在的数据表

field_name = 0x7f651401fcf4 “nick” 列名

key_start = 2 包含这个字段且为索引第一个字段的索引编号,2的二进制是10,也就是第二索引以该字段为起始

3. MYSQL源码中如何使用索引信息

下面摘抄函数store_create_info(显示SHOW CREATE TABLE命令)显示索引信息部分的代码如下:

1351 for (uint i=0 ; i < share->keys ; i++,key_info++)1352 {1353 KEY_PART_INFO *key_part= key_info->key_part;...1357 if (i == primary_key && !strcmp(key_info->name, primary_key_name))1358 {1359 found_primary=1;1364 packet->append(STRING_WITH_LEN("PRIMARY KEY"));1365 }1366 else if (key_info->flags & HA_NOSAME)1367 packet->append(STRING_WITH_LEN("UNIQUE KEY "));...1372 else1373 packet->append(STRING_WITH_LEN("KEY "));...1380 for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)1381 {...1401 }1402 packet->append(')');1403 store_key_options(thd, packet, table, key_info);1404 if (key_info->parser)1405 {...1410 }1411 }

1351for(uinti=0;ikeys;i++,key_info++)

1352{

1353KEY_PART_INFO *key_part=key_info->key_part;

...

1357if(i==primary_key&&!strcmp(key_info->name,primary_key_name))

1358{

1359found_primary=1;

1364packet->append(STRING_WITH_LEN("PRIMARY KEY"));

1365}

1366elseif(key_info->flags&HA_NOSAME)

1367packet->append(STRING_WITH_LEN("UNIQUE KEY "));

...1372else

1373packet->append(STRING_WITH_LEN("KEY "));

...

1380for(uintj=0;jkey_parts;j++,key_part++)

1381{...1401}

1402packet->append(')');

1403store_key_options(thd,packet,table,key_info);

1404if(key_info->parser)

1405{...1410}1411}

小结:

(1) 可以看到MySQL如何遍历一个表的所有索引

key_info= table->key_info;for (uint i=0 ; i < share->keys ; i++,key_info++){...}

key_info=table->key_info;

for(uinti=0;ikeys;i++,key_info++)

{...}

(2) 可以看到MySQL如何根据key_info->flags字段如何区分唯一索引,全文索引等

(3) 可以看到MySQL如何遍历一个索引的所有字段:

KEY_PART_INFO *key_part= key_info->key_part;for (uint j=0 ; j < key_info->key_parts ; j++,key_part++){...}

KEY_PART_INFO *key_part=key_info->key_part;

for(uintj=0;jkey_parts;j++,key_part++)

{...}

(4) 查看完整的这个函数还可以看到MySQL如何读取数据表的各个column

文章来自:orczhou

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

616

2026.02.13

微博网页版主页入口与登录指南_官方网页端快速访问方法
微博网页版主页入口与登录指南_官方网页端快速访问方法

本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

194

2026.02.13

Flutter跨平台开发与状态管理实战
Flutter跨平台开发与状态管理实战

本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

91

2026.02.13

TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

20

2026.02.13

Redis高可用架构与分布式缓存实战
Redis高可用架构与分布式缓存实战

本专题围绕 Redis 在高并发系统中的应用展开,系统讲解主从复制、哨兵机制、Cluster 集群模式及数据分片原理。内容涵盖缓存穿透与雪崩解决方案、分布式锁实现、热点数据优化及持久化策略。通过真实业务场景演示,帮助开发者构建高可用、可扩展的分布式缓存系统。

54

2026.02.13

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

29

2026.02.12

雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法
雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法

本专题系统整理雨课堂网页版官方入口及在线登录方式,涵盖账号登录流程、官方直连入口及平台访问方法说明,帮助师生用户快速进入雨课堂在线教学平台,实现便捷、高效的课程学习与教学管理体验。

15

2026.02.12

豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法
豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法

本专题汇总豆包AI官方网页版入口及在线使用方式,涵盖智能写作工具、图片生成体验入口和官网登录方法,帮助用户快速直达豆包AI平台,高效完成文本创作与AI生图任务,实现便捷智能创作体验。

598

2026.02.12

PostgreSQL性能优化与索引调优实战
PostgreSQL性能优化与索引调优实战

本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

56

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
CSS3 教程
CSS3 教程

共18课时 | 5.8万人学习

PostgreSQL 教程
PostgreSQL 教程

共48课时 | 9.3万人学习

Django 教程
Django 教程

共28课时 | 4.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号