「中国统计网」MySQL性能测试 · 数据库调优攻略( 二 )


2. SELECT语句务必指明字段名称SELECT *增加很多不必要的消耗(cpu、io、内存、网络带宽);增加了使用覆盖索引的可能性;当表结构发生改变时 , 前断也需要更新 。 所以要求直接在select后面接上字段名 。
3. 当只需要一条数据的时候 , 使用limit 1这是为了使EXPLAIN中type列达到const类型
4. 如果排序字段没有用到索引 , 就尽量少排序5. 如果限制条件中其他字段没有索引 , 尽量少用oror两边的字段中 , 如果有一个不是索引字段 , 而其他条件也不是索引字段 , 会造成该查询不走索引的情况 。 很多时候使用 union all 或者是union(必要的时候)的方式来代替“or”会得到更好的效果
6. 区分in和exists ,not in和not existsselect*from表Awhereidin(selectidfrom表B)上面sql语句相当于
select*from表Awhereexists(select*from表Bwhere表B.id=表A.id)区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键) , 如果是exists , 那么以外层表为驱动表 , 先被访问 , 如果是IN , 那么先执行子查询 。 所以IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况 。 关于not in和not exists , 推荐使用not exists , 不仅仅是效率问题 , not in可能存在逻辑问题 。 如何高效的写出一个替代not exists的sql语句?
原sql语句:
selectcolname …fromA表wherea.idnotin(selectb.idfromB表)高效的sql语句:
selectcolname …fromA表LeftjoinB表onwherea.id = b.idwhereb.idisnull7. 分段查询在一些用户选择页面中 , 可能一些用户选择的时间范围过大 , 造成查询缓慢 。 主要的原因是扫描行数过多 。 这个时候可以通过程序 , 分段进行查询 , 循环遍历 , 将结果合并处理进行展示
8. 避免在 where 子句中对字段进行 null 值判断对于null的判断会导致引擎放弃使用索引而进行全表扫描 。
9. 不建议使用%前缀模糊查询例如LIKE “%name”或者LIKE “%name%” , 这种查询会导致索引失效而进行全表扫描 。 但是可以使用LIKE “name%” 。
10. 注意范围查询语句对于联合索引来说 , 如果存在范围查询 , 比如between,>,<等条件时 , 会造成后面的索引字段失效 。

  • type 访问类型
  • ALL 扫描全表数据
  • index 遍历索引
  • range 索引范围查找
  • index_subquery 在子查询中使用 ref
  • unique_subquery在子查询中使用 eq_ref
  • ref_or_null 对Null进行索引的优化的 ref
  • fulltext使用全文索引
  • ref使用非唯一索引查找数据
  • eq_ref在join查询中使用PRIMARY KEYorUNIQUE NOT NULL索引关联
  • const使用主键或者唯一索引 , 且匹配的结果只有一条记录
  • system const 连接类型的特例 , 查询的表为系统表
性能从好到差依次为:
system , const , eq_ref , ref , fulltext , ref_or_null , unique_subquery , index_subquery , range , index_merge , index , ALL , 除了ALL之外 , 其他的type都可以使用到索引 , 除了index_merge之外 , 其他的type只可以用到一个索引 。
所以 , 如果通过执行计划发现某张表的查询语句的type显示为ALL , 那就要考虑添加索引 , 或者更换查询方式 , 使用索引进行查询 。
  • possible_keys
可能使用的索引 , 注意不一定会使用 。 查询涉及到的字段上若存在索引 , 则该索引将被列出来 。 当该列为 NULL时就要考虑当前的SQL是否需要优化了 。
  • key
显示MySQL在查询中实际使用的索引 , 若没有使用索引 , 显示为NULL 。


推荐阅读