[转帖]高性能MySql进化论(十一):常见查询语句的优化_MySQL, Oracle及数据库讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  MySQL, Oracle及数据库讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 2169 | 回复: 0   主题: [转帖]高性能MySql进化论(十一):常见查询语句的优化        下一篇 
ab19890824
注册用户
等级:少尉
经验:351
发帖:92
精华:0
注册:2011-11-21
状态:离线
发送短消息息给ab19890824 加好友    发送短消息息给ab19890824 发消息
发表于: IP:您无权察看 2015-3-16 10:06:04 | [全部帖] [楼主帖] 楼主

总结一下常见查询语句的优化方式

1 COUNT


1. COUNT的作用

· COUNT(table.filed)统计的该字段非空值的记录行数

· COUNT(*)或者是COUNT(not nullable field) 统计的是全表的行数

如果要是统计全表记录数,COUNT(*)效率会比COUNT(not nullable field)要高一点

2. MYISAM的COUNT

一般执行COUNT操作时需要扫描大量的记录,但是在MyISAM引擎的数据库中,数据库把表的记录数保存起来,所以COUN(*)会非常的快(前提是不包含where条件)

3. 当需要频繁的使用COUNT时,可以考虑使用汇总表的策略

4. 优化小例子
在MYISAM中进行范围查询时,可以减少检索行数的小技巧
原始的:select count(*) from dictionary where id>5.

优化后:select (select count(*) fromdictionary)-count(*) from dictionary where id<=5

减少查询次数

优化前:需要两条语句

Select count(*)from student where area=’SH’
Select count(*)from student where area=’BJ’


优化后:合并成一条

select count(area='SH') as shcount, count(area='BJ') as bjcount from student;


2 优化关联查询
1. 确保ON或USING的字句上有索引

2. 一般情况下只需要在第二个表上创建索引

3. 尽量使 Group by/Order by的表达式中只包含一个表的字段

3 优化子查询
尽量用关联代替子查询

4 优化Group by 以及Distinct
1. 当对关联查询执行group by操作时,使用查询表的标识列作为分组条件效率会比较高

2. 当需要查询的非group by指定的字段时,正常情况下是无法执行的,可以通过inner join 的形式来弥补

select firstname, lastname
from actor
inner join(select actor_id, count(*) as cnt from actor group by(actor_id))
using (actor_id)


3. group by默认会对查询的结果进行排序,数据量很大的时候可能会比较耗资源,如果你不关心查询结果的顺序,可以通过order by null 避免这种不必要的浪费

5 LIMIT分页
在进行分页查询的时候往往是采用select * from table1 limit 100,20 的方式来提取数据,在处理的过程中会读取120条数据,然后扔掉100条的offset记录,最后返回20条记录给客户端。如果offset的值非常大,效率上可能会有影响,可以尝试

1. 可以通过覆盖索引+inner join的方式来重写sql

select field1,field2,field3
from table1
inner join
(select id from table1 limit 100, 20) as temp
using(id)


2. 如果可以计算出明确的开始点和结束点,可以转换成 between and 的方式,这种方式只会扫描指定的行数,效率比较高

Select * from table1 between 100 and 120.


3. 可以通过位置标签的方式,来减少需要检索的记录数

例如 从某个位置开始。 Select * from table1 whereid>100 limit 20

下图列出了三种方式的效率对比

在进行分页处理的时候往往需要知道记录的总数,然后用这些总数生成页码。获取总数往往是使用count或是伴随一次全表查询得到的,这个过程也是检索所有的记录,然后再丢掉。为了避免这种浪费可以采取两种策略

· 把页码换成“下一页”的方式,这样就只需要去取固定的条数

· 一次性读取1000条,当一千条使用完后,采用“获取更多记录”的方式再获取1000条

6 UNION


· 使用的时候要把每个优化手段下推到每个子集中(http://blog.csdn.net/eric_sunah/article/details/17290641)

· Union操作会对处理后的结果执行distinct操作,这在很多时候是没有必要的。可以采用union all来避免这个问题

7 自定义变量
合理灵活的使用自定义变量往往会给程序的性能带来意想不到的效果,但往往也会带来与其他数据库系统的兼容性问题。

下面列出几个自定义变量使用的小例子

· 行号

mysql> set @rownumber:=0;
mysql> select mean, @rownumber:=@rownumber+1 from dictionary limit10;


· 避免重复查询刚刚更新的数据

在更新完一条记录后,往往需要再次执行select查询刚刚更新过的记录

通过变量可以避免这种问题

Mysql>set @updaterow:=null;
mysql> update dictionary set mean='update get variable' where id=100and @updaterow:=now();


· 统计更新和插入的数量

mysql> set @x:=0; //define avariable
mysql> insert into dictionary (id,mean) values(3,'duplicate') onduplicate key update mean=values(mean)+(0*(@x:=@x+1)); //insert a duplicaterecord
mysql> select @x; //get x value, it’s indicator duplicate times

8 静态分析工具
有时候可以借助专门的查询分析工具来发现自己的问题,比如pt-query-advisor(http://www.percona.com/doc/percona-toolkit/2.1/pt-query-advisor.html)

                                                                                                                                                                                                                                           --转自北京联动北方科技有限公司



赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论