目录
概述
在企业级的项目中,数据库里的数据量很大,经常就是一条查询语句运行很久才能得到结果,超出了用户能忍受的范围,需要在让sql数据库查询变得更快,首先做好表设计,根据业务需求,尽量让每次查询的数据量更少,关联的表更少,建立索引、视图帮助查询,最后在查询语句上做优化。
sql语句执行顺序
要想优化查询语句,首先要对查询语句的执行有个大概了解,以下是查询语句执行流程
FORM: 后面跟着表,或者子查询,或是JOIN合并成的笛卡尔积,产生虚表VT1
JOIN: 指定了各种JOIN,产生笛卡尔积,执行ON保留表中未匹配的行就会作为外部行添加到虚表VT1中,产生虚表VT2
ON: 对虚表VT2进行筛选,产生虚表VT3,重复JOIN操作实现多表链接。
WHERE: 对虚拟表VT3进行条件过滤,插入到虚表VT4中
GROUP BY: 根据列对VT4中的记录进行分组操作,产生VT5
HAVING: 对虚表VT5应用having过滤,插入到虚表VT6中
SELECT: 执行select操作,选择显示的列,到虚表VT7中
DISTINCT: 对VT7中的记录进行去重。产生虚表VT8
ORDER BY: 将虚表VT8中的记录排序,产生虚表VT9
LIMIT:取出指定行的记录,产生虚表VT10, 并将结果返回。
知道这个顺序后,就要想办法让大量的数据尽快变得很少。
查询注意点
禁用select *,一是为了方便阅读,二是确实*会慢一点点
使用select count(*) 统计行数,效率上count(1)=count(0)=count(常量)=count(*),最后都是count(*),所以直接用count(*),在这里并不是全表扫描,count(列名)这个列字段如果长的话,效率较低。
尽量少运算
尽量避免对字段进行表达式计算
尽量避免对字段进行函数操作
where条件
尽量避免在where子句对字段进行null判断
尽量避免在where子句使用!= 或者<>
尽量避免在where子句使用or连接
尽量避免在where子句中使用in,not in或者having,使用exists,not exists代替
尽量早过滤(mysql与oracl不同)
多表查询
尽量少join,生成笛卡尔积
尽量用join代替子查询,这可以从执行顺序得出,子查询又从头到尾走了一边流程。
尽量用union all代替union
索引
尽量避免使用不是复合索引的前缀列进行过滤连接
尽量避免两端模糊匹配 like ‘%呵呵%’,这也是跟索引有关,索引依靠前缀去找,%在前面就不会用索引,所以慢。
尽量避免全表扫描,如果可以,在过滤列建立索引
不能用null作索引,任何包含null值的列都将不会被包含在索引中,复合索引任意一列包含null值,索引无效。
EXPLAIN
MySql提供了EXPLAIN语法用来进行查询分析,在SQL语句前加一个"EXPLAIN"即可。
其他
避免类型转换
优先优化高并发sql,而不是频率低的大sql
尽可能对每一条sql进行explain
尽可能从全局出发
尽量批量insert