索引的底层理解
最近看了很多文章,这里再补充一下对索引底层的理解,仅个人意见,有不对的,大家可以留言下,非常欢迎~
关于什么是索引,索引的建立,索引不同存储引擎可以在之前的文章了解到
请点击这里:http://www.cnblogs.com/houdashuai/p/6681680.html
这次总结一下,重点说一下底层结构
普通索引「INDEX」: 增加索引结构,对数据列增加普通索引
全文索引「FULLTEXT」: 增加索引结构,全文索引适用于文章查询,一般用普通索引就可以
唯一索引「UNIQUE」: 增加索引结构,数据不允许出现重复,但是可以为空,空就是空,不等于0,也不等于空字符串
主键索引「PRIMARY」: 增加索引结构,数据不允许出现重复,但是不可以为空
联合索引: 根据左前缀原则合理创建,这里不多介绍
针对于数据库查询,数据库字段肯定是越小,越少的元素会很快,那么在创建表,对字段的约束尽量以数据类型为主:
1. 尽量以INT数值去做索引列,因为数值的查询效率总是大于文字;
2. 数据列字段尽量范围越小越好,这种区别在千万级数据库中或者单张表字段很多时会有很大差距,tinyint就是用tinyint,不要用int,或者char;
3. 还有字段尽量给 NOT NULL,尽量给 NOT NULL,尽量给 NOT NULL,这个要注意下,因为索引对空值的判断很复杂,可以给默认值填充空字符串;
会影响到全表扫描的语句,像 NOT IN 、LIKE、<>、!=、or......这些explain 看一下语句级别和影响行数注意一下
说一下两个常用的点:
1. limit:
limit 一般用到分页,但是如果数据很多的话,一般都是这样写的 limit 100,200
如果场景允许的话可以适用一下这种方式:
WHERE uid>100 LIMIT 200
原因:limit会产生全表扫描,但是可以用WHERE筛选掉一部分数据,这样会节省很多查询时间,大家可以尝试一下这种方式~
2. *:count(0)、count(*)
网上对星号的歧义有很多,这两种哪个效率高,我觉得用*号应用性更好一些(部分场景),每个项目都会封装model层,这些一般都是封装单张表的SQL
SELECT COUNT(*) FROM `demo`;
SELECT * FROM `demo`;
如果查询涉及到一张表建议还是用*号,考虑到扩展性、及效率
扩展性:网站业务扩展,字段增加,如果不用*号那就不可避免的要更改最底层的代码,这种操作很危险;
效率:效率来讲,*号会自动匹配到这张表中查询效率最优的数据列,从而获取到数据,如果是单张表我还是建议用*号,但是如果是关联表就不建议使用*号了,关联表那影响查询效率就翻倍了。
优点:增加查询速度
缺点:影响写的效率
问题:为什么会影响写的效率。
每创建一个索引,都会创建一条依据这个索引的索引查询结构,也就是平衡树结构。
可以这样理解,每创建一条索引都会生成一个索引结构文件,这个文件存的不是数据,而是数据的【指针】,索引根据二分算法也就是B+Tree、B-Tree的算法去查询到数据的指针,再拿到数据。
讲到这里就有一个问题,索引的产生肯定是维持在一个正确的平衡树状态,那么每一次做增、删、改的操作时就会重新排序索引文件结构,那么索引如果有一条,两条,三条,的时候,那么索引越多岂不是很影响写的效率,因为每一条索引结构都会重新排序,并且当数据量过于巨大时,每一次写操作,对于数据库的压力也会非常大;
所有的优化都是空间换时间,或者时间换空间;
这里想强调一下:对于优化而言网上有提供很多种,但是这里还是说一下级别,能在表,SQL,计算机硬件上做优化尽量先考虑这些,之后可以再考虑主从,读写分离,负载均衡,不到很卡顿尽量还是不要做分库分表,因为目前而言大都是关系型数据库居多,以关系为主,过多的做子表拆分也就扩大了关系型数据库的弊端,也可以考虑一下NoSQL,当然如果涉及到表设计需要分表这个另说,像这种关系型数据库,亿级以下的数据用索引,SQL优化,架构优化,读写分离,主从完全可以搞得定,如果还是卡,那就硬件提升一下,4G上8G,速度绝对有提升很多,尽量从其他方面考虑,MySQL毕竟也是一种开发语言,吼住上亿数据还是毛毛雨的~