《MySQL系列-InnoDB引擎36》索引与算法-哈希算法

哈希算法

哈希算法是一种常见算法,时间复杂度为O(1),且不只存在于索引中,每个数据库应用都存在该数据结构。设想一个问题,当前服务器内存为128GB时,用户怎么从内存中得到某一个被缓存的页呢?虽然内存查询速度很快,但是也不可能每次都要遍历所有内存来进行查找,这时对于字典操作只需O(1)的哈希算法就有了用武之地。

1 哈希表

哈希表也称散列表,由直接寻址表改进而来。在哈希方式下,该元素处于h(k)中,即利用哈希函数h,根据关键字k计算出槽的位置。哈希函数h必须可以很好的进行散列。最好的情况是能避免碰撞的发生。即使不能避免,也应该使碰撞在最小程度下产生。一般来说,都将关键字换成自然数,然后通过触发散列、乘法散列或全域散列来实现。数据库中一般采用除法散列的方法。

在哈希函数的除法散列法中,通过取k除以m的余数,将关键字k映射到m个槽的某一个去,即哈希函数为:

h(k) = k mod m

2 InnoDB存储引擎中的哈希算法

InnoDB存储引擎使用哈希算法来对字典进行查找,其冲突机制采用链表方式,哈希函数采用散列方式。对于缓冲池页的哈希表来说,在缓冲池中的Page页都有一个chain指针,它指向相同哈希函数值的页。而对于除法散列,m的取值为略大于2倍的缓冲池页数量的质数。例如:当前参数innodb_buffer_pool_size的大小为10M,则共有640个16KB的页。对于缓冲池页内存的哈希表来说,需要分配640*2=1280个槽,但是由于1280不是质数,需要取比1280略大的一个质数,应是1399,所以在启动时会分配1399个槽的哈希表,用来哈希查询所在缓冲池中的页。

那么InnoDB存储引擎的缓冲池对于其中的页是怎么进行查找的呢?上面只是给出一般算法,怎么将要查找的页转换成自然数呢?

其实页很简单,InnoDB存储引擎的表空间都有一个space_id,用户所需要查询的应该是某表空间的某个连续16KB的页,即偏移量offset。InnoDB存储引擎将space_id左移20位,然后加上这个space_id和offset,即关键字

K = space_id << 20 + space_id + offset,然后通过除法散列到各个槽中。

3 自适应哈希索引

自适应哈希索引采用之前讨论的哈希表的方式实现。不同的是,这仅是数据库自身创建并使用的,DBA本身不能对其干预。自适应哈希索引哈希函数映射到一个哈希表中,因此对于字典类型的查找非常快速,如select * from table where a = xx;。但是对于范围查询不太友好。

由于自适应哈希索引是由InnoDB存储引擎自己控制的,因此这里的这些信息只供参考。不过可以通过参数innodb_adaptive_hash_index来禁用或启动此特性,默认为开启。

mysql> show variables like 'innodb_adaptive_hash_index';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| innodb_adaptive_hash_index | ON    |
+----------------------------+-------+
1 row in set (0.00 sec)

猜你喜欢

转载自blog.csdn.net/m0_51197424/article/details/129778525
今日推荐