Oracle 查询优化器 -- 改写查询语句

来源:互联网 发布:现在做淘宝还有前途吗 编辑:程序博客网 时间:2024/05/18 05:13

-- Start

当我们执行一条查询语句的时候,我们只告诉 Oracle 我们想要哪些数据,至于数据在哪里,怎么找,那是查询优化器的事情,优化器需要改写查询语句,决定访问路径(如:全表扫描,快速全索引扫描,索引扫描),决定表联接顺序等。至于选择哪种方式,优化器需要根据数据字典做出判断。

那优化器如何改写查询语句呢?

第一种方法叫合并视图,如果你的查询语句中引用了视图,那么优化器会把视图合并到查询中,下面是一个简单的例子,需要注意的是优化器也不是神,如果你的视图包含集合操作符,聚合函数,Group by 等,优化器也傻了,不知道如何合并了。

-- 视图定义CREATE VIEW employees_50_vw ASSELECT employee_id, last_name, job_id, salary, commission_pct, department_idFROM employeesWHERE department_id = 50;-- 查询语句SELECT employee_idFROM employees_50_vwWHERE employee_id > 150;-- 合并视图后的查询语句SELECT employee_idFROM employeesWHERE department_id = 50AND employee_id > 150;

第二种方法叫谓词推进(Predicate Pushing),对于那些无法执行合并视图的查询语句,Oracle 会把查询语句中的条件挪到视图中,下面是一个简单的例子。

-- 视图定义CREATE VIEW all_employees_vw AS(SELECT employee_id, last_name, job_id, commission_pct, department_id FROM employees)UNION(SELECT employee_id, last_name, job_id, commission_pct, department_id FROM contract_workers);-- 查询语句的查询语句SELECT last_nameFROM all_employees_vwWHERE department_id = 50;-- 谓词推进SELECT last_nameFROM ( SELECT employee_id, last_name, job_id, commission_pct, department_id FROM employeesWHERE department_id=50 -- 注意此处UNIONSELECT employee_id, last_name, job_id, commission_pct, department_id FROM contract_workersWHERE department_id=50 -- 注意此处);

第三种方法是将非嵌套子查询转化为表连接。下面是一个简单的例子。需要注意的是,并不是所有的非嵌套子查询都能转化为表连接,对于下面的例子而言,如果 customers.cust_id 不是主键,转化后会产生笛卡尔集。

-- 非嵌套子查询SELECT *FROM salesWHERE cust_id IN (SELECT cust_id FROM customers);-- 表连接SELECT sales.*FROM sales, customersWHERE sales.cust_id = customers.cust_id;

第四种方法是使用物化视图改写查询,物化视图是将一个查询的结果集保存在一个表中,如果你的查询语句和某个物化视图兼容,那么 Oracle 就可以直接从物化视图中取得数据。

--更多参见:Oracle SQL 优化精萃

-- 声明:转载请注明出处

-- Last edited on 2015-07-10

-- Created by ShangBo on 2015-07-10

-- End


0 0