一、结论
1、首先排序字段得有索引
2、如果排序字段在大表内,需要确保大表要作为驱动表,
注意:inner join 会自动选择数量小的表作为驱动表,
如果想让大表作为驱动表需要使用straight_join强制前表为驱动表
3、 如果order by仍没有走索引,则使用force强制走索引
4、 优化前sql
select A.aid from A
inner join (select B.b from B inner join C on B.cid = C.cid) as BC on BC.b = A.b
order by A.aid
limit asc 10
5、 优化后sql
select A.aid from A force index (`PRIMARY`, `b_index`)
straight_join (select B.b from B inner join C on B.cid = C.cid) as BC on BC.b = A.b
order by A.aid
limit asc 10
6、下面为优化前后explain的说明,第一幅图为 优化前,第二幅图为优化后
二、说明
有ABC三张表,A表aid主键自增,字段b有索引,b为字符串字段,B表b字段无索引,字段cid也无索引,C表cid为自增主键。
A表80万数据,BC表7万数据
需要关联查询aid并按aid排序
select A.aid from A
inner join (select B.b from B inner join C on B.cid = C.cid) as BC on BC.b = A.b
order by A.aid
limit asc 10
优化前sql直接采用inner join查询,此时mysql会自己优化执行过程,会主动选择数据量小的表为驱动表也就是从 B->C->A,
此时是从表B出发的,那么他的排序将不会走表A的索引,而是把数据查出来后,再最终进行排序,可以看到使用了filesort
select A.aid from A force index (`PRIMARY`, `b_index`)
straight_join (select B.b from B inner join C on B.cid = C.cid) as BC on BC.b = A.b
order by A.aid
limit asc 10
优化后sql,强制使用表A作为驱动表,并且强制使用表A使用aid的主键索引和b字段的索引,此时排序将走表A的主键索引,
而不是先查出所有数据再进行排序