SQL查询语句执行的流程,看完你就懂了
sql对于大多数来说大同小异,来简练的说一下一条sql查询语句执行的流程。
1、首先点击运行按钮,写好的sql语句会通过你用的客户端传到服务器。
2、服务器对sql语句进行解析,首先传过来的sql语句会先从高数缓存中查找是否有相同的执行计划,如果找到就会直接执行,省去后面步骤节约时间。另外这个缓存是服务器的,内存的读取速度要比硬盘快的多!
3、服务器开始检查语句的合法性。检查传过来的sql语句是否符合语法规则,如果出现错误就会反馈给客户端。在这一步不会对sql语句本身的表,字段进行检查。这些是下一步需要检查的。
4、语言含义检查。当语法没有问题的时候,数据库开始检查表,字段是不是在数据字典中呀,如果不存在,同样会把错误信息反馈给客户端。所以在写查询语句的时候先是语法错误,语法没错了才是字段表结构错误。
5、获取对象锁。如上都正确了,数据库会把要查询的表对象进行加锁,以免在操作的同时,别人在对同一条数据或者表结构进行处理变更,从而保持一致。
6、数据访问权限核对。数据库会查询当前用户是否具有这张表的查询权限,当然数据权限这里需要如上都检查没问题再会到这一步!所以sql写正确未必能查到数据,sql写错误不知后面还有个坑。
7、最佳执行计划。数据库会对没有问题的sql,按照一定的规则进行优化,当然优化是有限的。具体的还需要自己在sql的同时考虑到sql语句的调优,已达到最快的效率!然后数据库会把这条sql语句以及执行计划放到数据库的高速缓存,以便下次再有相同语句,直接执行不用在检查了。
8、语句执行。
一是:若被选择行所在的数据块已经被读取到数据缓冲区的话,则服务器进程会直接把这个数据传递给客户端,而不是从数据库文件中去查询数据。
二是:若数据不在缓冲区中,则服务器进程将从数据库文件中查询相关数据,并把这些数据放入到数据缓冲区中(buffer cache)
9、sql语句中的函数、关键字、排序等执行顺序。
mysql
oracle
(8)select (9)distinct (11)<top num> <select list> (1)from [left_table] (3)<join_type> join <right_table> (2)on <join_condition> (4)where <where_condition> (5)group by <group_by_list> (6)with <cube | rollup> (7)having <分组后筛选> (10)order by <排序字段> 逻辑查询处理阶段简介 ---------- 1、from:对from子句中的前两个表执行笛卡尔积(cartesian product)(交叉联接),生成虚拟表vt1 2、on:对vt1应用on筛选器。只有那些使<join_condition>为真的行才被插入vt2。 3、outer(join):如 果指定了outer join(相对于cross join 或(inner join),保留表(preserved table:左外部联接把左表标记为保留表,右外部联接把右表标记为保留表,完全外部联接把两个表都标记为保留表)中未找到匹配的行将作为外部行添加到 vt2,生成vt3.如果from子句包含两个以上的表,则对上一个联接生成的结果表和下一个表重复执行步骤1到步骤3,直到处理完所有的表为止。 4、where:对vt3应用where筛选器。只有使<where_condition>为true的行才被插入vt4. 5、group by:按group by子句中的列列表对vt4中的行分组,生成vt5. 6、cube|rollup:把超组(suppergroups)插入vt5,生成vt6. 7、having:对vt6应用having筛选器。只有使<having_condition>为true的组才会被插入vt7. 8、select:处理select列表,产生vt8. 9、distinct:将重复的行从vt8中移除,产生vt9. 10、order by:将vt9中的行按order by 子句中的列列表排序,生成游标(vc10). 11、top:从vc10的开始处选择指定数量或比例的行,生成表vt11,并返回调用者。
注:步骤10,按order by子句中的列列表排序上步返回的行,返回游标vc10.这一步是第一步也是唯一 一步可以使用select列表中的列别名的步骤。这一步不同于其它步骤的 是,它不返回有效的表,而是返回一个游标。sql是基于集合理论的。集合不会预先对它的行排序,它只是成员的逻辑集合,成员的顺序无关紧要。对表进行排序 的查询可以返回一个对象,包含按特定物理顺序组织的行。ansi把这种对象称为游标。理解这一步是正确理解sql的基础。
因为这一步不返回表(而是返回游标),使用了order by子句的查询不能用作表表达式。表表达式包括:视图、内联表值函数、子查询、派生表和共用表达式。它的结果必须返回给期望得到物理记录的客户端应用程序。例如,下面的派生表查询无效,并产生一个错误:
select * from(select orderid,customerid from orders order by orderid) as d