有如下下数据表,只有主键id
执行sql【explain select id,n1 from tb where n2='f' and n4>'c' order by n3 desc limit 1;】
通过explain分析:
不光是ALL全表扫描,而且还产生了一次内部排序using filesort,效率及其底下。
那么如何建立索引呢?首先n2这个字段肯定是要建立索引的,可以用上等值,而且范围之后索引失效所以可以考虑按n2n3的顺序建立一个索引idx_n2_n3,或者按n2n3n4的顺序建立索引idx_n2_n3_n4。
那么我们先来尝试一种错误的情况,对了n2n4n3建立索引idx_n2_n4_n3。
执行sql【explain select id,n1 from tb where n2='f' and n4>'c' order by n3 desc limit 1;】
可以看到访问类型为range,而且范围之后的索引失效,又产生了内部排序。
我们把这个索引删掉,按n2n3的顺序建立新的索引。
执行sql【explain select id,n1 from tb where n2='f' and n4>'c' order by n3 desc limit 1;】
这个时候n2字段用于等值查询,n3用于排序,消除了全表扫描以及内部排序。
如果对n2n3n4建立索引呢?当然更好,这个时候n4都能用上索引,但是索引本身是很占空间的,即使相对数据表来说索引也不小,切记不要胡乱建立索引。
我们可以试着玩一下。
在我的10条数据量下面没有差异,但是数据一多也差不多,因为到了n4必定只能范围查询。
连接有join,left join,right join,我的mysql5.5没有full join,但是我们可以用union合并结果集来弥补。同时对于join如果不指定连接字段的话(也就是on),会将两表笛卡尔积返回,执行效率就是两张表全部都要去全扫描。
同时按照小结果集驱动大结果集的原则,mysql的join会自动用小表来连接大表,而对于left join 和 right join会按照我们left和right的顺序来连接表。
建立两张表,t1和t2。
可以看到t1有4条数据,t2有7条数据。
执行sql【explain select t1_name from t1 join t2 on t1.id=t2.id;】
可以看到mysql选择用t1表去驱动t2表,t2表扫描类型为唯一索引。
如果把t1表的数据加大到10条呢?
再次执行sql【explain select t1_name from t1 join t2 on t1.id=t2.id;】
结果相反,mysql用t2表去驱动t1表了。
所以mysql的join会自动判断表的大小进行表的连接查询,实战当中如果允许的话可以考虑在连接的两张表的相应字段都建立索引。
而对于left join和right join的话,则会按left或者right的顺序进行连接。
可以看到,t1驱动t2。
把t1和t2位置交换一下,同时改用right join,也是t1驱动t2。
把t1放前,进行左连接,和我们预期的一样,t1驱动t2。
被驱动的表查询的时候能够使用上索引,所以我们总是要遵循驱动的是小结果集去驱动大的结果集的原则,这样才能写出高效率的SQL。
三表连接和两表连接一样,除了驱动表必须全扫描之外,其余的被驱动的表在查询的时候都可以用上索引,当然,前提是在连接字段上建立了相关索引。
可以看道,对于join三表,mysql还是自动选择了最小的表最为驱动表。
如果改成left join或者right join,mysql则会按我们的顺序来连接。