笔者在使用数据库查询时,需要设定条件查询,在sql语句后面可以设置几个条件。但是可以选择条件为空,于是乎两个条件间相接间,第一个条件为空,那么第二个条件开头就会是 “and”,这样sql语句就会发生错误。笔者当时处理时是在sql语句中添加where 1=1来解决。
where 1=1 是为了避免where 关键字后面的第一个词直接就是 “and”而导致语法错误。但是,where 1=1会全表扫描,需要大量的IO操作,数据量越大越慢。
我们来看一下下面的查询命令。数据表中又三条数据,使用explain(执行计划),使用explain关键字可以模拟优化器执行sql查询语句,从而知道数据库是如何处理sql语句。explain主要用于分析查询语句或表结构的性能瓶颈。
explain查询所使用的访问类型,type的值主要有八种,该值表示查询的sql语句好坏,从最好到最差依次为:system>const>eq_ref>ref>range>index>ALL。
1、system,表只有一行记录(等于系统表),是const的特例类型,平时不会出现;;
2、const,通过一次索引就找到了结果,常出现于primary key或unique索引,只匹配一行数据,所以查询非常快;
3、eq_ref,唯一索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见主键或唯一索引扫描。
4、ref,非唯一性索引扫描,返回匹配某个单独值的所有行。本质上也是一种索引访问,返回匹配某值(某条件)的多行值。
5、range,只检索给定范围的行,使用一个索引来检索行,可以在key列中查看使用的索引,一般出现在where语句的条件中,如使用between、>、<、in等查询。
6、index,全索引扫描,index和ALL的区别是index只遍历索引树,通常比ALL快,因为索引文件通常比数据文件小。虽说index和ALL都是全表扫描,但是index是从索引中读取,ALL是从磁盘中读取。
7、all,全表扫描,一般来说,需保证查询至少达到range级别,最好能达到ref。
explain查询中还有其他参数。
1、key值:实际中使用的索引。 下面的possible_keys表示理论上可能用到的索引,key表示实际中使用的索引。
2、key_len:表示索引中所使用的字节数,可通过该列计算查询中使用的索引长度。
3、possible_keys:显示可能应用在表中的索引,可能一个或多个。查询涉及到的字段若存在索引,则该索引将被列出,但不一定被查询实际使用。
4、ref,显示关联的字段。如果使用常数等值查询,则显示const,如果是连接查询,则会显示关联的字段。
5、rows,根据表统计信息及索引选用情况大致估算出找到所需记录所要读取的行数。
6、filtered,百分比值,表示存储引擎返回的数据经过滤后,剩下多少满足查询条件记录数量的比例。
7、Extra,显示十分重要的额外信息。Using filesort表明mysql会对数据使用一个外部的索引排序;使用了临时表保存中间结果,常见于排序order by和分组查询group by;Using index,select操作中使用了覆盖索引,避免访问表的额外数据行,效率不错,同时出现了Using where,表明索引被用来执行索引键值的查找。使用优先级Using index>Using filesort(九死一生)>Using temporary(十死无生)。
条件只是where 1=1的话是all,全表扫描,性能低。特别是数据表较大时,那么查询的效率就很慢。
那需要怎么优化呢?即查询条件添加索引。在查询时增加必输项,即where 1=1后面追加一些常用的必选条件,并且将这些必选条件建立适当的索引,效率会大大提高。
查看下图,如果在where 1=1跟踪主键card_old选项,那么type值就会变成const或者range。,避免全表扫描。
如果后面跟踪的不是主键索引或者唯一索引呢?查看下图的查询条件选项为为card_number时,还是全表扫描。
加上主键索引,也即是又两个条件,一个又索引,一个没有索引,那么查询type是const。
使用索引后,也需要保证索引不失效。这个可以参考博客园的文章-MySQL高级知识(六)——索引优化,总结起来又如下几点:
1、创建了多列索引的情况下,查询从索引的最左前列开始;
2、在索引列上做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效从而转向全表扫描。
3、条件范围右边的索引列失效。
4、尽量使用覆盖索引,即查询列和索引列尽量一致。
5、使用不等于(!=或<>)、is null 或 is not null、like通配符以%开头、字符串不加单引号、用or连接会使索引失效。
网友评论