减少select *的使用
select * 会增加网络IO压力,查询时间,内存等等。因为select* 是查询所有列,MySQL会把查到所有列发送给客户机,如果查询无用列增多,会增加网络IO的压力。
Join
join可以看做是两个表做循环 ,表A为驱动表,表B为被驱动表。扫描将表A的数据循环一遍,每一条表A的数据都和表B所有数据进行链接。
驱动表选择结果集少的
小表一趟for循环的代价+大表上使用B+树索引的代价<大表一趟for循环的代价+小表使用B+树索引的代价
如果表A有10条数据,表B有20条数据。
表A为驱动表时,链接次数1020=200
表B为驱动表时,链接次数2010=200
但是!就优化而言,如果被驱动表都添加索引后时间差别很小,驱动表循环次数越小肯定时间越短,优化效果约好。
inner join(等值连接) 只返回两个表中联结字段相等的行,MySQL有自己的算法选取驱动表(下面有介绍)
left join(左联接) 返回包括左表中的所有记录和右表中联结字段相等的记录,其中左表为驱动表。
right join(右联接) 返回包括右表中的所有记录和左表中联结字段相等的记录,其中右表为驱动表。
join实现原理
MySQL只支持一种join算法 Nested-Loop Join(嵌套循环链接)
但是Nested-Loop Join又分三种变化
- Simple Nested-Loop Join
- Index Nested-Loop Join
- Block Nested-Loop Join
Simple Nested-Loop Join
一行一行的扫描驱动表,然后和另一个表的每一行进行链接,效率最低,MySQL已经很少使用。
Index Nested-Loop Join
一行一行的扫描驱动表,然后查询第二个表的索引进行链接,在MySQL8中,如果SQL语句中没有指定驱动表,MySQL会将没有索引的表做驱动表,如果两个表都没有索引,会指定结果集少的作为驱动表。
Block Nested-Loop Join
先定义一个buffer缓存,这样就不用一行一行的扫描驱动表,而是按照buffer的容量,成批成批的和另一个表进行链接。如果join的两个表都没有索引,MySQL内部会默认使用这个算法。
join优化
1,尽可能减少驱动表的行数,减少外层循环次数
2,优化内层循环速度(添加索引)
3,增加join buffer的容量(在内存允许的前提下)