当B表的数据集小于A表的数据集时,用in 优于 exists。如下:
SELECT * FRON A WHERE id IN (SELECT id FROM B);
等价于
for select id from
for select * from A where A.id = B.id
当A表的数据集小于B表数据集时,用exist 优于 in。如下:
SELECT * FROM A WHERE EXISTS (SELECT 1 FROM B WHERE B.id = A.id)
等价于
for select * from A
for select * from B where B.id = A.id
注:A表,B表ID字段应建立索引
order by子句,尽量使用index方式排序,避免使用FileSort方式排序
Mysql支持两种方式的排序,FileSort和Index,Index效率高,它指Mysql扫描索引本身完成排序。FileSort方式效率低。
order by满足两种情况,会使用Index方式排序:
①order by 语句使用索引最左前列
②使用where子句与order by子句条件列组合满足索引最左前列。
尽可能在索引列上完成排序操作,遵照索引建的最佳左前缀
如果不在索引列上,filesort有两种算法:mysql启动双路排序和单路排序。
Mysql4.1 之前是使用双路排序,字面意思就是两次扫描磁盘,最终得到数据。读取行指针和orderby列,对他们进行排序,然后扫描已经排好序的列表,按照列表中的值重新从列表中读取对应的数据输出。
从磁盘取排序字段,在buffer进行排序,再从磁盘取其他字段。
从磁盘读取查询需要的所有列,按照orderby列在buffer对他们进行排序,然后扫描排序后的列表进行输出。他的效率更快一点,避免了第二次读取数据。并且把随机IO变成了顺序IO,但是它会使用更多的空间,因为他把每一行都保存在内存中了。
本来想省一次I/O操作,反而导致了大量的I/O操作,反而得不偿失。
增大sort_buffer_size参数的设置
增大max_length_for_sort_data参数的设置
why?
不管使用哪种算法,提高这个参数都会提高效率,当然,要根据系统的能力去提高,因为这个参数是针对每个进程的。
提高这个参数,会增加使用改进算法的概率。但是吐过设的太高,数据总量超出sort_buffer_size的概率就增大,明显症状是 高的磁盘I/O活动 和 低的处理器使用率。
为排序使用索引
Mysql两种排序方式:文件排序或扫描优需索引排序
Mysql能为排序与查询使用相同的索引
KEY a_b_c (a, b, c)
# order by 能使用索引 最左前缀
- ORDER BY a
- ORDER BY a, b
- ORDER BY a, b, c
- ORDER BY a DESC, b DESC, c DESC (a,b,c排序都一致可以用索引)
# 如果where使用索引的最左前缀定义为常量,则order by能使用索引
- WHERE a = const ORDER BY b, c
- WHERE a = const AND b=const ORDER BY c
- WHERE a = const ORDER BY b, c
- WHERE a = const AND b > const ORDER BY b, c
# 不能使用索引进行排序
- ORDER BY a ASC, b DESC , c DESC /*排序不一致*/
- WHERE g = const ORDER BY b, c /*丢失a索引*/
- WHERE a = const ORDER BY c /*丢失b索引*/
- WHERE a = const ORDER BY a,d /*d不是索引的一部分*/
- WHERE a in (···) ORDER BY b, c /*对于排序来说,多个相等条件也是范围查询*/
group by 实质是先排序后进行分组,遵照索引建的最佳左前缀
当无法使用索引列,增大max_length_for_sort_data参数的设置 + 增大 sort_buffer_size参数的设置
where高于having,能写在where限定的条件就不要去having限定了