左连接:
select * from teacher t left outer join course2 c on t.cid = c.cid where cname ='java'
索引往哪张表加? -- 小表驱动大表
where 小表.x = 大表.y
ex:
小表:10 大表:300
但是 对于 双层循环
当编写 on t.cid = c.cid 语句时 将数据量小的表放左边
索引建立在经常使用的字段
一般情况 左外连接 给左表加索引 右外连接 给右表加索引
三表优化
a.小表驱动大表
b.索引建立在经常查询的字段上
避免索引失效的一些原则
a.复合索引,不要跨列或无序使用 最佳左前缀
b复合索引.尽量使用全索引匹配
c.不要在索引上进行任何操作(计算,函数,类型转换)否则索引失效
对于复合索引,如果左边失效,右侧全部失效 假设有一索引(a,b,c) 例如 b失效,则b,c也失效
复合索引不能使用不等于 (!= <>)或is null 或 is not null 否则自身以及右侧所有全部失效
sql优化 是一种概率层面的优化 至于是否实际使用了我们的优化 要通过 explain 来进行推测
体验概率情况(< > =): 原因是服务层中有sql优化器,可能会影响我们的优化
-- 复合索引中如果有> 则自身和右侧索引全部失效
一般而言,范围查询(> < in )之后的索引都会失效
建议:尽量使用索引覆盖 using index
like尽量以“常量开头” 不要以‘%’开头 否则索引失效
一些其他的优化方法
优化exist 和 in
select .. from talbe where exist/in 子查询
如果子查询的数据集大,则使用in
如果子查询的数据集大,则使用exist
exist语法:将主查询的结果,放到子查询中进行条件校验‘子查询是否有数据,如果有数据 则校验成功 如果复合校验则保留数据
order by 优化
有两种算法: 双路排序 单路排序
依据:根据IO的次数
MySQL 4.1之前 默认使用双路排序 :双路:扫描2次磁盘
1.从磁盘读取排序字段,对排序字段进行排序 在buffer中进行的排序
2.扫描其他字段
缺陷: IO比较消耗性能
4.1之后,默认使用单路排序
1. 只读取一次 全部字段
在buffer中进行排序 但此种单路排序 会有一定的隐患
不定真的是 “单路|1次IO” 有可能多次IO
原因: 如果数据量特别大,则无法将所有字段的数据 一次性读取完毕 因此会进行“分片读取 多次读取”
表最终以文件形式保存在磁盘中、从磁盘读取
单路排序比双路排序 会占用更多的buffer
单路排序在使用时,如果数据大,可以考虑调大bufferr 的容量大小
set max_length_for_sort_data = 2048 单位byte
如果max_length_for_sort_data值太低 则mysql会自动从 单路-》双路
太低指的是需要排序的列的总大小超过了max_length_for_sort_data定义的字节数
提高order by 查询的策略
a.选择使用单路,双路:调整buffer容量大小
b.避免select * ....
c.复合索引 不要跨列使用 避免using filesort
d.尽量保证全部的排序字段 排序的一致性 都是升序 或降序