实践中如何优化MySQL(建议收藏!)( 二 )


12、尽量不用select *SELECT *增加很多不必要的消耗(cpu、io、内存、网络带宽);增加了使用覆盖索引的可能性;当表结构发生改变时 , 前者也需要经常更新 。 所以要求直接在select后面接上字段名 。
13、区分in和existsselect * from 表A where id in (select id from 表B)上面sql语句相当于
select * from 表A where exists(select * from 表B where 表B.id=表A.id)区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键) , 如果是exists , 那么以外层表为驱动表 , 先被访问 , 如果是IN , 那么先执行子查询 。 所以IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况 。
索引的优化:1、Join语句的优化Join 性能点
当我们执行两个表的Join的时候 , 就会有一个比较的过程 , 逐条比较两个表的语句是比较慢的 , 因此可以把两个表中数据依次读进一个内存块中 , 在Mysql中执行:show variables like 'join_buffer_size' , 可以看到join在内存中的缓存池大小 , 其大小将会影响join语句的性能 。
在执行join的时候 , 数据库会选择一个表把他要返回以及需要进行和其他表进行比较的数据放进join_buffer 。
如果是有索引的情况 , 则直接读取两个表的索引树进行比较就可以了 。
若没有索引 , 则会使用 'Block nested loop' 算法 , Block 块 , 也就是说每次都会取一块数据到内存以减少I/O的开销
实践中如何优化MySQL(建议收藏!)文章插图
另外 , Innodb会为每个数据表分配一个存储在磁盘的 表名.ibd 文件 , 若关联的表过多 , 将会导致查询的时候磁盘的磁头移动次数过多 , 从而影响性能
所以实践中 , 尽可能减少Join语句中的NestedLoop的循环次数:“永远用小结果集驱动大的结果集”

  1. 用小结果集驱动大结果集 , 将筛选结果小的表首先连接 , 再去连接结果集比较大的表 , 尽量减少join语句中的Nested Loop的循环总次数
  2. 优先优化Nested Loop的内层循环(也就是最外层的Join连接) , 因为内层循环是循环中执行次数最多的 , 每次循环提升很小的性能都能在整个循环中提升很大的性能;
  3. 对被驱动表的join字段上建立索引;
  4. 当被驱动表的join字段上无法建立索引的时候 , 设置足够的Join Buffer Size 。
  5. 尽量用inner join(因为其会自动选择小表去驱动大表).避免 LEFT JOIN (一般我们使用Left Join的场景是大表驱动小表)和NULL , 那么如何优化Left Join呢?1、条件中尽量能够过滤一些行将驱动表变得小一点 , 用小表去驱动大表2、右表的条件列一定要加上索引(主键、唯一索引、前缀索引等) , 最好能够使type达到range及以上(ref,eq_ref,const,system)
  6. 适当地在表里面添加冗余信息来减少join的次数
  7. 使用更快的固态硬盘
性能优化 , left join 是由左边决定的 , 左边一定都有 , 所以右边是我们的关键点 , 建立索引要建在右边 。 当然如果索引是在左边的 , 我们可以考虑使用右连接 , 如下
select * from atableleft join btable on atable.aid=btable.bid;//最好在bid上建索引(Tips:Join左连接在右边建立索引;组合索引则尽量将数据量大的放在左边 , 在左边建立索引)
2、避免索引失效1.最佳左前缀法则
如果索引了多列 , 要遵守最左前缀法则 , 指的是查询从索引的最左前列开始并且不跳过索引中的列 。 Mysql查询优化器会对查询的字段进行改进 , 判断查询的字段以哪种形式组合能使得查询更快 , 所有比如创建的是(a,b)索引 , 查询的是(b,a) , 查询优化器会修改成(a,b)后使用索引查询 。


推荐阅读