哈希索引
哈希索引目前只有mysql的memory引擎才支持,它是基于哈希表来实现,必须匹配一行所有的数据。
它大概是怎么做的呢?
比方说,我们的it表.如果要正常去查询全条件的话,sql语句应该是这样。
select * from it where id = 3 and content="aaa" and create_time="2013-09-03" and style =1 and userid =4
有人会说:你这个例子举得不合理啊,你所有条件都知道了你还查个毛线啊?
其实有时候会有这种情况,就是去查询是否存在,如果存在,那么我这样处理,如果不存在,那样处理。好了,不在这里费口舌,我们注意上面这个sql语句。
如果放到一张100W条数据的表里且没有索引,这条语句要炸了。(不过本例中,id是主键,也相当于是索引,它不会炸,我们暂时把id索引给删了)
这条语句会遍历100W次,且每次都是5个条件再依次匹配。
那么memory引擎填上hash索引,会怎么样呢?
memory会把每一行的都计算出一个简单的Hash值,然后把该hash值作为索引,并指向当前行,那么在进行全条件查询的时候,先计算出条件的hash值,然后就只匹配hash值,如果匹配中了,那么就说明存在哎。
有人会问:那么还要匹配100W个hash值,这样效率会高?
首先只匹配100W*1个条件远远比100W*5个条件要快,其次,这个hash算法算好肯定是按顺序节点树排列,那么时间几乎不计啊。
还有人问:那么如果有两行的hash值一样,你能匹配到正确的吗?
hash搜索算法在命中后,还会按节点比较参数是否相同,只有完全相同才会认为完全命中。
但这个东西,只能是memory引擎才能使用。memory引擎一般不使用的,不过我们可以利用这个思想,来创建些伪hash索引
伪哈希索引
注册需求里,通常是要校验用户名是否以及被注册过,有的用邮箱作为用户名,sql语句如下:
select count(*) from user where username="1221212211@qq.com"
用户名一般是varchar字段,它的长度其实不短。如果要直接这样写,那么匹配的速度就比较差。
我们可以增加一个字段:username_crc32
为什么起这个古怪的名字?因为要用mysql内置的crc32这种hash算法。
每次存储时,都将用户名进行crc32运算,然后存到username_crc32里,或者你使用存储引擎也行。
然后大概表就长这样了。
id | username | username_crc32 |
1 | 11111@qq.com | 123445641 |
2 | ejqdq@qq.com | 121245112 |
username_crc32是数字类型的,如果你此时再把username_crc32添加到B树的顺序索引(怎么添加,接下来章节会说),那么执行以下sql语句
select count(*) from user where username="1221212211@qq.com" and username_crc32=CRC32("1221212211@qq.com")
相信我,在百万级别的数据量里,查询这个,只需要几毫秒。
有人会问:为什么不直接在username上加索引
我告诉你,索引最好都用数字加,因为数字都有顺序,有顺序就意味着容易查找。在新增或者删行的时候,mysql处理数字索引的速度远超非数字索引。
有人会问:为什么不要md5?
你妹的md5是强加密的散列算法,是长字符串,你还不如不用呢!这又不是为了加密的,是为了查询的。
空间索引
空间索引mysql是菜鸡,不要用。
全文索引
这相当于搜索服务器,查关键字的,mysql也是菜鸡。不如用solr等lucene服务器