• 哈希索引


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

         在mysql中,只有memory引擎显示支持哈希索引。这也是memory引擎表的默认索引类型,memory引擎也支持B-Tree索引。值得一提的是memory引擎是支持非唯一哈希索引的。如果多个列的哈希值相同,索引会以链表的方式存放多个记录指针到同一个哈希条目中。

    因索引自身只需存储对应的哈希值,所以索引的结构十分紧凑,这也让哈希值索引查找的速度非常快。然而,哈希索引也有它的限制:

    • 哈希索引只包含哈希值和行指针,而不存储字段值,所以不能使用索引中的值来避免读取行。不过,访问内存中的行的速度很快,所以大部分情况下这一点对性能的影响并不明显。
    • 哈希索引数据并不是按照索引值顺序存储的,所以也就无法用于排序
    • 哈希索引也不支持部分索引列匹配查找,因为哈希索引始终是所用索引列的全部内容来计算哈希值的。例如,在数据列(A,B) 上建立哈希索引,如果查询只有数据列A,则无法使用该索引。
    • 哈希索引只支持等值比较查询,包括=、in()、<=>,也不支持任何范围查询。
    • 访问哈希索引的数据非常快,除非有很多哈希冲突,当出现哈希冲突的时候,存储引擎必须遍历链表中所有的行指针,逐行进行比较,直到找到所有符合条件的行。
    • 如果哈希冲突很多的话,一些索引维护操作的代价会很高。例如,如果在某个选择性很低(哈希冲突很多)的列上建立哈希索引,那么从表中删除一行时,存储引擎需要遍历对应哈希值的链表中的每一行,找到并删除对应行的引用,冲突越多,代价越大。

    因为这些限制,哈希索引只适用于某些特定的场合。而一旦适合哈希索引,则它带来的性能提升将非常显著。

    除了memory引擎外,NDB集群引擎也支持唯一哈希索引,且在NDB集群引擎中作用非常特殊。

    InnoDB引擎有一个特殊的功能叫做“自适应哈希索引”。当InnoDB注意到某些索引值被使用得非常频繁时,它会在内存中基于B-Tree索引之上再创建一个哈希索引,这样就让B-Tree索引也具有哈希索引的一些优点,比如快速的哈希查找。这是一个完全自动的、内部的行为,用户无法控制或者配置,不过如果有必要,可以完全关闭该功能。

    创建自定义哈希索引

    如果存储引擎不支持哈希索引,则可以模拟像InnoDB一样创建哈希索引,这可以享受一些哈希表的便利,例如只需要很小的索引就可以为超长的键创建索引。在B-Tree基础上创建一个伪哈希索引。这和真正的哈希索引不是一回事,因为还是使用B-Tree进行查找,但是它使用哈希值而不是键本身进行索引查找,你需要做的就是爱查找的where子句中手动指定使用哈希函数。

    下面是一个实例:例如需要存储大量的URL,并需要根据URL进行搜索查找。如果使用B-Tree来存储URL,存储的内容就会很大,因为URL本身都很长,正常情况下会有如下查询:

     SELECT id FROM url WHERE url="http://www.mysql.com";

     若删除原来url列上的索引,而新增一个被索引的url_crc列,使用CRC32做哈希,就可以使用一下方式查询:

    SELECT id FROM url WHERE url="http://www.mysql.com" AND url_crc=CRC32(http://www.mysql.com);

    这样做的性能会非常高,因为mysql优化器会使用这个选择性很高而体积很小的基于url_crc列的索引来完成查找。即使有多个记录有相同的索引值,查找仍然很快,只需要根据哈希值做快速的整数比较就能找到索引条目,然后一一比较返回对应的行。另外一种方式就是对完整的URL字符串做索引,那样会非常慢。

    这样实现的缺陷是需要维护哈希值。可以手动维护,也可以使用触发器实现。

    如果采用这种方式,记住不要使用SHA1()和MD5()作为哈希函数。因为这两个函数计算出来的哈希值是非常长的字符串,会浪费大量空间,比较时会更慢,SHA1()和MD5() 是强加密函数,设计目标是最大限度消除冲突。

    如果数据表非常大,CRC32()会出现大量的哈希冲突,则可以考虑实现一个简单的64位哈希函数。这个自定义函数要返回整数,而不是字符串。一个简单的办法是使用MD5()函数返回值的一部分来作为自定义哈希函数。

    处理哈希冲突,当使用索引进行查询的时候,必须在where子句中包含常量值。

  • 相关阅读:
    vue定义data的三种方式与区别
    利用Python开发App实战
    序列化:ProtoBuf 与 JSON 的比较 !
    年轻人不讲武德,where 1=1 是什么鬼?
    Java 生成随机数的 5 种方式,你知道几种?
    卸载 Navicat!事实已证明,正版客户端,它更牛逼……
    MySQL大表优化方案
    鹅厂是如何使用 Git 的?
    灵魂一问:一个TCP连接可以发多少个HTTP请求?
    新来的老大说,“公司以后禁止使用Lombok”,我表示反对~
  • 原文地址:https://www.cnblogs.com/alphathink/p/10973919.html
Copyright © 2020-2023  润新知