MySQL技巧--伪哈希索引

哈希索引

  哈希索引就是通过一个哈希函数计算出某个key的hash值,并以这个hash值去找到目标数据。例如:对于数据库的一行数据,对其主键进行hash运算,得到一个地址,这个地址指向这行记录的存储地址,key与hash值的对应关系就构成了哈希索引。根据某一列进行查询时,如果为这一列建立了哈希索引,那查询的速度是非常快的,只需对其进行一次hash运算即可直接得到地址拿到数据,时间复杂度为O(1)。

  但是众多MySQL存储引擎中,支持哈希索引的引擎却比较少,如Memory、NDB等。广泛使用的InnoDB引擎也只是会自适应的建立哈希索引,如某几行记录的查询频率非常高的情况,但是不能手动建立。这是因为,哈希索引虽然查询速度非常快,但是它的特性是通过key经过hash函数运算得到地址,散列存储即连续的key得到的地址却不是连续的。这就决定了哈希索引只适合等值查询,而不适合范围查询,而范围查询又是非常普遍的,还有就是数据规模一大hash运算的冲突概率会上升的非常快,等值查询的速度也没有优势了。

伪哈希索引

  虽然使用哈希索引有诸多不便,但我们也可以从它做法中得到某些启示。比如将复杂且长数据进行hash运算得到一个简单映射值,但不将这个映射值作为地址,而是为这些映射值建立一个B+树的索引,这样再走索引查询时效率就会提高很多。比如有一个列存储url,这是一个比较长的字符串比较时效率不高,则可以考虑增加一列hashUrl,存储url经过hash运算的值,最好是一个整数。例如:

  url                                                    hahsUrl

----------------------------------------------------------------------

  "http://www.mysql.com"                     118291010

  "http://www.apache.com"                   318291011

然后为hashUrl建立B+树的索引,查询url时:

 select * from table1 where hashUrl  = hashFunc("http://www.mysql.com");         //hashFunc就是某个hash函数

为了一次性的解决hash冲突的问题,可以在后面加上直接按url查询的条件:

 select * from table1 where hashUrl  = hashFunc("http://www.mysql.com")
    and url = "http://www.mysql.com";         //hashFunc就是某个hash函数

当 hashFunc("http://www.mysql.com")得到的整数在索引中不止一个时,即发生了冲突,这时第二个条件就发挥了作用,做进一步筛选。最重要的是:经过第一个用整数的条件筛完后,第二个直接用字符串筛选的记录就非常少了,不会又导致了效率的降低。因此使用伪哈希索引查询时,把原本的列也加入查询条件是一种很好的办法。

注意:一定要仔细衡量使用伪哈希索引的得失,有时它带来的收益可能是负的。因为这样做表就要徒增一列,浪费存储空间,且每次更改、插入原数据都要用hash函数运算哈希值写到存储其哈希值的列,也是一笔开销。当某列的数据类型确实长度大、且比较时效率低,且通过它查询的情况十分多,则可以考虑伪哈希索引。

原文地址:https://www.cnblogs.com/shen-qian/p/11855555.html