mysql中groupby会⽤到索引吗_MySQL的优化实验 group by
和order。。。
最近决定将以前同事写的存储过程查看⼀遍,寻⼀些代码上写的不太好的地⽅,争取进⾏修改以后让这些过程达到⼀个很好的运⾏速度。下⾯是遇到的最多的⼏个问题。
我遇到了这样的⼀个SQL:
select name, count(*) from (select name from table_1) a group by
a.name;
MySQL的执⾏计划对于这种派⽣表的解释⾮常的不友好,但是能直观的感觉到的是,这个SQL执⾏速度特别的慢。查看这个表table_1发现,name字段是有索引的。审视这段代码,可以推断出当时程序员的想法,应该是想让数据库扫描更⼩的结果集,因为select
*是很不好的习惯。不过他应该忽略了⼀个MySQL的很重要的特点就是索引。MySQL的索引是个很有意思的东西,是我从Oracle转过来感觉最好玩的东西,好玩的地⽅就在于,可以优化group
by。当我把这个SQL改成如下SQL以后:
select name, count(*) from table_1 group by name;
这样⼀来,这段SQL的执⾏速度就⾮常的快了,extra列明确的显⽰了using index,索引覆盖查询,速度杠杠的。
其实这种错误应该是程序员常犯的,因为程序员对Java等代码超级熟悉,但是对于SQL,基本上都是⼤学的时候学习的SQL,⽤SQLServer练出来的,基本上没有对数据库进⾏⾮常深⼊的研究,其实每种数据库中,同⼀条SQL的执⾏计划都是不尽相同的,这也就是企业有⼀个专业的DBA的⼀个作⽤。
下⾯,就是⼀个让⼈很头疼的错误:
select name, userid from table_1 where name = null;group by的用法及原理详解
不管是MySQL还是Oracle,对这种SQL的写法的规范都是where name is (not)
null。null这个值,在不管什么数据库⾥都是⼀个让⼈(包括程序员和DBA)都很头疼的东西。我对MySQL的理解还不够深⼊,但是根据某⼀本《Oracle
DBA⼿记》中记载,Oracle中每种数据类型的null都代表了不⼀样的意义。
做了下⾯⼀个实验:
可以看出来,不管是“= null”还是“<> null”,得到的值其实都是不确定,也就是null。因此,必须要写成is
(not) null。在《剑破冰⼭》这本书⾥也有对Oracle的null值的详细介绍。
总结⼀下最近的⼯作,我研究了⼩半年时间的MySQL,发现这个开源的数据库并不像我过去认为的那样,就是⼀个互联⽹数据库。这个数据库在⾯向OLAP复杂计算的⽅⾯确实和Oracle,DB2等商⽤数据库之间有不⼩的差距,不过在MariaDB这个分⽀中,这部分有了不⼩的进步,相信后⾯的MySQL版本中也会越来越好。其实这个数据库最让我感兴趣的不是开源,因为我确实看不懂那么长的源代码,我的C语⾔⽔平就是⼤学毕业⽔平。这个数据库最让我感兴趣(起码现在来讲)是它的索引,它的索引和Oracle有很⼤的不同,尤其是InnoDB的表整个就是⽤索引组织起来的,在简单的查询的时候,⼀个索引覆盖查询就可以⽆敌于天下了,在group
by和order by的时候,如果是索引字段,效率会相当的⾼。
其实我还想说的就是,⼀个团队⾥,如果涉及到⼤量存储过程的编写,⼀定要有⼀个专业的DBA⼈员参与其中。SQL是⼀个标准,横跨了所有的关系型数据库,但是每⼀种关系型数据库对SQL的实现⼜不尽相同,因此同样的⼀段SQL,放到不同的数据库上执⾏,效率上就会千差万别。⽽SQL⼜⾮常容易⽤⼈最习惯最简单的思维写出来,⽐如搜索⼀个订单表⾥美国员⼯⽣成的订单信息,SQL有可能是
这样的:
select * from orders t1
ployee_id in (select employee_id from employee t2
where t2.nation = 'USA');
如果是Oracle这样的商业数据库,这个SQL的执⾏效率可能会⽐较好,但是应该不如⽤exists的SQL。但是当这段SQL在MySQL中执⾏的时候,效率就很差了,因为很多⼈都知道,MySQL的⼦查询效率实在是不敢恭维。这段代码会被改为相关⼦查询,⽽且随着数据量的增长,执⾏时间会越来越长。这段代码如果改成下⾯的SQL,效果会更好:
select t1.*
from orders t1
inner join employee t2
ployee_id = t2.employee_id
where t2.nation = 'USA';
如果表上有索引,执⾏速度快极了。
写SQL,还是要⾸先研究这个数据库的原理,然后慎⽽⼜慎的写。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。