设为首页 加入收藏

TOP

数据库执行sql的大致流程、数据库如何优化?
2017-11-19 09:07:02 】 浏览:170
Tags:数据库 执行 sql 大致 流程 如何 优化

数据库执行sql的大致流程

粗略流程,所有关系型数据库都是这几步,具体前后顺序根据不同dbms不同配置下略有小差别,以下过程都需要耗时耗资源

1.应用程序与数据库服务器建立链接

2.sql发送到数据库,数据库验证是否有执行的权限

3.进入语法解析器,进行词法与语法分析

4.进入优化器生成执行计划,部分dbms会检查是否有可重用的执行计划

5.根据执行计划依次扫描相关表中的行,不在数据缓冲区的走io

6.同时对于被扫描的行可能加锁,同时也可能会被其他sql阻塞

7.扫描的行足够放入查询缓存则开始运算或直接返回,不够则生成临时表,可能消耗io

8.对sql结果进行计算(可能)

9.将计算完成的结果全部写入网络io(可能)

10.如果事务完成则同步事务日志并释放锁,具体方式取决于dbms和当前配置

11.关闭连接(可选)

如何优化

这么多步骤,每一步都有优化策略,我尽量用简单的语言来描述

1.应用程序与数据库服务器建立链接

引入数据库连接池,避免每次都与数据库建立连接,提高效率

2.sql发送到数据库,数据库验证是否有执行的权限

没撒好说的

3.进入语法解析器,进行词法与语法分析

也没撒好说的,想要数据库在这里少用点资源就把sql写的简单点,但是差别不大

4.进入优化器生成执行计划,部分dbms会检查是否有可重用的执行计划

哦也,最复杂的部分来了,任何数据库如何生成执行计划都可以写一本几百页的书,我就简单说说,复杂的我也说不出来,哈哈哈

关系型数据库选择走什么执行计划都是基于消耗最小化的思路来的,简单来说就是走什么索引,按什么顺序走表,被扫到的数据行最少。如果你的表结构很复杂,有各种混搭的索引,你的join很多,那执行计划分析的时间就会拉长。所以sql对应的表索引简单,join或子查询少就快,复杂了优化器也会得选择困难症。

5.根据执行计划依次扫描相关表中的行,不在数据缓冲区的走io

存储引擎扫描表的性能消耗参考下面的list,消耗从大到小

全表扫描>全索引扫描>部分索引扫描>索引查找>唯一索引/主键查找>常量/null

要走索引对于sql语句也有要求,不能在谓词上作任何运算,扫描行数一般不能超过表的17%左右,这对你数据分布又有要求,比如你查select xxx from human where sex ='man',五五开,还是走扫描。这里我就不展开了,推荐题主一本书《Relational Database Index Design and the Optimizers》

6.同时对于被扫描的行可能加锁,同时也可能会被其他sql阻塞

如果扫描的行多,sql执行的时间长,被阻塞的概率就高,阻塞别人的概率也高,然后大家一起等,数据库就hung住了

7.扫描的行足够放入查询缓存则开始运算或直接返回,不够则生成临时表,可能消耗io

一次取的尽量少,这不单指返回服务端的行数,应该从嵌套最深的一个子查询开始算

8.对sql结果进行计算(可能)

少用各种复杂的函数啊,count啊,order by啊等等

9.将计算完成的结果全部写入网络io(可能)

请尽量少返回一点数据,如果不行请多次分批

10.如果事务完成则同步事务日志并释放锁,具体方式取决于dbms和当前配置

这里举两个代表性栗子:

sql渣:

for i in (1-1000):

start transaction;

insert into table values (1);

commit;

end for

sql赞:

start transaction;

for i in (1-1000):

insert into table values (1);

end for

commit;

sql赞爆:

insert into table values (1)()...........()(1000);

首先,sql语法是我临时自创的,这个不是关键,关键在sql渣先生是1000个事务插1000行,日志flush1000次。sql赞先生是一个事务插1000行,事务日志flush1次。sql赞爆最nice。

这个例子我想表达的意思是如果你要用sql做一件事,那就要尽量让这件事占用的事务总时间最少。

第二个例子

sql渣:

update table where id > 0 and id < 1000000;

sql赞:

update table where id > 0 and id < 1000;

update table where id >= 1000 and id < 2000;

update table where id >= 2000 and id < 3000;

....

....

这个例子我想表达的意思是如果你要用sql做一件很大的事,那就尽量让大事化成很多小事。

两个例子好好体会下,一点不矛盾哦。补充一下,这里每个update都是单独事务

11.关闭连接(可选)

同1,别每次都关,关了也许还要重连。不关的话记得commit就好了,千万要记得commit啊!

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇使用SolrJ实现索引库的增删查操作.. 下一篇MySQL安装及改密教程

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目