Oracle 如何处理给定的 SQL 语句

Posted

技术标签:

【中文标题】Oracle 如何处理给定的 SQL 语句【英文标题】:How Oracle processes the given SQL statement 【发布时间】:2015-04-04 17:23:17 【问题描述】:

您能否解释一下查询将如何执行?请逐步解释...

select
  max(salary),
  country_id
from (
  select
    salary,
    department_id,
    location_id,
    country_id
  from
    HR.EMPLOYEES
  natural join
    HR.DEPARTMENTS
  natural join
    HR.LOCATIONS
)
group by country_id;

【问题讨论】:

优化器将根据它对您的机器和数据细节的了解来确定执行的分步指令。 生成解释计划并自己分析。 我不认为它会被执行。我认为它会引发ORA-00918: column ambiguously defined 错误。 @DavidFaber 为什么?子查询只有一层深。它执行得很好。我在回答中使用了相同的查询。 【参考方案1】:

了解SQL执行步骤的最好方法是生成解释计划,从最里面的ID到最外面的分析。

SQL> explain plan for
  2  select
  3    max(salary),
  4    country_id
  5  from (
  6    select
  7      salary,
  8      department_id,
  9      location_id,
 10      country_id
 11    from
 12      HR.EMPLOYEES
 13    natural join
 14      HR.DEPARTMENTS
 15    natural join
 16      HR.LOCATIONS
 17  )
 18  group by country_id;

Explained.

SQL>

让我们以可读的格式显示解释计划:

SQL> SELECT * FROM TABLE(dbms_xplan.display);

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------
Plan hash value: 1571404374

----------------------------------------------------------------------------------------------
| Id  | Operation                      | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |             |    11 |   297 |     8   (0)| 00:00:01 |
|   1 |  HASH GROUP BY                 |             |    11 |   297 |     8   (0)| 00:00:01 |
|*  2 |   HASH JOIN                    |             |    11 |   297 |     8   (0)| 00:00:01 |
|   3 |    MERGE JOIN                  |             |    11 |   176 |     5   (0)| 00:00:01 |
|   4 |     TABLE ACCESS BY INDEX ROWID| LOCATIONS   |    23 |   138 |     2   (0)| 00:00:01 |
|   5 |      INDEX FULL SCAN           | LOC_ID_PK   |    23 |       |     1   (0)| 00:00:01 |
|*  6 |     SORT JOIN                  |             |    11 |   110 |     3   (0)| 00:00:01 |
|*  7 |      TABLE ACCESS FULL         | DEPARTMENTS |    11 |   110 |     3   (0)| 00:00:01 |
|   8 |    TABLE ACCESS FULL           | EMPLOYEES   |   107 |  1177 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access("EMPLOYEES"."DEPARTMENT_ID"="DEPARTMENTS"."DEPARTMENT_ID" AND
              "EMPLOYEES"."MANAGER_ID"="DEPARTMENTS"."MANAGER_ID")
   6 - access("DEPARTMENTS"."LOCATION_ID"="LOCATIONS"."LOCATION_ID")
       filter("DEPARTMENTS"."LOCATION_ID"="LOCATIONS"."LOCATION_ID")
   7 - filter("DEPARTMENTS"."MANAGER_ID" IS NOT NULL)

Note
-----
   - this is an adaptive plan

28 rows selected.

SQL>

查询转换器可以决定是否重写查询,以便优化器可以生成更好的执行计划。

来自documentation:

估算器

估算器确定给定执行计划的总成本。 估计器生成三种不同类型的度量来实现 这个目标:

选择性

此度量表示行集中的一小部分行。选择性与查询谓词相关联,例如 last_name='Smith', 或谓词的组合。

基数

此度量表示行集中的行数。

费用

此度量表示使用的工作单元或资源。查询优化器使用磁盘 I/O、CPU 使用率和内存使用率作为工作单元。

如果统计信息可用,则估算器使用它们来计算 措施。统计数据提高了准确度 措施。

我建议阅读我上面提供的文档链接。

【讨论】:

以上是关于Oracle 如何处理给定的 SQL 语句的主要内容,如果未能解决你的问题,请参考以下文章

如何处理异常并执行剩余语句?

HiveQL 逻辑过滤语句如何处理 NULL 值

sql语句写法——as后的别名中有括号怎么处理(Oracle)

python:如何处理if语句中的NaN数据[重复]

Oracle如何处理SQL中的存储函数调用?

这个三元运算符如何处理这个语句?