MySQL:索引与算法(自适应哈希索引)
asds哈希算法是一种常见算法,时间复杂度为O(1), 且不只存在于索引中,每个数据库应用中都存在该数据库结构。设想一个问题,当前服务器的内存为128GB 时,用户怎么从内存中得到某一个被缓存的页呢?虽然内存中查询速度很快,但是也不可能每次都要遍历所有内存来进行查找,这时对于字典操作只需O(1) 的哈希算法就有了很好的用武之地。asdsadasdasdasdsadasdasdasdsadassda
asds哈希算法是一种常见算法,时间复杂度为O(1), 且不只存在于索引中,每个数据库应用中都存在该数据库结构。设想一个问题,当前服务器的内存为128GB 时,用户怎么从内存中得到某一个被缓存的页呢? 虽然内存中查询速度很快,但是也不可能每次都要遍历所有内存来进行查找,这时对于字典操作只需O(1) 的哈希算法就有了很好的用武之地。
asdsadasdasdasdsadasdasdasdsadassdasdsadasdasdsadasdsadassadasdas————《MySQL技术内幕INNODB存储引擎》
哈希算法
哈希表
ssdss 哈希表(Hash Table) 也称散列表,由 直接寻址表 改进而来。
aassa直接寻址表:用一个数组(即直接寻址表) T [O … m-1] 表示动态集合,其中每个位置(或称槽或桶)对应全域U 中的一个关键字。槽K 指向集合中一个关键字为K 的元素。如果该集合中没有关键字为K 的元素,则T [k] =NULL 。
sdssa直接寻址技术存在一个很明显的问题:
ssdsssa如果域U 很大,在一台典型计算机的可用容量的限制下,要在机器中存储大小为U 的一张表T 就有点不实际,甚至是不可能的。如果实际要存储的关键字集合K 相对于U 来说很小,那么分配给T 的大部分空间都要浪费掉。
ssdsssa改进:哈希表出现了。在哈希方式下,该元素处于 h(k) 中,即利用哈希函数h,根据关键字k 计算出槽的位置。函数h 将关键字域U 映射到哈希表T [O … m-1] 的槽位。哈希表技术很好地解决了直接寻址遇到的问题,但是这样做有一个小问题,如两个关键字可能映射到同一个槽上。一般将这种情况称之为发生了碰撞(collision) 。在数据库中一般采用最简单的碰撞解决技术,这种技术被称为链接法。
ssdsssa哈希函数:必须可以很好地进行散列,一般采用除法散列的方法。h(k) = k mod m
lnnoDB 存储引擎中的哈希算法
ssdss InnoDB 存储引擎使用哈希算法来对字典进行查找,其冲突机制采用链表方式,哈希函数采用除法散列方式。对于缓冲池页的哈希表来说,在缓冲池中的Page 页都有一个chain 指针,它指向相同哈希函数值的页(相当于碰撞后的链表)。
aassa对于缓冲池页的哈希表来说,在缓冲池中的Page 页都有一个 chain 指针,它指向相同哈希函数值的页。而对于除法散列, m 的取值为略大于2 倍的缓冲池页数最的质数。
aassaeg:当前参数innodb_ buffer_pool_ size 的大小为 l0M, 则共有640 个16KB 的页。对于缓冲池页内存的哈希表来说,需要分配640X2=1280 (因640*16=10240)个槽,但是由于1280 不是质数,需要取比1280 略大的一个质数,应该是1399, 所以在启动时会分配1399 个槽的哈希表,用来哈希查询所在缓冲池中的页。
aassaInnoDB 存储引擎的缓冲池对于其中的页是怎么进行查找的呢?上面只是给出了一般的算法,怎么将要查找的页转换成自然数呢?
aassa答:InnoDB 存储引擎的表空间都有一个space_id, 用户所要查询的应该是某个表空间的某个连续16KB 的页,即偏移量offset 。InnoDB 存储引擎将space_id 左移20 位,然后加上这个space_id 和offset,然后通过除法散列到各个槽中去。
自适应哈希索引
ssdss 自适应哈希索引采用之前讨论的哈希表的方式实现。不同的是,这仅是数据库自身创建并使用的, DBA 本身并不能对其进行干预。自适应哈希索引经哈希函数映射到一个哈希表中,因此对于字典类型的查找非常快速.
aassa注:哈希索引只能用来搜索等值的查询,而对于其他查找类型,如范围查找,是不能使用哈希索引的。可以通过参数innodb_adaptive_hash_ index 来禁用或启动此特性,默认为开启。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)