最近决定将以前同事写的存储过程查看一遍,寻找一些代码上写的不太好的地方,争取进行修改以后让这些过程达到一个很好的运行速度。下面是遇到的最多的几个问题。

我遇到了这样的一个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;

不管是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
where t1.employee_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
on t1.employee_id = t2.employee_id
where t2.nation = 'USA';

如果表上有索引,执行速度快极了。

写SQL,还是要首先研究这个数据库的原理,然后慎而又慎的写。

从最近MySQL的优化工作想到的的更多相关文章

  1. MYSQL之性能优化 ----MySQL性能优化必备25条

    今天,数据库的操作越来越成为整个应用的性能瓶颈了,这点对于Web应用尤其明显.关于数据库的性能,这并不只是DBA才需要担心的事,而这更是我 们程序员需要去关注的事情.当我们去设计数据库表结构,对操作数 ...

  2. 百万行mysql数据库优化和10G大文件上传方案

    百万行mysql数据库优化和10G大文件上传方案 最近这几天正在忙这个优化的方案,一直没时间耍,忙碌了一段时间终于还是拿下了这个项目?项目中不要每次都把程序上的问题,让mysql数据库来承担,它只是个 ...

  3. Mysql 索引优化分析

    MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字 ...

  4. mySql索引优化分析

    MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字 ...

  5. MySQL性能优化必备25条

    1. 为查询缓存优化你的查询 大多数的MySQL服务器都开启了查询缓存.这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的.当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一 ...

  6. 【学习】016 MySQL数据库优化

    MySQL如何优化 表的设计合理化(符合3NF) 添加适当索引(index) [四种: 普通索引.主键索引.唯一索引unique.全文索引] SQL语句优化 分表技术(水平分割.垂直分割) 读写[写: ...

  7. 一本彻底搞懂MySQL索引优化EXPLAIN百科全书

    1.MySQL逻辑架构 日常在CURD的过程中,都避免不了跟数据库打交道,大多数业务都离不开数据库表的设计和SQL的编写,那如何让你编写的SQL语句性能更优呢? 先来整体看下MySQL逻辑架构图: M ...

  8. Mysql性能优化:为什么你的count(*)这么慢?

    导读 在开发中一定会用到统计一张表的行数,比如一个交易系统,老板会让你每天生成一个报表,这些统计信息少不了 sql 中的count函数. 但是随着记录越来越多,查询的速度会越来越慢,为什么会这样呢?M ...

  9. mysql深度优化与理解(迄今为止读到最优秀的mysql博客)

    转载:https://www.cnblogs.com/shenzikun1314/p/6396105.html 本篇深入了解查询优化和服务器的内部机制,了解MySql如何执行特定查询,从中也可以知道如 ...

随机推荐

  1. c#基础精华01(强调代码规范,虚方法,抽象方法,接口)

    强调代码规范 规则(法律,必须遵守否则报错) 语法 规范(道德,大家都喜欢有道德的人.) 注释//,/**/,/// 骆驼命名 :第一个单词首字母小写,之后的单词首字母大写 userName.user ...

  2. 关于Apache Struts 2 S2-032高危漏洞的一些确认

    2016年4月21日Struts2官方发布两个CVE,其中CVE-2016-3081(S2-032)官方评级为高. 主要原因为在用户开启动态方法调用的情况下,会被攻击者实现远程代码执行攻击. 具体的漏 ...

  3. 搜索引擎spam

    什么是SPAM?搜索引擎优化中的SPAM 在搜索引擎优化相关的文章中中经常遇到“SPAM”一词,SPAM通常用来指垃圾邮件,不过在搜索引擎营销中所说的SPAM是专门针对那些欺骗搜索引擎的信息.搜索引擎 ...

  4. 在vs2010中mfc,C++的一些小经验

    1 如果你最近才从vc6.0到vs2010,在vs2010中mfc可能遇见一个小问题,如果你添加或改天了窗口中的控件,运行程序缺没有发现其中的变化,这时候需要在debug选项中rebuild all一 ...

  5. jqueryrotate 使用 帮助 笔记 学习

      1.想变角度 $("imgID").rotate(45);   2.想变角度时,有运动过程 $("imgID").rotate({animateTo:45} ...

  6. 实用的eclipse adt 快捷键

    Ctrl + Shift + T: 打开类型:显示"打开类型"对话框来在编辑器中打开类型."打开类型"选择对话框显示工作空间中存在的所有类型如类.接口等.    ...

  7. Android 之 内存管理-查看内存泄露(三)

    概述 在android的开发中,要时刻主要内存的分配和垃圾回收,因为系统为每一个dalvik虚拟机分配的内存是有限的,在google的G1中,分配的最大堆大小只有16M,后来的机器一般都为24M,实在 ...

  8. Anti-pattern(反面模式)

    转自维基百科 http://zh.wikipedia.org/wiki/%E5%8F%8D%E9%9D%A2%E6%A8%A1%E5%BC%8F 在软件工程中,一个反面模式(anti-pattern或 ...

  9. bzoj1293: [SCOI2009]生日礼物

    单调队列 用一个堆维护目前每个颜色在里面的点,每回取出队首点,并更新答案.一旦哪个颜色的点都被用完,跳出循环. #include<cstdio> #include<algorithm ...

  10. 对DataTable里数据进行排序

    在日常开发过程中,有一个DataTable集合,里面有很多字段,现在要求针对某一列进行排序,如果该列为数字的话,进行ASC即可实现,但是该字段类型为string,此时排序就有点不正确了. 我也不多废话 ...