MySQL优化七-重构查询方式

优化有问题的查询时,有时转换下写法,返回的结果不变,但性能却有所提升。

目录

一、切分查询

二、分解关联查询

三、优化count()查询

四、优化关联查询

五、优化group by 查询

六、优化limit 分页


一、切分查询

场景:定期清除大量数据时,如果用一个大的语句一次性完成的话,则可能一次锁住很多数据,占满事务日志,阻塞查询。

优化:将一个大的delete语句切分为多个较小的查询,可以尽可能小地影响mysql性能,同时还可以减少mysql复制的延迟。

案例:

mysql > delete from messages from created_date < now()

********用类似下面的办法也可以完成

row_affected = 0
do {
    row_affected = do_query {
        " delete from messages from created_date < now() limit 10000"
    }
} while row_affected > 0

这样重构之后,一次只删除1万行,循环判断是否还有可删除的记录。

二、分解关联查询

很多高性能的应用会对关联查询进行分解,简单地说,可以对每个表进行单表查询,然后将结果在应用程序中进行关联。例如:

mysql > select t1*  from tag t1 inner join tag_post t2
        on t1.tag_id = t2.tag_id

*******分解成以下查询可代替
mysql > select * from tag_post where tag = 'mysql'
        select * from tag where tag_id in ( 1234 , 1245 )

分解关联查询的好处如下:

1、让缓存的效率更高。

2、单个查询可能减少锁表的竞争。

3、使用IN()代替关联查询,可让mysql按id顺序查询,比随机关联更高效。

4、减少冗余记录的查询。

5、在应用中实现了哈希关联。而不是使用mysql嵌套循环关联。

三、优化count()查询

当使用count(*)  ,不会像我们猜想的扩展所有的列,而是忽略所有的列,直接统计所有的行数。所有统计行数,不要在括号内指定列,而是直接用count(*)       

利用count(*) 全表统计快的特性,还可以作如下的处理。

mysql> select count(*) from repayment where id > 5

********改写如下:

mysql> select ( select count(*) from repayment - count(*) ) 
        from repayment where id < 5 

 这样优化器按id顺序查询,只需要查前5条记录。

四、优化关联查询

如果表A和表B用列C作关联,关联顺序是A join B,此时只需要在B表的C列建索引,没用到的索引只会带来额外的负担。

五、优化group by 查询

如果对关联查询做分组group by ,按表中的某个列分组。通常采用表的标识列分组的效率会更高一些。

mysql> select t1.first_name, t1.last_name, count(*) 
    ->from film_actor t1 inner join  actor  t2 on t1.actor_id = t2.actor_id 
    ->group by t1.first_name,t1.last_name
*****这样查效率不高,改写如下效率会更高:
mysql> select t1.first_name, t1.last_name, count(*) 
    ->from film_actor t1 inner join  actor  t2 on t1.actor_id = t2.actor_id 
    ->group by t2.actor_id 

这个查询 利用了actor的名字和id直接相关的特点,改写后查询的结果不影响。

六、优化limit 分页

limit 10000,10,这样的查询,mysql需要查10000条记录后返回10条查询结果,前面的10000条记录将被丢弃,这样的代价很高。优化的方法是尽可能地使用索引覆盖查询。

mysql> select film_id , description from film order by title limit 10000,10
*******改写如下:
mysql> select film_id , description from film t1
    -> inner join ( select film_id from film order by title limit 10000,10) t2
    -> on t1.film_id = t2.film_id

你可能感兴趣的:(mariadb,重构)