- 语法分析,分析语句的语法是否符合规范,衡量语句中各表达式的意义。
- 语义分析,检查语句中涉及的所有数据库对象是否存在,且用户有相应的权限。
- 视图转换,将涉及视图的查询语句转换为相应的对基表查询语句。
- 表达式转换,将复杂的 SQL 表达式转换为较简单的等效连接表达式。
- 选择优化器,不同的优化器一般产生不同的“执行计划”。
- 选择连接方式,ORACLE 有三种连接方式,对多表连接 ORACLE 可选择适当的连接方式。
- 选择连接顺序,对多表连接 ORACLE 选择哪一对表先连接,选择这两表中哪个表做为源数据表。
- 选择数据的搜索路径,根据以上条件选择合适的数据搜索路径,如是选用全表搜索还是利用索引或是其他的方式。
- 运行“执行计划”。
二、SQL Select语句完整的执行顺序:
- from子句组装来自不同数据源的数据;(from后面的表关联,是自右向左解析的,即在写SQL的时候,尽量把数据量大的表放在最右边来进行关联)
- where子句基于指定的条件对记录行进行筛选;(where条件的解析顺序是自下而上,从右到左的,即应把能筛选出大量数据的条件放在where语句的最下面)
- group by子句将数据划分为多个分组;
- 使用聚集函数进行计算;
- 使用having子句筛选分组;
- 计算所有的表达式;
- select 的字段;
- 使用order by对结果集进行排序;
- 选择指定数量或比例的行,返回给调用者。
SQL查询处理的步骤顺序如下:
(8)SELECT (9) DISTINCT (11) <TOP_specification> <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 <having_condition>
(10) ORDER BY <order_by_list>
(12) limit <limit_condition>
在SQL语句中,第一个被处理的子句是FROM,而不是第一句SELECT。以上每个步骤都会产生一个虚拟表,该虚拟表被用作下一个步骤的输入;
三、SQL优化
对查询进行优化,应尽量避免全表扫描
(1)Where 语句
- 避免在WHERE子句中使用in,not in,or 或者having;
- 可以使用 exist 和not exist代替 in和not in;对连续数值可以使用between;
- 可以使用表链接代替 exist;
- Having可以用where代替,如果无法代替可以分两步处理。
- 应尽量避免在where子句中对字段进行函数操作;
- 尽量避免在 where 子句中对索引字段进行计算操作;
- 应尽量避免在 where 子句中使用 != 或 <> 操作符;
- 应尽量避免在 where 子句中对字段进行 null 值判断;
- 应尽量避免在 where 子句中使用 or 来连接条件;
- 否则将导致引擎放弃使用索引而进行全表扫描
(2)Select语句
- 尽量不要使用select * from table这种方式;把要查询的具体字段列出来,不要返回任何用不到的字段;
- 尽可能的使用 varchar/nvarchar 代替 char/nchar ,因为首先变长字段存储空间小,可以节省存储空间;
(3)连接语句
- UNION 会将各查询子集的记录做比较,自动去掉重复记录,故比起UNION ALL 的速度,UNION的速度会慢很多。一般来说,如果使用UNION ALL能满足要求的话,尽量使用UNION ALL。
(4)Count (*)和 Count(1)以及 Count(column)的区别
- 一般情况,Select Count (*)和Select Count(1)返回结果一样;
- 假如表没有主键(Primary key),那么count(1)比count(*)快;
- 如果有主键,那主键作为count的条件时 count(主键)最快;
- 如果你的表只有一个字段,那count(*)最快;
- count(*) 跟 count(1) 的结果一样,都包括对NULL的统计,而count(column) 不包括NULL的统计
(5)查询的模糊匹配
- 尽量避免在一个复杂查询里面使用 LIKE '%parm1%' ,百分号会导致相关列的索引无法使用,最好不要用。
(6)复杂操作
- 部分UPDATE、SELECT 语句 写得很复杂(经常嵌套多级子查询),可以适当拆成几步,先生成一些临时表,再进行关联操作。
- 尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。