Sql优化

在进行MySQL的优化之前必须要了解的就是MySQL的查询过程,很多的查询优化工作实际上就是遵循一些原则让MySQL的优化器能够按照预想的  合理方式运行而已。更多关于MySQL查询相关参照:http://www.cnblogs.com/clsn/p/8038964.html#_label6 系列文章。


数据库层面优化方式:

   1.硬件

           2.系统配置

           3.数据库表结构

           4.SQL及索引

优化成本及效果比拼图

优化工具:


关于zabbix参考:http://www.cnblogs.com/clsn/p/7885990.html

sql优化10个原则:

 原则1 : 尽量避免在列上进行运算,这样会导致索引失效。

        例如原句为: SELECT * FROM t WHERE YEAR(d) >= 2011;

        优化为:SELECT * FROM t WHERE d >= '2011-01-01';

原则2 : 使用JO IN时,应该用小结果集驱动大结果集。同时把复杂的JO IN查询拆分成多 个Query。因为JOIN多个表时,可能导致更多的锁定和堵塞。

        例如: SELECT * FROM a JOIN b ON a.id=b.idLEFT JOIN c ON c.time=a.dateLEFT JOIN d ON c.pid=b.aidLEFT JOIN e ON e.cid=a.did 

原则3 : 注意L IK E模糊查询的使用,避免% %。

        例如原句为: SELECT * FROM t WHERE name LIKE '%de%'

        优化为:SELECT * FROM t WHERE name>='de' AND name<'df'

原则4 : 仅列出需要查询的字段,这对速度不会有明显影响,主要考虑节省内存。

        例如原句为: SELECT * FROM Member;

        优化为:SELECT id,name,pwd FROM Member;

原则5 : 使用批量插入语句节省交互。

        例如原句为: INSERT INTO t (id,name) VALUES (1,'a');INSERT INTO t (id,name) VALUES (2,'b');INSERT INTO t (id,name) VALUES (3,'c');        

        优化为: INSERT INTO t (id,name) VALUES (1,'a'),(2,'b'),(3,'c'); 

原则6: limit的基数比较大时使用between。

        例如原句为: select * from article as article order by id limit 1000000,10

        优化为:select * from article as article where id between 1000000 and 1000010 order by id

between限定比limit快,所以在海量数据访问时,建议用between或是where替换掉limit。 但是between也有缺陷,如果id中间有断行或是中间部分id不读取的情况,总读取的数量会少 于预计数量! 在取比较后面的数据时,通过desc方式把数据反向查找,以减少对前段数据的扫描,让 limit的基数越小越好!

 原则7 : 不要使用rand函数获取多条随机记录。

        例如: select * from table order by rand() limit 20;

       优化为:SELECT * FROM 'table' AS tl JOIN (SELECT ROUND(RAND() * ((SELECT MAX(id) FROM 'table')-(SELECT MIN(id) FROM 'table'))+(SELECT MIN(id) FROM 'table')) AS id ) AS t2 WHERE tl.id>=t2.id ORDER BY tl.id LIMIT 1;

这是获取一条随机记录,这样即使执行2 0次,也比原来的语句髙效。或者先用java产生随机数,把这个字符串传给MySQL, MySQL里用in查询。

 原则8 : 避免使用NULL。

 原则9 : 不要使用count(id), 而应该是count( * )。 

原则1 0 :不要做无谓的排序操作,而应尽可能在索引中完成排序。 


Mysql查询语句执行原理

数据库查询语句如何执行?

DML语句首先进行语法分析,对使用sql表示的查询进行语法分析,生成查询语法分析树。

语义检查:检查sql中所涉及的对象以及是否在数据库中存在,用户是否具有操作权限等

视图转换:将语法分析树转换成关系代数表达式,称为逻辑查询计划;

查询优化:在选择逻辑查询计划时,会有多个不同的表达式,选择最佳的逻辑查询计划;

代码生成:必须将逻辑查询计划转换成物理查询计划,物理查询计划不仅能指明要执行的操作,也给出了这些操作的执行顺序,每步所用的算法,存储数据的方式以及从一个操作传递给另一个操作的方式。

将DML转换成一串可执行的存取操作的过程称为束缚过程,

Mysql查询语句执行过程

这里简单介绍一下mysql数据库,mysql数据库是一款关系型数据库,所谓关系型数据库就是以二维表的形式存储数据,使用行和列方便我们对数据的增删改查。

  我们以mysql数据库为例,对一条sql语句的执行流程进行分析。(本篇博客不涉及到表连接)

  首先,创建一张student表,字段有自增主键id,学生姓名name,学科subject,成绩grade

  建表语句:

                DROP TABLE IF EXISTS student;

                CREATE TABLE `student` (

                  `id` int(5) NOT NULL AUTO_INCREMENT,

                  `name` varchar(10) DEFAULT NULL,

                  `subject` varchar(10) DEFAULT NULL,

                  `grade` double(4,1) DEFAULT NULL,

                  PRIMARY KEY (`id`)

                ) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=utf8;


  初始化数据:

            INSERT INTO student(`name`,`subject`,grade)VALUES('aom','语文',88);

            INSERT INTO student(`name`,`subject`,grade)VALUES('aom','数学',99);

            INSERT INTO student(`name`,`subject`,grade)VALUES('aom','外语',55);

            INSERT INTO student(`name`,`subject`,grade)VALUES('jack','语文',67);

            INSERT INTO student(`name`,`subject`,grade)VALUES('jack','数学',44);

            INSERT INTO student(`name`,`subject`,grade)VALUES('jack','外语',55);

            INSERT INTO student(`name`,`subject`,grade)VALUES('susan','语文',56);

            INSERT INTO student(`name`,`subject`,grade)VALUES('susan','数学',35);

            INSERT INTO student(`name`,`subject`,grade)VALUES('susan','外语',77);

            INSERT INTO student(`name`,`subject`,grade)VALUES('alice','语文',88);

            INSERT INTO student(`name`,`subject`,grade)VALUES('alice','数学',77);

            INSERT INTO student(`name`,`subject`,grade)VALUES('alice','外语',100);

            INSERT INTO student(`name`,`subject`,grade)VALUES('rajo','语文',33);

            INSERT INTO student(`name`,`subject`,grade)VALUES('rajo','数学',55);

            INSERT INTO student(`name`,`subject`,grade)VALUES('rajo','外语',55);

下面我们来看一下,数据在数据库中的存储形式。


 (图1.0)

现在针对这张student表中的数据提出一个问题:要求查询出挂科数目多于两门(包含两门)的前两名学生的姓名,如果挂科数目相同按学生姓名升序排列。

下面是这条查询的sql语句

SELECT `name`,COUNT(`name`) AS num FROM student WHERE grade<60GROUPBY`name`HAVINGnum>= 2 ORDER BY num DESC,`name` ASC LIMIT 0,2;

执行结果:


图(1.1)

以上这条sql语句基本上概括了单表查询中所有要注意的点,那么我们就以这条sql为例来分析一下一条语句的执行流程。

1,一条查询的sql语句先执行的是 FROM student 负责把数据库的表文件加载到内存中去,如图1.0中所示。(mysql数据库在计算机上也是一个进程,cpu会给该进程分配一块内存空间,在计算机‘服务’中可以看到,该进程的状态)


  图(1.2)

2,WHERE grade < 60,会把(图1.0)所示表中的数据进行过滤,取出符合条件的记录行,生成一张临时表,如下图所示。


 图(1.3)

3,GROUP BY `name`会把图(1.3)的临时表切分成若干临时表,分为四个分

组,我们用下图来表示内存中这个切分的过程。


 图(1.4)   图(1.5)  图(1.6)   图(1.7)

4,SELECT 的执行读取规则分为sql语句中有无GROUP BY两种情况。

  (1)当没有GROUP BY时,SELECT 会根据后面的字段名称对内存中的一张临时表整列读取。

  (2)当查询sql中有GROUP BY时,会对内存中的若干临时表分别执行SELECT,而且只取各临时表中的第一条记录,然后再形成新的临时表。这就决定了查询sql使用GROUP BY的场景下,SELECT后面跟的一般是参与分组的字段和聚合函数,否则查询出的数据要是情况而定。另外聚合函数中的字段可以是表中的任意字段,需要注意的是聚合函数会自动忽略空值。

  我们还是以本例中的查询sql来分析,现在内存中有四张被GROUP BY `name`切分成的临时表,我们分别取名为 tempTable1,tempTable2,tempTable3,tempTable4分别对应图(1.4)、图(1.5)、图(1.6),图(1.7)下面写四条"伪SQL"来说明这个查询过程。

SELECT `name`,COUNT(`name`) AS num FROM tempTable1;

SELECT `name`,COUNT(`name`) AS num FROM tempTable2;

SELECT `name`,COUNT(`name`) AS num FROM tempTable3;

SELECT `name`,COUNT(`name`) AS num FROM tempTable4;

最后再次成新的临时表,如下图:


  图(1.8)

5,HAVING num >= 2对上图所示临时表中的数据再次过滤,与WHERE语句不同的是HAVING 用在GROUP BY之后,WHERE是对FROM student从数据库表文件加载到内存中的原生数据过滤,而HAVING 是对SELECT 语句执行之后的临时表中的数据过滤,所以说column AS otherName ,otherName这样的字段在WHERE后不能使用,但在HAVING 后可以使用。但HAVING的后使用的字段只能是SELECT 后的字段,SELECT后没有的字段HAVING之后不能使用。HAVING num >= 2语句执行之后生成一张临时表,如下:


  图(1.9)


6,ORDER BY num DESC,`name` ASC对以上的临时表按照num,name进行排序。

7,LIMIT 0,2取排序后的前两个。


以上就是一条sql的执行过程,同时我们在书写查询sql的时候应当遵守以下顺序。

SELECT XXX FROM XXX WHERE XXX GROUP BY XXX HAVING XXX ORDER BY XXX LIMIT XXX;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351