写在最前面
这门课没学太明白,若有问题请批评指正(っ•̀ω•́)っ✎⁾⁾ ,鞠躬
一、实验目的:
以分布式数据库管理系统Oracle为例,通过查询计划的执行了解Oracle产品的优化程序基于代价的优化器(Cost-Based Optimizer, CBO),明确Oracle CBO查询优化器架构及其使用方法。
二、实验内容:
(1)在集中式环境下,构建相应的示例表,通过发起对不同场景下的查询,实际了解CBO优化器的优化策略执行过程。
(2)在分布式环境下,构建相应的示例表,通过发起分布式查询,实际理解CBO如何确定局部执行代价,并利用相关优化技术的理论方法得到最优的执行计划。
实验重点:在分布式环境下,通过发起分布式查询样例,在物理执行层面剖析Oracle的CBO技术。
实验难点:对Oracle数据库管理系统下CBO技术,通过语言层面的操作与执行实际了解它的优化机制与理论。
三、实验结果:
示例表的建立过程以及不同场景下的查询执行,优化过程的语言操作层描述。
参考教材:P131
参考:Navicat查看Oracle数据库执行计划
基于规则的优化RBO
当数据库执行一条query语句的时候必须遵循预先定义好的一系列规则(比如oracle的15条规则,排名越靠前的执行引擎认为效率越高)来确定执行过程,它不关心访问表的数据分布情况,仅仅凭借规则经验来确定,所以说是一种比较粗放的优化策略。
基于代价的优化CBO
让执行引擎依据预先存储到数据库中表的一些实时更新的统计信息来选择出最优代价最小的执行计划来执行query语句,CBO会根据统计信息来生成一组可能被使用到的执行计划,进而估算出每个计划的代价,从而选择出代价最小的交给执行器去执行。
1. 建立不同的表,对比CBO的查询时间。
开启SQL查询时间的显示:
先将现有表中的数据提取到新表,然后建立索引,之后在SQL中打开执行计划,执行语句,查看执行结果
explain plan for 要执行的语句;
执行:创建索引后查找表,查找索引,查询优化方式,通过主键查询表,通过RBO优化方式以索引查询表。
--create index my on help(seq); --select * from user_tables; --select * from user_indexes;
–查询当前数据库CBO的优化方式show parameter optimizer_mode;
select * from help where seq='1'; --select /*+RULE*/* From help where seq='1'; --execution plan
执行解释:
①先执行From ->Where ->Group By->Order By,避免全表扫。
②执行From 从右往左进行执行。因此选择记录条数最少的表放在右边。
③Where执行顺序是从后向前执行,过滤最大数量记录的条件写在Where子句的末尾,而对于多表之间的连接,则写在之前。进行连接时,可以去掉大多不重复的项。
④SELECT中避免使用(),ORACLE在解析的过程中, 通过查询数据字典完成将’’ 依次转换成所有的列名的工作,耗费更多时间。但在count(*)的执行中不需要遵守上述内容,速度是相同的。
参考:https://blog.csdn.net/wangdonghao137/article/details/50149203
测试表说明:
t_mass表:无分区、无索引
t_mass_hash:有哈希分区、无索引
t_mass_ind:无分区、有索引(索引在id列上)
t_mass_hash_ind:有哈希分区、并有索引(索引在id列上)
–创建表无分区 在创建时拷贝数据 --耗时Elapsed: 00:00:19.57
create table t_mass_ind
(id,name)
as (select id,name from t_mass);
–1.创建临时表空间
create Temporary Tablespace MASS_TEMP TempFile 'D:\oracle\product\10.2.0\oradata\orcl\MASS_TEMP_0.dbf'--不同操作系统上此路径应该按实际情况设置,但文件名可以不变 size 64M --大小 autoextend on --自动扩展磁盘空间 next 16M maxsize 2048M --步进及最大容量 extent management local;
–2.创建永久表空间
create Tablespace MASS_DATA logging datafile 'D:\oracle\product\10.2.0\oradata\orcl\MASS_DATA_0.dbf' size 64M autoextend on next 16M maxsize 2048M extent management local;
–创建表后建立索引,–耗时Elapsed: 00:00:52.42
create index ind_t_mass_ind on t_mass_ind(id);
–这里注意,当表上无分区时,此sql语句后不能加local
–创建表 哈希分区16个 在创建时拷贝数据 --耗时Elapsed: Elapsed: 00:00:26.76
create table t_mass_hash_ind (id,name) partition by hash(id) partitions 16 as (select id,name from t_mass);
–创建表后建立索引,–耗时Elapsed: 00:00:36.78
create index ind_t_mass_hash_ind on t_mass_hash_ind(id) local; --这里注意,当表上无分区时,此sql语句后不能加local
(图源网络)
2. 执行计划的优化策略
① 建立索引前的执行代价为3,且查询方式为全表扫描。
② 建立索引后的执行代价为1,且查询方式为索引扫描,对象变为index_EMPNO。
预期:INDEX(FULL SCAN) COST(1)
查询优化器有rule-based-optimizer(基于规则的查询优化器) 和Cost-Based-optimizer(基于成本的查询优化器)。其中基于规则的查询优化器在10g版本中消失。对于规则查询,其最后查询的是全表扫描。而CBO则会根据统计信息进行最后的选择。
实际:
原因:由于表数据过少,所以查询代价不变。
3. 附选:在分布式环境下,了解CBO是如何利用分区视图减少查询代价。
① 主机建表(总部信息索引表)
CREATE TABLE student( sno VARCHAR2 ( 10 ) ) ; insert into student values('1'); insert into student values('2'); insert into student values('3'); insert into student values('4'); insert into student values('5'); insert into student values('6'); insert into student values('7'); insert into student values('8');
② 主机建表(总部具体信息表)
CREATE TABLE student_partition_windows ( sno VARCHAR2 ( 10 ), sname VARCHAR2 ( 20 ), sage NUMBER ( 2 ), score NUMBER ( 2 ) ) ;
insert into student_partition_windows values('5','我叫分区1',12,55); insert into student_partition_windows values('6','我叫分区1',12,56); insert into student_partition_windows values('7','我叫分区2',12,76); insert into student_partition_windows values('8','我叫分区3',12,86);
③ 虚拟机建表(分部具体信息表)
先删除之前创建错误的表,然后再次创建。
drop table student_partition; CREATE TABLE student_partition ( sno VARCHAR2 ( 10 ), sname VARCHAR2 ( 20 ), sage NUMBER ( 2 ), score NUMBER ( 2 ) ) ;
插入数据
insert into student_partition values('1','我叫分区1',12,55); insert into student_partition values('2','我叫分区1',12,56); insert into student_partition values('3','我叫分区2',12,76); insert into student_partition values('4','我叫分区3',12,86);
④ 建立主机和虚拟机表的视图(总部和分部信息汇总表)
drop database link link1; --create database link link1 connect to system identified by Ab1234 using 'orcl'; create database link link1 connect to system identified by Ab123456 using 'orclVM'; Create View student12 As Select student_partition_windows.sno,sname,sage,score From student,student_partition_windows where student.sno=student_partition_windows.sno Union Select student_partition.sno,sname,sage,score From student,student_partition@link1 where student.sno=student_partition.sno@link1
union:将两个查询的结果集进行追加在一起,它不会引起列的变化。 由于是追加操作,需要两个结果集的列数应该是相关的,并且相应列的数据类型也应该相当的。union 返回两个结果集,同时将两个结果集重复的项进行消除。如果不进行消除,用UNOIN ALL。
通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果,对索引列使用OR将造成全表扫描。
注意:以上规则只针对多个索引列有效。如果有column没有被索引, 查询效率可能会因为没有选择OR而降低。
参考:https://blog.csdn.net/qq_47527477/article/details/120976245
注意:需要设置视图参数partition_view_enabled=true
partition_view_enabled 优化程序,如果将 PARTITION_VIEW_ENABLED 设置为 TRUE,该优化程序将剪除 (或跳过) 分区视图中不必要的表访问。该参数还能更改基于成本的优化程序从基础表统计信息计算分区视图统计信息的方式。
⑤创建视图后,在本地数据库用户下,查询成绩为55的全部学生信息。
SELECT * FROM student12 WHERE score = '55';
CBO对查询场地个数进行了约简,由于需要在数据全部位于远程数据库中,故可以将其余场地的数据过滤掉,只在远程数据库中执行查询。
4. 相关资料
参考:https://blog.csdn.net/haiross/article/details/27304969
1、CBO和RBO,如果SQL中涉及的表都是远端的,那么该语句在远端执行,在得到结果后返回调用端。当查询包含了本地表和远端表时,oracle总是先把远端表的数据通过网络传送到SQL的发起端,再跟本地表进行关联得到最终结果。
2、可以通过driving_site的hint来执行SQL在那端执行。这个hints在某些特定条件下的分布式查询调优非常有用。
3、当Oracle数据库拿到SQL语句时,其会根据查询优化器分析该语句,并根据分析结果生成查询执行计划。数据库是执行的查询计划,而不是Sql语句。
4、ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表。
5. 报错及解决
报错1:invalid username/password; logon denied ORA-02063: 紧接着 line (起自 LINK1)
解决:删除链接后,通过用户密码建立链接。
注意,system为用户名,Ab123456为密码,'orclVM’为虚拟机数据库名。
这样,就建立了一个使用本地服务orcl(实际上是指向服务器2的服务orclVM)、名为link1的数据库链接,该链接通过服务器2的用户名system登入对方数据库。
报错2:未明确定义列
原因:百度说是因为查询的两表中存在相同的列名
解决:将列名前加上所属表