写在最前面:sql优化,对什么样的语句优化,我们可以通过开启mysql的慢查询,检测超过我们预期时间的sql语句来优化。下面是开启满查询的方法。
show variables “%quer%” 来查看是否开启了慢查询日志
mysql> show variables like ”%slow%”; //查看一下慢查询是不是已经开启
+———————+———————————+
| Variable_name | Value |
+———————+———————————+
| log_slow_queries | OFF |
| slow_launch_time | 2 |
| slow_query_log | OFF |
| slow_query_log_file | /usr/local/mysql/mysql-slow.log |
+———————+———————————+
mysql> set global slow_query_log=’ON’;//启用慢查询一定要加上global 否则会报错
mysql> set global long_query_time=2;//设置我们能够接受的最慢查询时间
mysql> set global slow_query_log_file = {path};//设置日志存储路径
设置完毕之后,记得重新连接数据库,才能看到设置的我们能够承受的最慢查询时间,切记,重新连接。起初还以为自己设置错了!!!!!
下面是总结的一点点数据库的优化:
count的优化
之前又看到下面一个描述
比如:计算id大于5的城市 a. select count(*) from world.city where id > 5; b.
select (select count() from world.city) – count() from world.city
where id <= 5; a语句当行数超过11行的时候需要扫描的行数比b语句要多,
b语句扫描了6行,此种情况下,b语句比a语句更有效率。当没有where语句的时候直接select count(*) from world.city这样会更快,因为mysql总是知道表的行数。
如果按照之前博客里写的sql语句的执行顺序分析的话上面的结论是不成立的,但是
select count(*) from world.city
是不会扫描全表的返回速度非常快,所以上面提到的优化是正确的。
还有另外一种情况,就是count(*)和count(name)的比较,争论很多,个人感觉,如果想过滤掉col中的null字段,则用后者,否则用前者。
- 索引失效
很多情况下会使索引失效。比如:
1,对索引字段在where进行计算或者使用聚合函数
SELECT * FROM T1 WHERE F1/2=100 应改为: SELECT * FROM T1 WHERE F1=100*2
2.避免使用!=或<>、IS NULL或IS NOT NULL、IN ,NOT IN等这样的操作符.
上面提到的情况不能一概而论,只是尽量的避免使用,在数据量比较大的时候。看下面例外情况。
在主键上使用!=和in用到了primary索引,但是在name字段上使用却没使用索引。
3.尽量使用数字型字段.
4.尽量避免在索引过的字符数据中,使用非打头字母搜索。这也使得引擎无法利用索引。
5.如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)
user_name没有索引的情况下
user_name加上索引的情况下
6.多列索引使用时不符合最左前缀规则的失效
- 尽量少 join
join会由于笛卡尔积产生大量的数据,应该尽量避免用join
- 尽量少排序
排序操作会消耗较多的 CPU 资源,所以减少排序可以在缓存命中率高等 IO 能力足够的场景下会较大影响 SQL 的响应时间。
对于MySQL来说,减少排序有多种办法,比如:
上面误区中提到的通过利用索引来排序的方式进行优化
减少参与排序的记录条数
非必要不对数据进行排序
…
- 尽量避免 select *
虽然 select 列数的多少一定程度上不影响速度,但是在有order by 时,如果select中的列都含有索引,则可以直接取出,否在还需要去表中获取数据排序。
- 尽量用 join 代替子查询
- 尽量少 or
当 where 子句中存在多个条件以“或”并存的时候会造成了其性能比较低下,很多时候使用 union all 或者是union(必要的时候)的方式来代替“or”会得到更好的效果。
- 尽量用 union all 代替 union
union 和 union all 的差异主要是前者需要将两个(或者多个)结果集合并后再进行唯一性过滤操作,这就会涉及到排序,所以当我们可以确认不可能出现重复结果集或者不在乎重复结果集的时候,尽量使用 union all 而不是 union。