指引网

当前位置: 主页 > 数据库 > Oracle >

SQL语句执行顺序及建议

来源:网络 作者:佚名 点击: 时间:2018-01-13 06:40
[摘要] 一、当SQL 语句进入 Oracle 的库缓存后,sql语句的执行步骤: 1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义。 Note: sql语法的分析是从右到左 2)语义分析,检查语句中
一、当SQL 语句进入Oracle 的库缓存后,sql语句的执行步骤:

  1)语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义。

  Note: sql语法的分析是从右到左

  2)语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限。

  3)视图转换,将涉及视图的查询语句转换为相应的对基表查询语句。

  4)表达式转换, 将复杂的 SQL 表达式转换为较简单的等效连接表达式。

  5)选择优化器,不同的优化器一般产生不同的"执行计划"

  6)选择连接方式, ORACLE 有三种连接方式,对多表连接 ORACLE 可选择适当的连接方式。

  7)选择连接顺序, 对多表连接ORACLE 选择哪一对表先连接,选择这两表中哪个表做为源数据表。

  8)选择数据的搜索路径,根据以上条件选择合适的数据搜索路径,如是选用全表搜索还是利用索引或是其他的方式。

  9)运行"执行计划"

  一旦为执行准备好了,SQL以后的执行将很快发生,因为Oracle认可同一个SQL语句,并且重用那些语句的执行。

  然而,对于生成特殊的SQL 语句,或嵌入了文字变量的SQL 语句的系统,SQL 执行计划的生成时间就很重要了,

  并且前一个执行计划通常不能够被重用。对那些连接了很多表的查询,Oracle需要花费大量的时间来检测连接这些表的适当顺序。

  二、sql执行顺序:

  from子句--执行顺序为从后往前、从右到左

  表名(最后面的那个表名为驱动表,执行顺序为从后往前, 所以数据量较少的表尽量放后)

  oracle的解析器按照从右到左的顺序处理,FROM 子句中的表名,FROM 子句中写在最后的表(基础表driving table)将被最先处理,即最后的表为驱动表,在FROM 子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3 个以上的表连接查询, 那就需要选择交叉表(intersectiontable)作为基础表, 交叉表是指被其他表所引用的表

  多表连接时,使用表的别名并把别名前缀于每个Column上。可以减少解析的时间并减少那些由Column 歧义引起的语法错误。

  where子句--执行顺序为自下而上、从右到左

  ORACLE采用自下而上从右到左的顺序解析Where 子句,根据这个原理,表之间的连接必须写在其他Where 条件之前, 可以过滤掉最大数量记录的条件必须写在Where 子句的末尾。

  groupby--执行顺序从左往右分组

  提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUPBY 之前过滤掉。即在GROUP BY前使用WHERE来过虑,而尽量避免GROUP BY后再HAVING过滤。

  having子句----很耗资源,尽量少用

  避免使用HAVING 子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤。这个处理需要排序,总计等操作。

  如果能通过Where 子句在GROUP BY前限制记录的数目,那就能减少这方面的开销。

  (非oracle 中)on、where、having 这三个都可以加条件的子句中,on 是最先执行,where 次之,having 最后,因为on 是先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,按理说应该速度是最快的,

  where 也应该比having 快点的,因为它过滤数据后才进行sum,在两个表联接时才用on 的,所以在一个表的时候,就剩下where 跟having比较了。

  在这单表查询统计的情况下,如果要过滤的条件没有涉及到要计算字段,那它们的结果是一样的,只是where 可以使用rushmore 技术,而having 就不能,在速度上后者要慢。

  如果要涉及到计算的字段,就表示在没计算之前,这个字段的值是不确定的,where 的作用时间是在计算之前就完成的,而having 就是在计算后才起作用的,所以在这种情况下,两者的结果会不同。

  在多表联接查询时,on 比where 更早起作用。系统首先根据各个表之间的联接条件,把多个表合成一个临时表后,再由where 进行过滤,然后再计算,计算完后再由having 进行过滤。

  由此可见,要想过滤条件起到正确的作用,首先要明白这个条件应该在什么时候起作用,然后再决定放在那里。

  select子句--少用*号,尽量取字段名称。

  ORACLE在解析的过程中, 会将依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 使用列名意味着将减少消耗时间。

------分隔线----------------------------