mysql

查询优化

2019-02-14  本文已影响0人  阿长_一个程序员

衡量查询开销的三个指标

关联查询的优化

原理部分


image.png
image.png
image.png
inner join的优化

STRAIGHT_JOIN功能同join类似,但能让左边的表来驱动右边的表,能改表优化器对于联表查询的执行顺序。
接下来我们举个例子进行大致的分析:

select t1.* from Table1 t1 inner join Table2 t2
on t1.CommonID = t2.CommonID where t1.FilterID = 1

以上sql大数据量下执行需要30s,明明Table1表的FilterID字段建了索引,Table1和Table2的CommonID也建了索引。通过explain来分析,发现执行计划中表的执行顺序是Table2->Table1。,mysql中指定了连接条件时,满足查询条件的记录行数少的表为驱动表;如未指定查询条件,则扫描行数少的为驱动表。mysql优化器就是这么粗暴以小表驱动大表的方式来决定执行顺序的。
但如下sql的执行时间都少于1s:

select t1.* from Table1 t1 where t1.FilterID = 1
select t1.* from Table1 t1 inner join Table2 t2 on t1.CommonID = t2.CommonID

这个时候STRAIGHT_JOIN就派上用场,我们对sql进行改造如下:

select t1.* from Table1 t1 STRAIGHT_JOIN  Table2 t2 on t1.CommonID = t2.CommonID 
where t1.FilterID = 1

用explain进行分析,发现执行顺序为Table1->Table2,这时就由Table1来作为驱动表了,Table1中相应的索引也就用上了,执行时间竟然低于1s了。

分析到这里,必须要重点说下:

union 优化

image.png

松散索引

有如下查询

索引(a,b)
select ... from tb1 where b between 2 and 3
image.png
image.png
image.png

在同一个表上查询和更新

mysql不允许同一张表同时进行查询和更新
例如

update tb1 as outer_tb1
    set cnt = (
          select count(*) from tb1 as inner_tb1
          where inner_tb1.type = outer_tb1.type
    );
ERROR 1093 (HY000):You can't specify target table 'outer_tb1' for update in FROM clause

可以通过使用生成表的形式绕过这个限制,因为mysql只会把这个表当作一个临时表处理。

update tb1 inner join(
                        select type,count(*) as cnt
                        from tb1
                        group by type
                   ) as der using(type)
set tb1.cnt = der.cnt

优化count()查询

count()有两种不同的作用

简单的优化
例一
例二
例二中的 OR NULL必须有!

优化关联查询

优化group by和distinct

如果对关联查询做分组,通常采用查找表的标志列分组的效率比其他列更高。
例如下面查询的效率不会很好


image.png

下面的查询效率会更高


image.png

group by 会自动按照其字句的字段排序(GROUP BY id相当于GROUP BY id ORDER BY id),如果不关心结果集的顺序,则可以使用order by null,避免mysql使用filesort

优化LIMIT

在偏移量非常大时,例如limit 10000,10会查询10010条记录,再把前面的10000条记录抛弃掉,代价非常高
例如

SELECT * FROM person LIMIT 1000000,10 

这个查询需要花1.094s
延迟关联让mysql扫描尽可能少的页面,可以大大提升查询效率

SELECT * FROM person INNER JOIN (SELECT id FROM person LIMIT 1000000,10) AS lim USING(id)

使用延迟关联后,查询时间缩短为0.839s

优化UNION

mysql通过创建并填充临时表的方式来执行union查询。union会在临时表上加上DISTINCT选项消除重复的行使得数据唯一,这样做的代价非常高。
如果对数据的唯一性没有要求,则使用union all

上一篇 下一篇

猜你喜欢

热点阅读