sql优化我的总结(全)

sql优化总结--博客
第一次本身写博客,之后要坚持每掌握一个技能点,就要写一篇博客出来,作一个不知足于一个
只会写if...else的程序员。
最近三个月入职了一家新的公司,作的是CRM系统,将公司多个平台的数据同步到CRM,进行
查询,统计和汇总。因为数据量比较庞大,大部分表数据上百万,甚至有的表数据上千万。因此
在系统中作sql优化比较多,特此写一篇博客总结一下关于sql优化方面的经验。
--致使查询缓慢的缘由
一、数据量过大
二、表设计不合理
三、sql语句写得很差
四、没有合理使用索引

-- 针对SQL语句的优化
一、查询语句中不要使用 *
二、尽可能减小子查询,使用关联查询(left join,right join,inner  join)替代
三、减小使用IN或者NOT IN ,使用exists,not exists或者关联查询语句替代
四、or 的查询尽可能用 union或者union all 代替
(在确认没有重复数据或者不用剔除重复数据时,union all会更好)
五、合理的增长冗余的字段(减小表的联接查询)
六、增长中间表进行优化(这个主要是在统计报表的场景,
后台开定时任务将数据先统计好,尽可能不要在查询的时候去统计)
七、建表的时候能使用数字类型的字段就使用数字类型(type,status...),数字类型的字段做为条件查询比字符串的快
八、那些能够过滤掉最大数量记录的条件必须写在WHERE子句的最末尾

-- 索引优化
若是针对sql语句已经没啥能够优化的,那咱们就要考虑加索引了。

--说索引前先说说explain查看sql的执行计划
1 id
 SELECT识别符。这是select查询序列号。这个不重要
2 select_type
表示查询中每一个select子句的类型(简单OR复杂)
有如下几种值:
 1 simple
 查询中不包含查询或者UNION(联合查询)
 2 PRIMARY
 查询中若包含任何复杂的子部分,最外层查询则被标记为:PRIMARY
 3 UNION
 表示链接查询的第2个或后面的查询语句。
 4 DEPENDENT UNION
 UNION 中的第二个或者后面的select语句,取决于外面的查询
 5 UNION RESULT
 链接查询的结果
 6 SUBQUERY
 子查询中的第一个select语句
 7 DEPENDENT SUBQUERY
 子查询中的第一个select语句,取决于外面的查询
 8 DERIVED
 select(from子句的子查询)
3 table 表示查询的表
4 type
表示表的链接类型
如下的链接类型的顺序是从最佳类型到最差类型
 1 syste
 表仅有一行,这是const类型的特例,平时不会出现
 2 const
 数据表最多只有一个匹配行,由于只匹配一行数据,因此很快,经常使用于PRIMARY KEY
 或者UNIQUE查询,可理解为是最优化的。
 3 eq_ref
 mysql手册是这样说的: 对于每一个来自前面的表的行组合,从该表中读取一行。
 这多是最好的联接类型,除了const类型。他用在一个索引的全部部分被联接使用而且而且索引是UNIQUE或PRIMARY KEY    eq_ref能够用于使用=比较带索引的列。
 4 ref
 查询条件索引既不是UNIQUE 也不是PRIMARY KEY 的状况,ref可用于=或<或>操做符的带索引的列。
 5 ref_or_null
 该联接类型如同ref,可是添加了Mysql能够专门搜索包含null值的行,在解决子查询中常用该联接类型的优化。
 以上这五种状况都是很理想的索引使用状况。
 6 index
 该链接类型与ALL相同,除了只有索引树被扫描。这一般比ALL快,由于索引文件一般比数据文件小。
 7 ALL
 对于每一个来自先前的表的行组合,进行完整的表扫描。
5 possible_key
 指出Mysql能使用哪一个索引在该表中找到行。
 若是该列为NULL 说明没有使用索引,能够对该列建立索引来提升性能
6 Key
 显示mysql实际决定使用的索引,若是没有选择索引,键是null
 能够强制使用索引或者忽略索引:
 强制使用索引:USE index(列名)
 忽略使用索引:IGNORE INDEX(列名)
7 key_len
 显示mysql决定使用的键长度。若是键是NULL则长度为NULL。
 注意:key_len 是肯定了mysql将实际使用的索引长度
8 ref
 显示使用哪一个列或常数与key一块儿从表中选择行
9 rows
 显示mysql认为它执行查询时必须检查的行数
10 extra
 关于MYSQL如何解析查询的额外信息。Using temporary和Using filesort,意思MYSQL根本不能使用索引,结果是检索会很慢
 说明:extra列返回的描述的意义
 Distinct :一旦mysql找到了与行相联合匹配的行,就再也不搜索了。
 Not exists :mysql优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,就再也不搜索了。
 Range checked for each Record(index map:#) :没有找到理想的索引,所以对从前面表中来的每个行组合,mysql检查使用哪一个索引,并用它来从表中返回行。这是使用索引的最慢的链接之一。
 Using filesort :看到这个的时候,查询就须要优化了。mysql须要进行额外的步骤来发现如何对返回的行排序。它根据链接类型以及存储排序键值和匹配条件的所有行的行指针来排序所有行。
 Using index :列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的所有的请求列都是同一个索引的部分的时候。
 Using temporary :看到这个的时候,查询须要优化了。这里,mysql须要建立一个临时表来存储结果,这一般发生在对不一样的列集进行ORDER BY上,而不是GROUP BY上。
 Where used :使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。若是不想返回表中的所有行,而且链接类型ALL或index,这就会发生,或者是查询有问题。
 
使用explain查看sql执行计划后,咱们主要先看下type属性,表示链接的类型,若是是ALL这种那就须要优化了,
再看下possible_key属性,表示可使用的索引,若是没有则为null,key属性表示mysql实际决定使用的索引,若是没有选择索引,键是null,
rows 表示mysql认为它执行查询时必须检查的行数,行数越多效率越低。
 
--索引类型
 主键索引,惟一索引,组合索引,普通索引
--什么是索引
 数据库索引是数据库管理系统中的一个排序的数据结构,以协助快速查询,更新数据库表中数据,索引的实现一般使用B树(B-tree)以及其变种B+tree(一些高效率的算法)

--使用索引时有些不生效的状况
 一、使用like关键字模糊查询时,% 放在前面索引不起做用,只有“%”不在第一个位置,索引才会生效(like '%文'--索引不起做用)
 二、使用联合索引时,只有查询条件中使用了这些字段中的第一个字段,索引才会生效
 三、使用OR关键字的查询,查询语句的查询条件中只有OR关键字,且OR先后的两个条件中的列都是索引时,索引才会生效,不然索引不生效。
 四、尽可能避免在where子句中使用!=或<>操做符,不然引擎将放弃使用索引而进行全表扫描。
 五、对查询进行优化,应尽可能避免全表扫描,首先应考虑在where以及order by涉及的列上创建索引。
 六、应尽可能避免在 where 子句中对字段进行表达式操做,这将致使引擎放弃使用索引而进行全表扫描。如:
    select id from t where num/2=100
    应改成:
    select id from t where num=100*2
 七、尽可能避免在where子句中对字段进行函数操做,将致使引擎放弃使用索引而进行全表扫描。
 八、不要在 where 子句中的“=”左边进行函数、算术运算或其余表达式运算,不然系统将可能没法正确使用索引。
 九、并非全部的索引对查询都有效,sql是根据表中的数据来进行查询优化的,当索引列有大量数据重复时,sql查询不会去利用索引,如一表中有字段
  sex,male,female几乎个一半,那么即便在sex上创建了索引也对查询效率起不了做用。
 十、索引并非越多越好,索引当然能够提升相应的 select 的效率,但同时也下降了 insert 及 update 的效率,
   由于 insert 或 update 时有可能会重建索引,因此怎样建索引须要慎重考虑,视具体状况而定。一个表的索引数最好不要超过6个,
   若太多则应考虑一些不常使用到的列上建的索引是否有 必要。
 十一、尽可能使用数字型字段,若只含数值信息的字段尽可能不要设计为字符型,这会下降查询和链接的性能,并会增长存储开销。
   这是由于引擎在处理查询和链接时会 逐个比较字符串中每个字符,而对于数字型而言只须要比较一次就够了。
 十二、mysql查询只使用一个索引,所以若是where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。
   所以数据库默认排序能够符合要求的状况下不要使用排序操做,尽可能不要包含多个列的排序,若是须要最好给这些列建复合索引。
 1三、order by 索引 ,不起做用的问题(除了主键索引以外):
    一、 若是select 只查询索引字段,order by 索引字段会用到索引,要否则就是全表排列;        二、若是有where 条件,好比where vtype=1 order by vtype asc . 这样order by 也会用到索引!
相关文章
相关标签/搜索