Oracle 查询优化器 -- 改写查询语句
2015-07-10 17:17
459 查看
-- Start
当我们执行一条查询语句的时候,我们只告诉 Oracle 我们想要哪些数据,至于数据在哪里,怎么找,那是查询优化器的事情,优化器需要改写查询语句,决定访问路径(如:全表扫描,快速全索引扫描,索引扫描),决定表联接顺序等。至于选择哪种方式,优化器需要根据数据字典做出判断。
那优化器如何改写查询语句呢?
第一种方法叫合并视图,如果你的查询语句中引用了视图,那么优化器会把视图合并到查询中,下面是一个简单的例子,需要注意的是优化器也不是神,如果你的视图包含集合操作符,聚合函数,Group by 等,优化器也傻了,不知道如何合并了。
第二种方法叫谓词推进(Predicate Pushing),对于那些无法执行合并视图的查询语句,Oracle 会把查询语句中的条件挪到视图中,下面是一个简单的例子。
第三种方法是将非嵌套子查询转化为表连接。下面是一个简单的例子。需要注意的是,并不是所有的非嵌套子查询都能转化为表连接,对于下面的例子而言,如果 customers.cust_id 不是主键,转化后会产生笛卡尔集。
第四种方法是使用物化视图改写查询,物化视图是将一个查询的结果集保存在一个表中,如果你的查询语句和某个物化视图兼容,那么 Oracle 就可以直接从物化视图中取得数据。
--更多参见:Oracle SQL 优化精萃
-- 声明:转载请注明出处
-- Last edited on 2015-07-10
-- Created by ShangBo on 2015-07-10
-- End
当我们执行一条查询语句的时候,我们只告诉 Oracle 我们想要哪些数据,至于数据在哪里,怎么找,那是查询优化器的事情,优化器需要改写查询语句,决定访问路径(如:全表扫描,快速全索引扫描,索引扫描),决定表联接顺序等。至于选择哪种方式,优化器需要根据数据字典做出判断。
那优化器如何改写查询语句呢?
第一种方法叫合并视图,如果你的查询语句中引用了视图,那么优化器会把视图合并到查询中,下面是一个简单的例子,需要注意的是优化器也不是神,如果你的视图包含集合操作符,聚合函数,Group by 等,优化器也傻了,不知道如何合并了。
-- 视图定义 CREATE VIEW employees_50_vw AS SELECT employee_id, last_name, job_id, salary, commission_pct, department_id FROM employees WHERE department_id = 50; -- 查询语句 SELECT employee_id FROM employees_50_vw WHERE employee_id > 150; -- 合并视图后的查询语句 SELECT employee_id FROM employees WHERE department_id = 50 AND 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_name FROM all_employees_vw WHERE department_id = 50; -- 谓词推进 SELECT last_name FROM ( SELECT employee_id, last_name, job_id, commission_pct, department_id FROM employees WHERE department_id=50 -- 注意此处 UNION SELECT employee_id, last_name, job_id, commission_pct, department_id FROM contract_workers WHERE department_id=50 -- 注意此处 );
第三种方法是将非嵌套子查询转化为表连接。下面是一个简单的例子。需要注意的是,并不是所有的非嵌套子查询都能转化为表连接,对于下面的例子而言,如果 customers.cust_id 不是主键,转化后会产生笛卡尔集。
-- 非嵌套子查询 SELECT * FROM sales WHERE cust_id IN (SELECT cust_id FROM customers); -- 表连接 SELECT sales.* FROM sales, customers WHERE sales.cust_id = customers.cust_id;
第四种方法是使用物化视图改写查询,物化视图是将一个查询的结果集保存在一个表中,如果你的查询语句和某个物化视图兼容,那么 Oracle 就可以直接从物化视图中取得数据。
--更多参见:Oracle SQL 优化精萃
-- 声明:转载请注明出处
-- Last edited on 2015-07-10
-- Created by ShangBo on 2015-07-10
-- End
相关文章推荐
- [转]asp+oracle分页
- 关于Access导入Oracle会产生双引号的问题
- oracle12c新特点之可插拔数据库(Pluggable Database,PDB)
- Oracle学习(十八)之控制文件、日志文件、数据文件及配置文件管理总结
- oracle 表 主键自增
- 【技术支持】Oracle plsql中的having子句并非都能改写成where子句。having子句的适用场景。
- Oracle创建类似mysql AUTO_INCREMENT自增列
- 【转】CentOS/RHEL/OracleLinux使用UDEV配置ASMDISK
- oracle参数与启停
- Oracle-BPM(二)
- oracle定时任务JOB
- ORACLE密码过期解决方法
- Oracle-BPM(一)
- Oracle数据库备份还原
- 不安装oracle客户端,用plsql连接oracle
- oracle-创建JOB
- An Overview of Oracle Business Intelligence Apps.
- Python导入oracle数据的方法
- ORACLE创建定时任务
- oracle“记录被另一个用户锁住”