MySQL内置结构hash表的使用

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介:

最近实现的两个patch都使用到了MySQL内置的hash结构。这个结构在MySQL框架层中被多处使用,理解它可以方便代码阅读。

1、 总体

InnoDB中也有自带的HASH表, 本文中介绍的是MySQL框架层的hash表。 其定义的头文件在include/hash.h,实现位置mysys/hash.c。内部存储数据使用了动态数组DYNAMIC_ARRAY。

这个hash表实现了插入、删除、修改、查找接口,也提供了遍历接口。在打patch时会发现很好用。

2、初始化 _my_hash_init

a) 声明

参数表

说明

HASH *hash

欲初始化的hash表地址

uint growth_size

Hash表空间不够时再次申请的个数

CHARSET_INFO *charset

系统字符集

ulong default_array_elements

初始容量

size_t key_offset

Key在data中的偏移量

size_t key_length

Key的长度

my_hash_get_key get_key

获取key的回调函数

void (*free_element)(void*)

析构回调

uint flags

hash表类型

b) 说明:1) 调用时growth_size一般取值为0,内部会根据初始值和每个HASH_LINK大小得到一个合理的值(./mysys/array.c), sizeof(HASH_LINK)=sizeof(int)+sizeof(char*);

2)hash表类型目前只有0和1(HASH_UNIQUE), 为1表示key值不允许重复;

3) 析够回调中,对于传入的元素指针,需要自定义一个合适的删除方法。

4)特别说明typedef uchar *(*my_hash_get_key)(const uchar *,size_t*,my_bool)。 若该回调函数不为NULL, 则通过该函数的size_t*传出key的长度, 返回值为key在data中的起始地址; 若为NULL,则偏移量为key_offset,key长度为key_length。

从init的声明中可以看到,这个hash表中存的是全数据(data), 也包含了key的内容。Key作为data的一部分,通过my_hash_get_key告诉hash表key的获取方式(当然获取到key之后,最终还是签名后决定hash位置)。

3、插入元素 my_hash_insert

a) 声明

参数表

说明

HASH *info

hash表地址

const uchar *data

插入的数据地址

b)说明: 1)可以看到,插入的参数只有一个datakey的获取方式即为init时指定的my_hash_get_key或 key_offset& key_length;

2) 需要注意,hash中存的只是data的地址,因此data不能为栈变量。且需要在free_element中自定义删除方法。

3)返回值为TRUE时,表示插入失败,为0时表示插入成功。

4、查找元素 my_hash_search

a) 声明

参数表

说明

const HASH *info

hash表地址

const uchar *key

查找的key

size_t length

Key长度

b)说明: 1)返回值为查找到的data的地址,若查找不到,返回NULL

2)由于直接返回data的地址,因此如果要修改data中的key字段,可以直接指针操作。

5、删除/修改元素

a) 删除my_hash_delete

参数表

说明

const HASH *info

hash表地址

const uchar *data

删除的数据地址

说明: 1)注意这里是按照地址比较的,非key

b) 修改my_hash_update

参数表

说明

const HASH *info

hash表地址

const uchar *data

修改的数据地址

uchar *old_key

原key

size_t old_key_length

原key长度

说明: 1)该函数的功能是,当data内容有涉及到key的修改时,修改key,及其在hash表的位置。 效果上等效于delete+insert,但效率更高。

6、遍历

遍历功能使得这个数据结构非常好用。看下面的代码就知道用法了。

for(i=0; i<my_hash->records; i++)
{
    hash_item= (hash_item_t*)my_hash_element(my_hash, i);
}

说明:其中hash_item_thash表中的元素――我们自定义的类型。

7、一个例子

用一个例子来简要说明用法,只需要演示init部分就可以了。

初始化语句

hash_init(&table_hash, &my_charset_bin, MAX_RECORD_NUM+16, 0, 0, hash_item_get_key, (hash_free_key)hash_item_free_entry, MYF(0));


说明:MySQL代码中多使用这个宏,其中growth_size在替换中默认使用0;


typedef struct st_hash_item
{
    int value;
    int key_len;
    char key[2*NAME_CHAR_LEN+1];
}hash_item_t;

uchar *hash_item_get_key(const uchar *record, size_t *length, my_bool not_used __attribute__((unused)))
{ 
  hash_item_t *entry= (hash_item_t*) record;
  *length= entry->key_len;
  return (uchar*) entry->key;
}

static void hash_item_free_entry(hash_item_t* record)
{
    delete record;
    DBUG_VOID_RETURN;
}

说明:1)我们使用字符串的key,因此在hash_item_t中有key_lenkey[]。配合hash_item_get_key提供根据输入的data,获取key_lenkey的方法。

2)由于inserthash表的数据是通过new hash_item_t的方法得到的,因此在free_entry中直接使用delete回收。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2月前
|
存储 关系型数据库 MySQL
阿里面试:为什么要索引?什么是MySQL索引?底层结构是什么?
尼恩是一位资深架构师,他在自己的读者交流群中分享了关于MySQL索引的重要知识点。索引是帮助MySQL高效获取数据的数据结构,主要作用包括显著提升查询速度、降低磁盘I/O次数、优化排序与分组操作以及提升复杂查询的性能。MySQL支持多种索引类型,如主键索引、唯一索引、普通索引、全文索引和空间数据索引。索引的底层数据结构主要是B+树,它能够有效支持范围查询和顺序遍历,同时保持高效的插入、删除和查找性能。尼恩还强调了索引的优缺点,并提供了多个面试题及其解答,帮助读者在面试中脱颖而出。相关资料可在公众号【技术自由圈】获取。
|
6月前
|
关系型数据库 MySQL 数据库
数据迁移脚本优化过程:从 MySQL 到 Django 模型表
在大规模的数据迁移过程中,性能问题往往是开发者面临的主要挑战之一。本文将分析一个数据迁移脚本的优化过程,展示如何从 MySQL 数据库迁移数据到 Django 模型表,并探讨优化前后的性能差异。
|
1月前
|
JSON 关系型数据库 MySQL
MySQL JSON数据存储结构与操作
通过本文的介绍,我们了解了MySQL中JSON数据类型的基本操作、常用JSON函数、以及如何通过索引和优化来提高查询性能。JSON数据类型为存储和操作结构化数据提供了灵活性和便利性,在现代数据库应用中具有广泛的应用前景。希望本文对您在MySQL中使用JSON数据类型有所帮助。
57 0
|
5月前
|
SQL 关系型数据库 MySQL
Mysql:如何自定义导出表结构
通过以上方法,你可以灵活地自定义导出MySQL中的表结构,以满足不同的需求和场景。在进行操作的时候要注意权限问题以及路径问题,确保MySQL用户有权限写入指定的文件路径。在执行导出任务之前,还应确保你对数据库及其内容有足够的了解,以避免不必要的数据丢失或损坏。
88 1
|
5月前
|
SQL 关系型数据库 MySQL
实时计算 Flink版产品使用问题之要将MySQL同步到Doris,并设置整库同步,只变更库名、表名和表结构都不变,该如何设置
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
5月前
|
存储 SQL 关系型数据库
MySQL设计规约问题之在数据库设计中,为什么要适当考虑反范式的表设计
MySQL设计规约问题之在数据库设计中,为什么要适当考虑反范式的表设计
|
5月前
|
SQL 存储 数据库
MySQL设计规约问题之如何处理日志类型的表
MySQL设计规约问题之如何处理日志类型的表
|
5月前
|
运维 关系型数据库 MySQL
实时计算 Flink版产品使用问题之在处理MySQL表新增数据记录时,没有正确触发变更事件,该如何解决
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
6月前
|
SQL 关系型数据库 MySQL
ClickHouse(23)ClickHouse集成Mysql表引擎详细解析
ClickHouse的MySQL引擎允许执行`SELECT`查询从远程MySQL服务器。使用`MySQL(&#39;host:port&#39;, &#39;database&#39;, &#39;table&#39;, &#39;user&#39;, &#39;password&#39;[,...])`格式连接,支持简单`WHERE`子句在MySQL端处理,复杂条件和`LIMIT`在ClickHouse端执行。不支持`NULL`值,用默认值替换。系列文章涵盖ClickHouse安装、集群搭建、表引擎解析等主题。[链接](https://zhangfeidezhu.com/?p=468)有更多
270 0
|
6月前
|
SQL 缓存 关系型数据库
MySQL操作全攻略:库、表、数据、事务全面指南
MySQL操作全攻略:库、表、数据、事务全面指南