Oracle数据库索引培训——201609
1. 数据库发展概要介绍 http://www.cbdio.com/BigData/2016-02/24/content_4651751.htm 观点:关系数据库在子应用中还是会继续存在,随着数据大爆炸的不断升级,关系数据库将会更方便的迁移到大数据平台。大数据引导消费、大数据支撑模型、大数据辅助决策 将 会是一个商业常态。
2.Oracle优化器(RBO与CBO)http://blog.itpub.net/26738398/viewspace-1058763/ Oracle的优化器有两种,基于规则的优化器(RBO)和基于代价的优化器(CBO)。 在8i之前,Oracle使用的是RBO(Rule Based Optimizer,基于规则的优化器),他的执行非常简单,就是在优化器里面嵌入15中规则,执行SQL语句符合哪种规则,就按照规则定制出相应的SQL执行计划。由于他是一种过时呆板的优化器,在10g以后的版本中已经被踢出掉了。从8i开始,Oracle引入了CBO(Cost Based Optimizer,基于代价的优化器),他的思路是让Oracle获取所有的执行计划的相关信息,通过这些信息做计算分析,最后得出一个代价最小的执行计划作为最终的执行计划.
3. Oracle索引详解http://www.52php.cn/article/p-egimbydt-bks.html
3.1 索引按存储方法分类,可以分为2类:B*树索引和位图索引。 1)二元高度(binary height) http://www.52php.cn/article/p-qhgimtfn-bad.html 2) ORACLE B树索引概念的理解 http://www.52php.cn/article/p-frxdioyb-bad.html 3)位图索引概念的理解 http://www.52php.cn/article/p-vilvdpnc-bad.html http://www.52php.cn/article/p-tvcaqsev-bad.html
4.ORACLE性能优化之SQL语句优化4.1 Oracle优化的基本原则http://www.cnblogs.com/rootq/archive/2008/11/17/1334727.html以下是从上面的博文摘取出来规则(包括规则的序号): (1)选择最有效率的表名顺序(只在基于规则的优化器中有效): ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询,那就需要选择交叉表(intersection table)作为基础表,交叉表是指那个被其他表所引用的表. (2)WHERE子句中的连接顺序.: ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾. (3)SELECT子句中避免使用 ‘ * ‘: ORACLE在解析的过程中,会将'*' 依次转换成所有的列名,这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间 (11)用Where子句替换HAVING子句: (14)使用表的别名(Alias): 当在SQL语句中连接多个表时,请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误. (15)用EXISTS替代IN、用NOT EXISTS替代NOT IN: 在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下,使用EXISTS(或NOT EXISTS)通常将提高查询的效率. 在子查询中,NOT IN子句将执行一个内部的排序和合并. 无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历). 为了避免使用NOT IN,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS. 例子: (高效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND EXISTS (SELECT ‘X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB') (低效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB') (21)避免在索引列上使用NOT 通常, 我们要避免在索引列上使用NOT,NOT会产生在和在索引列上使用函数相同的影响. 当ORACLE”遇到”NOT,他就会停止使用索引转而执行全表扫描. (22)避免在索引列上使用计算. WHERE子句中,如果索引列是函数的一部分.优化器将不使用索引而使用全表扫描. 举例: 低效: SELECT … FROM DEPT WHERE SAL * 12 > 25000; 高效: SELECT … FROM DEPT WHERE SAL > 25000/12; (26)避免在索引列上使用IS NULL和IS NOT NULL 避免在索引中使用任何可以为空的列,ORACLE将无法使用该索引.对于单列索引,如果列包含空值,索引中将不存在此记录. 对于复合索引,如果每个列都为空,索引中同样不存在此记录. 如果至少有一个列不为空,则记录存在于索引中.举例: 如果唯一性索引建立在表的A列和B列上,并且表中存在一条记录的A,B值为(123,null),ORACLE将不接受下一条具有相同A,B值(123,null)的记录(插入). 然而如果所有的索引列都为空,ORACLE将认为整个键值为空而空不等于空. 因此你可以插入1000 条具有相同键值的记录,当然它们都是空! 因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引. 低效: (索引失效) SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL; 高效: (索引有效) SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0; (27)总是使用索引的第一个列: 如果索引是建立在多个列上,只有在它的第一个列(leading column)被where子句引用时,优化器才会选择使用该索引. 这也是一条简单而重要的规则,当仅引用索引的第二个列时,优化器使用了全表扫描而忽略了索引 (30)避免改变索引列的类型.: 当比较不同数据类型的数据时,ORACLE自动对列进行简单的类型转换. 假设 EMPNO是一个数值类型的索引列. SELECT … FROM EMP WHERE EMPNO = ‘123' 实际上,经过ORACLE类型转换,语句转化为: SELECT … FROM EMP WHERE EMPNO = TO_NUMBER(‘123') 幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变. 现在,假设EMP_TYPE是一个字符类型的索引列. SELECT … FROM EMP WHERE EMP_TYPE = 123 这个语句被ORACLE转换为: SELECT … FROM EMP WHERETO_NUMBER(EMP_TYPE)=123 因为内部发生的类型转换,这个索引将不会被用到! 为了避免ORACLE对你的SQL进行隐式的类型转换,最好把类型转换用显式表现出来. 注意当字符和数值比较时,ORACLE会优先转换数值类型到字符类型 4.2 ORACLE的HINT详解hints是oracle提供的一种机制,用来告诉优化器按照我们的告诉它的方式生成执行计划。我们可以用hints来实现.http://www.2cto.com/database/201305/211384.html http://czmmiao.iteye.com/blog/1478465 4.3 Oracle查询计划例子(有兴趣的自行阅读)执行计划分析才是sql优化的关键,可以根据实际执行计划来检查是否按照预想的来执行。http://www.cnblogs.com/cxxjohnson/p/5686721.html 备注:合理的使用Hint来引导执行计划 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |