本文咱们来谈谈项目中经常使用的 20 条 MySQL 优化方法,效率至少提升 3倍!前端
具体以下:面试
使⽤ EXPLAIN 判断 SQL 语句是否合理使用索引,尽可能避免 extra 列出现:Using File Sort、Using Temporary 等。sql
重要SQL必须被索引:update、delete 的 where 条件列、order by、group by、distinct 字段、多表 join 字段。数据库
对于联合索引来讲,若是存在范围查询,好比between、>、<等条件时,会形成后面的索引字段失效。数组
对于联合索引来讲,要遵照最左前缀法则:举列来讲索引含有字段 id、name、school
,能够直接用 id 字段,也能够 id、name 这样的顺序,可是 name; school 都没法使用这个索引。因此在建立联合索引的时候必定要注意索引字段顺序,经常使用的查询字段放在最前面。网络
必要时可使用 force index
来强制查询走某个索引: 有的时候MySQL优化器采起它认为合适的索引来检索 SQL 语句,可是可能它所采用的索引并非咱们想要的。这时就能够采用 forceindex 来强制优化器使用咱们制定的索引。架构
对于非标准的日期字段,例如字符串的日期字段,进行分区裁剪查询时会致使没法识辨,依旧走全表扫描。并发
尽可能使用 TIMESTAMEP 类型,由于其存储空间只须要 datetime 的一半。函数
SELECT 只获取必要的字段,禁止使用 SELECT *。这样能减小没必要要的消耗(CPU、IO、内存、网络带宽),增长使用覆盖索引的可能性;当表结构发生改变时,表结构变动对前端程序基本无影响。高并发
SQL 中避免出现 now()
、rand()
、sysdate()
、current_user()
等不肯定结果的函数。在语句级复制场景下,引发主从数据不一致;不肯定值的函数,产生的 SQL 语句没法使用 QUERY CACHE。
避免在 where 子句中对字段进行 null 值
判断:对于 null 的判断会致使引擎放弃使用索引而进行全表扫描。
避免在where子句中对字段进行表达式操做:由于对字段就好了算术运算,这会形成引擎放弃使用索引。
禁止使用 % 前导查询,例如:like “%abc”,⽆法利⽤到索引。
在平常中你会发现全模糊匹配的查询,因为 MySQL 的索引是 B+ 树结构,因此当查询条件为全模糊时,例如 %AB%
、%AB
,索引没法使用,这时须要经过添加其余选择度高的列或者条件做为一种补充,从而加快查询速度。仅AB%
形式的能够避免通配符引发索引屏蔽。
OR 两边的字段中,若是有一个不是索引字段,而其它条件也不是索引字段,会形成该查询不走索引的状况。不少时候都会使用 IN 进行替代,或者使用 union all 或者是 union(必要的时候)的方式来代替“or”也会获得更好的效果。但 SQL 语句中 IN 包含的值不宜过多,应少于 1000 个。过多会使随机 IO 增大,影响性能。
使用 IN 是由于 MySQL 对其作了相应的优化,即将 IN 中的常量所有存储在一个数组里面,并且这个数组是排好序的。可是若是数值较多,产生的消耗比较大。
再例如:
select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了;再或者使用链接来替换。
禁止使⽤负向查询,例如:not in、!=、<>、not like。
在对字符串类型的索引进行大于运算时,会致使全表扫描。因此应改成区间between区间范围运算。
另外 order by/group by
的 SQL 涉及排序,尽可能在索引中包含排序字段,并让排序字段的排序顺序与索引列中的顺序相同,这样能够避免排序或减小排序次数。若是排序字段没有用到索引,就尽可能少排序。
order by rand() 会为表增长几个伪列,而后用 rand() 函数为每一行数据计算 rand() 值,最后基于该行排序,这一般都会生成磁盘上的临时表,所以效率很是低。建议先使用 rand() 函数得到随机的主键值,而后经过主键获取数据。
union 和 union all 的差别主要是前者须要将结果集合并后再进行惟一性过滤操做,这就会涉及到排序,增长大量的CPU运算,加大资源消耗及延迟。固然,union all 的前提条件是两个结果集没有重复数据。
尽可能采用批量 SQL 语句,减小与数据库交互次数。
获取⼤量数据时,建议分批次获取数据,每次获取数据少于 5000 条,结果集应⼩于 1M。
不要用一个SQL解决全部事情,能够分步骤作,省时、易理解、优化。且 MySQL 也十分擅长处理短而简单的 SQL,整体耗时会更短,并且也不会产生臃肿的 SQL,让人难以理解和优化。
拆分复杂 SQL 为多个 小SQL,避免⼤事务。简单的 SQL 容易使用到 MySQL 的 QUERY CACHE;减小锁表时间特别是 MyISAM;可使用多核 CPU。
delete from table_name;
会产生大量 undo 和 redo 日志,执行时间很长,可采用 TRUNCATE TABLE tablename;
col_utf8mb4 = col_utf8
关联类型都是 varchar ,但字符集不一样,没法使用索引。使用过程当中要特别注意。
这也是一个被面试中常常会问到的问题,对于下面的四条 SELECT 语句:
select count(*) from table … ; select count(1) from table … ; select count(primary key) from table … ; select count(index key) from table …;
哪一条的执行效率最高呢?这个问题须要具体问题具体分析,不能一律而论。这里举 SELECT count(1) 这条 SQL 为例。
优化前和优化后,执行效率相差2倍。就添加了一个索引。
优化思路 : 是选择索引 key_len
最短的二级索引效率高,不要使用全表扫描(PK 聚族索引会全表扫描),由于索引 key_len
越短,读取页面越少,进而 IO_COST
越小。
prepared statement
和绑定变量,能够提高性能并避免 SQL 注入重点总结一下:SQL 的执行过程->查询优化器的工做原理->SQL 执行计划的解读->MySQL 慢查询日志和分析->SQL 经常使用的优化手段->SQL 编写规范->深刻实际业务对数据库访问进行优化。