Mysql索引使用
众所周知,索引的运用会提高数据查询的效率,也是优化查询的最简单直接的方法,特别是针对数据量大的数据表查询,如果查询关键字建立了索引,查询速度会大大的提高。下面主要介绍在使用索引的优缺点,和使用时注意事项。
一、 索引的优点
如果对一个数据表执行查询,并且查询关键字没有建立索引,查询的时候将是对该数据表的全部扫描。这样对大数据量来说是很消耗性能和时间的。如果我们查询条件建立了索引,在执行查询的时候就不会全表扫描,因为索引值是经过分类,可以在查询的时候知道在什么位置结束扫描。而索引提高查询效率的一原因也就是匹配的数据在什么地方结束。从而缩短了查询的时间。
二、 索引的缺点
索引虽然加快了我们查询数据的速度,但是却降低了我们添加、修改、删除数据的速度,也就是说降低了我们写入数据的速度。因为写入一条数据的时候,相应的索引位置也要做改变,这样一个表的索引越多,作出位置改变的也将会越多。所以,一个表的索引不是越多越好,应该把索引建立在经常用到的查询条件上。
三、 索引列的选择
因为一个数据表索引过多,会影响我们写入数据的速度,那我们最好把索引建立在哪些数据列上呢?
- 建立在用来搜索、分组、排序的数据列,不要为作为输出显示的列建立索引,也就是说,最适合建立索引的数据列,是那些跟在Where语句,在联合语句(inner join left join)或者Order By,Group By 语句后的数据列。
- 考虑数据列所容纳的非重复值个数,重复的数据值越少,索引的使用效果就越好,如我们经常使用的IsDelete数据列,一般就只有0、1值,重复度比较高,虽然经常用来跟在Where语句作为查询条件,但并不适合建立索引。
- 选择比较小的数据类型作索引,小的值可以让比较数据的操作更快的完成,加快索引的查询速度,并且小的值体积小,能更有效的减少磁盘I/O的移动。
- 充分利用最左边的索引,这就是我们通常所说的,为多个列一起建立索引。用的时候一定要注意使用到最左边的索引。比如我们对订单号(OrderID),添加时间(AddTime),联系人(LinkMan)三个字段进行复合索引的建立。那在我们使用他们做查询的时候,查询组合我们可以使用:
Select OrderID,AddTime,LinkMan
Select OrderID
Select OrderID,AddTime
也就是说Mysql使用索引作为条件查询的时候,不能使用没有包含最最左边索引的作为查询条件,如
Select AddTime
Select AddTime,LinkMan 或者Select LinkMan
这样索引就不能使用。如果给定的是第一个OrderID和第三个值LinkMan,这样虽然能通过索引查询时能缩小搜索的范围,当是不能这个索引不能用于值的组合。
所以我们在使用复合索引时需要从最左边索引用起。不然索引不能有效使用。
综上所述:不要建立过多的索引,不要以为索引越多越好,把所有要查询的数据列都建立索引,每一个多出的索引都要占据额外的磁盘空间,在数据进行修改、添加、删除操作的时候,会来回移动索引位置以保持索引顺序,索引会影响他们操作的速度。
四、 索引类型
在建立索引的时候,mysql存储引擎我们常用的主要有两种类型:
- B树索引,它在使用<,<=,=,>=,>,<>,!=和Between操作进行的精确比较和范围查询里是很有效率的,如果不是以通配符开头的查询,如”*”号开头查询,B树索引也可以使用Like 操作符进行模糊查询。
- 散列索引,散列索引在使用“=”或“<=>”(严格比较两个NULL值是否相等),,操作符用来进行精确比较操作速度会很快,如果用来查询范围条件的,查询速度就不会很好。
五、 MyISAM和InnoDB存储引擎存储索引的不同
对于MyISAM数据引擎来说,数据表的数据行存储在数据文件里,而索引值是在单独的索引文件里。索引文件里的每一个索引都是有分类的关键记录数组组成的,这些数组用于快速访问索引文件。
而InnDB存储引擎数据表的数据行和索引值是没有分开的,他们使用的是一个表空间,在这个表空间里管理着所有InnnDB类型数据表的数据和索引的存储。因为MyISAM存储引擎数据行和索引分别在不同的的数据文件里。所有一般在查询的时候,使用MyISAM查询相对更快些,但是它不支持事务方面的操作。
六、 查询优化
查询优化的工具,Mysql自带了查询用户工具,用Explan可以看出那些字段使用了索引,索引关键字是否起作用。使用该命令,后更查询语句,能返回较多的查询相关信息,通过该信息可以的分析怎么优化查询语句。也可以通过mysql的慢日志能查询出执行较慢的SQL。
- 查询优化最好的也是最简单的就是正确使用索引,只要可能就尽可能的使用索引,尽可能快的排除那些不符合索引条件的数据行,第一个条件筛选出的数据越多越好。
如:执行查询语句
Select * from OrderInfo
Where OrderID in (1001,1002,1003) 和 AddTime>’2012-11-12’ and AddTime<=’2012-12-11’
比如该表数据有10000 行数据,在执行In 条件一下就能排除9998行数据,而在执行AddTime条件时能排除5000行,我们就用过把OrderID 的条件放在前面,AddTime放在后门,因为前者能排除更多的数据行,后面的AND语句相对就会进行更少的数据搜索、作更少的数据计算,这样查询效率就会相对快些。
- 使用数据类型的数据进行比较,如果他们数据类型相同,查询的性能就会高一些,相反性能就会低一些,如int类型和Bigint类型比较,就没有int /int和Bigint/bigint比较快一些。如果出现数据类型不一样的比较,最好能修改成数据类型一致才进行两个的比较。
- 在表达式比较时,带索引的数据列在比较表达式中单独出现。比如两条语句:
Select * from OrderInfo AddTime >AddDate(’2012-12-12’,1);
Select * from OrderInfo AddDate(AddTime,-1)>’2012-12-11’;
假设我们为AddTime建立了索引,在第一种查询时,AddTime就能使用索引,对数据很快的查询处理,而如果使用第二种方式,因为我们对索引数据列进行了表达式计算,索引就不能使用索引对数据查询,这种情况下,在查询时索引就不起作用了。
所以我们在进行时间查询或者有表达式计算的查询时,一定要注意索引列要单独与计算好的数据再做比较。
- 用like 查询的开始位置不要使用通配符,能用一个“%”号放在右边就用一个,除非要求全模糊才两边加上“%”。
- 避免过多的使用Mysql的类型自动转换功能,所谓类型自动转换,就是查询的时候,我们输入字符串能自动转换成数字之类的。如:
Select * from OrderInfo where orderID=’1’,这里我们指定OrderID为Int类型
这个查询条件就把字符串1自动转换成了int类型1,这种转换或多或少会对性能有点影响,如果orderID 为索引列的话,因为进行了自动转换,有可能建立在该字段的索引会失去索引的作用。相反,如果一个int 类型与字符串类型作比较,在查询的时候也会阻止索引的使用。所以我们在做比较的时候,最好是认清数据类型,避免比较的时候mysql自动转换类型。
以上基本是在使用Mysql索引的时候,需要注意的地方。