Oracle SQL语句优化
- 格式:pdf
- 大小:546.32 KB
- 文档页数:9
ORACLE常用SQL优化hint语句在SQL语句优化过程中,我们经常会用到hint,现总结一下在SQL优化过程中常见Oracle HINT的用法:1. /*+ALL_ROWS*/表明对语句块选择基于开销的优化方法,并获得最佳吞吐量,使资源消耗最小化.例如:SELECT /*+ALL+_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO=’SCOTT’;2. /*+FIRST_ROWS*/表明对语句块选择基于开销的优化方法,并获得最佳响应时间,使资源消耗最小化.例如:SELECT /*+FIRST_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO=’SCOTT’;3. /*+CHOOSE*/表明如果数据字典中有访问表的统计信息,将基于开销的优化方法,并获得最佳的吞吐量;表明如果数据字典中没有访问表的统计信息,将基于规则开销的优化方法;例如:SELECT /*+CHOOSE*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO=’SCOTT’;4. /*+RULE*/表明对语句块选择基于规则的优化方法.例如:SELECT /*+ RULE */ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO=’SCOTT’;5. /*+FULL(TABLE)*/表明对表选择全局扫描的方法.例如:SELECT /*+FULL(A)*/ EMP_NO,EMP_NAM FROM BSEMPMS A WHERE EMP_NO=’SCOTT’;6. /*+ROWID(TABLE)*/提示明确表明对指定表根据ROWID进行访问.例如:SELECT /*+ROWID(BSEMPMS)*/ * FROM BSEMPMS WHERE ROWID>=’AAAAAAAAAAAAAA’AND EMP_NO=’SCOTT’;7. /*+CLUSTER(TABLE)*/提示明确表明对指定表选择簇扫描的访问方法,它只对簇对象有效.例如:SELECT /*+CLUSTER */ BSEMPMS.EMP_NO,DPT_NO FROM BSEMPMS,BSDPTMSWHERE DPT_NO=’TEC304′ AND BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;8. /*+INDEX(TABLE INDEX_NAME)*/表明对表选择索引的扫描方法.例如:SELECT /*+INDEX(BSEMPMS SEX_INDEX) USE SEX_INDEX BECAUSE THERE ARE FEWMALE BSEMPMS */ FROM BSEMPMS WHERE SEX=’M';9. /*+INDEX_ASC(TABLE INDEX_NAME)*/表明对表选择索引升序的扫描方法.例如:SELECT /*+INDEX_ASC(BSEMPMS PK_BSEMPMS) */ FROM BSEMPMS WHERE DPT_NO=’SCOTT’;10. /*+INDEX_COMBINE*/为指定表选择位图访问路经,如果INDEX_COMBINE中没有提供作为参数的索引,将选择出位图索引的布尔组合方式.例如:SELECT /*+INDEX_COMBINE(BSEMPMS SAL_BMI HIREDATE_BMI)*/ * FROM BSEMPMSWHERE SAL<5000000 AND HIREDATE11. /*+INDEX_JOIN(TABLE INDEX_NAME)*/提示明确命令优化器使用索引作为访问路径.例如:SELECT /*+INDEX_JOIN(BSEMPMS SAL_HMI HIREDATE_BMI)*/ SAL,HIREDATE FROM BSEMPMS WHERE SAL<60000;12. /*+INDEX_DESC(TABLE INDEX_NAME)*/表明对表选择索引降序的扫描方法.例如:SELECT /*+INDEX_DESC(BSEMPMS PK_BSEMPMS) */ FROM BSEMPMS WHERE DPT_NO='SCOTT';13. /*+INDEX_FFS(TABLE INDEX_NAME)*/对指定的表执行快速全索引扫描,而不是全表扫描的办法.例如:SELECT /*+INDEX_FFS(BSEMPMS IN_EMPNAM)*/ * FROM BSEMPMS WHERE DPT_NO='TEC305';14. /*+ADD_EQUAL TABLE INDEX_NAM1,INDEX_NAM2,...*/提示明确进行执行规划的选择,将几个单列索引的扫描合起来.例如:SELECT /*+INDEX_FFS(BSEMPMS IN_DPTNO,IN_EMPNO,IN_SEX)*/ * FROM BSEMPMS WHERE EMP_NO='SCOTT' AND DPT_NO='TDC306';15. /*+USE_CONCAT*/对查询中的WHERE后面的OR条件进行转换为UNION ALL的组合查询.例如:SELECT /*+USE_CONCAT*/ * FROM BSEMPMS WHERE DPT_NO='TDC506' AND SEX='M';16. /*+NO_EXPAND*/对于WHERE后面的OR 或者IN-LIST的查询语句,NO_EXPAND将阻止其基于优化器对其进行扩展.例如:SELECT /*+NO_EXPAND*/ * FROM BSEMPMS WHERE DPT_NO='TDC506' AND SEX='M';17. /*+NOWRITE*/禁止对查询块的查询重写操作.18. /*+REWRITE*/可以将视图作为参数.19. /*+MERGE(TABLE)*/能够对视图的各个查询进行相应的合并.例如:SELECT /*+MERGE(V) */ A.EMP_NO,A.EMP_NAM,B.DPT_NO FROM BSEMPMS A (SELET DPT_NO,AVG(SAL) AS AVG_SAL FROM BSEMPMS B GROUP BY DPT_NO) V WHERE A.DPT_NO=V.DPT_NOAND A.SAL>V.AVG_SAL;20. /*+NO_MERGE(TABLE)*/对于有可合并的视图不再合并.例如:SELECT /*+NO_MERGE(V) */ A.EMP_NO,A.EMP_NAM,B.DPT_NO FROM BSEMPMS A (SELECT DPT_NO,AVG(SAL) AS AVG_SAL FROM BSEMPMS B GROUP BY DPT_NO) V WHERE A.DPT_NO=V.DPT_NO AND A.SAL>V.AVG_SAL;21. /*+ORDERED*/根据表出现在FROM中的顺序,ORDERED使ORACLE依此顺序对其连接.例如:SELECT /*+ORDERED*/ A.COL1,B.COL2,C.COL3 FROM TABLE1 A,TABLE2 B,TABLE3 C WHERE A.COL1=B.COL1 AND B.COL1=C.COL1;22. /*+USE_NL(TABLE)*/将指定表与嵌套的连接的行源进行连接,并把指定表作为内部表.例如:SELECT /*+ORDERED USE_NL(BSEMPMS)*/ BSDPTMS.DPT_NO,BSEMPMS.EMP_NO,BSEMPMS.EMP_NAM FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;23. /*+USE_MERGE(TABLE)*/将指定的表与其他行源通过合并排序连接方式连接起来.例如:SELECT /*+USE_MERGE(BSEMPMS,BSDPTMS)*/ * FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;24. /*+USE_HASH(TABLE)*/将指定的表与其他行源通过哈希连接方式连接起来.例如:SELECT /*+USE_HASH(BSEMPMS,BSDPTMS)*/ * FROM BSEMPMS,BSDPTMS WHERE BSEMPMS.DPT_NO=BSDPTMS.DPT_NO;25. /*+DRIVING_SITE(TABLE)*/强制与ORACLE所选择的位置不同的表进行查询执行.例如:SELECT /*+DRIVING_SITE(DEPT)*/ * FROM BSEMPMS,DEPT@BSDPTMS WHERE BSEMPMS.DPT_NO=DEPT.DPT_NO;26. /*+LEADING(TABLE)*/将指定的表作为连接次序中的首表.27. /*+CACHE(TABLE)*/当进行全表扫描时,CACHE提示能够将表的检索块放置在缓冲区缓存中最近最少列表LRU的最近使用端例如:SELECT /*+FULL(BSEMPMS) CAHE(BSEMPMS) */ EMP_NAM FROM BSEMPMS;28. /*+NOCACHE(TABLE)*/当进行全表扫描时,CACHE提示能够将表的检索块放置在缓冲区缓存中最近最少列表LRU的最近使用端例如:SELECT /*+FULL(BSEMPMS) NOCAHE(BSEMPMS) */ EMP_NAM FROM BSEMPMS;29. /*+APPEND*/直接插入到表的最后,可以提高速度.insert /*+append*/ into test1 select * from test4 ;30. /*+NOAPPEND*/通过在插入语句生存期内停止并行模式来启动常规插入.insert /*+noappend*/ into test1 select * from test4 ;---------------------------------------------------------------------------- Optimization Approaches Access MethodsALL_ROWS AND_EQUALCHOOSE CLUSTERFIRST RULES FULLRULE HASHParallel Execution HASH_AJAPPEND*ORDERED HASH_SJ ***STAR**INDEXSTAR_TRANSFORMATION*INDEX_ASCJoin Operations INDEX_COMBINE*DRIVING_SITE*INDEX_DESCUSE_HASH**INDEX_FFS*USE_MERGE MERGE_AJ**USE_NL MERGE_SJ***Additional Hints ROW_IDCACHE USE_CONCATNOCACHE NO_EXPAND***PUSH_SUBQ REWRITE***MERGE***NOREWRITE***NO_MERGE*Join OrdersPUSH_JOIN_PRED***NO_PUSH_JOIN_PRED***NOAPPEND*ORDERED PREDICATES***NOPARALLELPARALLELPARALLEL_INDEX*NO_PARALLEL_INDEX***----------------------------------------------------------------------------并且使用基本的试探法生成执行计划。
Oracle 优化SQL 语句,提高效率我们都了解索引是相关表概念部分,主要是提高检索数据的相关效率,当Oracle 使用了较为复杂的自平衡 B-tree 结构时。
我们一般是通过索引查询数据 比全表扫描要快。
当 Oracle 找出执行查询和 Update 语句的最好路径时 , Oracle 优化将使用索引。
同样在联结多个表时使用索引也能够提高效率。
另一个使用索引的好处是 , 他提供了主键 (primary key ) 的唯一性验证。
那些 LON (或 LONCRAW 数据类型,您能够索引几乎任何的列。
通常,在大型表中使用 索引特别有效. 当然,您也会发现, 在扫描小表时,使用索引同样能提高效率。
虽然使用索引能得到查询效率的提高 , 但是我们也必须注意到他的代价。
索引需要空间来存储 ,也需要定期维护 , 每当有记录在表中增减或索引列被 修改时 , 索引本身也会被修改。
这意味着每条记录的 INSERT ,DELETE , UPDATE 将为此多付出 4、 5 次的磁盘 I/O 。
因为索引需要额外的存储空间和处理,那 些不必要的索引反而会使查询反应时间变慢。
定期的重构索引是有必要的:ALTER INDEX REBUILD1.用 EXISTS 替换 DISTINCT当提交一个包含一对多表信息 ( 比如部门表和雇员表 ) 的查询时,避免在SELECT?句中使用DISTINCT 。
一般能够考虑用 EXIST 替换,EXISTS 使查询更 为迅速,因为RDBM 核心模块将在子查询的条件一旦满足后, 立即返回结果。
例 子:(低效): SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E WHEREEXISTS ( SELECT ‘X' FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO );2.SQL 语句用大写的;因为 Oracle 总是先解析SQL 语句,把小写的字母转 换成大写的再执行。
ORACLESQL语句优化SQL Select语句完整的执行顺序1、from子句组装来自不同数据源的数据;2、where子句基于指定的条件对记录行进行筛选;3> group by子句将数据划分为多个分组;4、使用聚集函数进行计算;5、使用having 了-句筛选分组;6、计算所有的表达式;7、使用order by对结果集进行排序。
说明:—8) SELECT (9) DISTINCT (11) <T0P_spec辻ication> <select_list>—(1) FROM <left_table>—(3) <join_type> JOIN <right_table>—(2) ON <join_condition>—(4) WHERE <where_condit ion>—(5) GROUP BY <group_by_list>—(6) WITH {CUBE ROLLUP}—(7) HAVING <having_condition>~(10) ORDER BY <order_by_list>Oracle SQL性能优化技巧1、选用适合的ORACLE优化器2、访问Table的方式3、共享SQL语句4、选择最有效率的表名顺序(只在基于规则的优化器中有效)5、 WHERE子句中的连接顺序6、SELECT子句中避免使用'* '7、减少访问数据库的次数8、使用DECODE函数来减少处理时间9、整合简单,无关联的数据库访问10、删除重复记录11、用 TRUNCATE 替代 DELETE12、尽量多使用COMMIT13、计算记录条数14、用Where子句替换HAVING子句13、减少对表的查询16、通过内部函数提高SQL效率17、使用表的别名(Alias)18、用 EXISTS 替代 IN19、用 NOT EXISTS 替代 \0T IN20、用表连接替换EXISTS21、用 EXISTS 替换 DISTINCT1.选用适合的ORACLE优化器ORACLE的优化器共有3种a、 RULE (基于规则)b、 COST (基于成本)c、 CHOOSE (选择性)设置缺省的优化器,可以通过对init. ora文件中OPTIMIZER.MODE参数的各种声明,如 RULE, COST, CHOOSE, ALL_ROWS, FIRST_ROWS。
oracle sql 优化技巧(实用版3篇)目录(篇1)1.Oracle SQL 简介2.优化技巧2.1 减少访问数据库次数2.2 选择最有效率的表名顺序2.3 避免使用 SELECT2.4 利用 DECODE 函数2.5 设置 ARRAYSIZE 参数2.6 使用 TRUNCATE 替代 DELETE2.7 多使用 COMMIT 命令2.8 合理使用索引正文(篇1)Oracle SQL 是一款广泛应用于各类大、中、小微机环境的高效、可靠的关系数据库管理系统。
为了提高 Oracle SQL 的性能,本文将为您介绍一些优化技巧。
首先,减少访问数据库的次数是最基本的优化方法。
Oracle 在内部执行了许多工作,如解析 SQL 语句、估算索引的利用率、读数据块等,这些都会大量耗费 Oracle 数据库的运行。
因此,尽量减少访问数据库的次数,可以有效提高系统性能。
其次,选择最有效率的表名顺序也可以明显提升 Oracle 的性能。
Oracle 解析器是按照从右到左的顺序处理 FROM 子句中的表名,因此,合理安排表名顺序,可以减少解析时间,提高查询效率。
在执行 SELECT 子句时,应尽量避免使用,因为 Oracle 在解析的过程中,会将依次转换成列名,这是通过查询数据字典完成的,耗费时间较长。
DECODE 函数也是一个很好的优化工具,它可以避免重复扫描相同记录,或者重复连接相同的表,提高查询效率。
在 SQLPlus 和 SQLForms 以及 ProC 中,可以重新设置 ARRAYSIZE 参数。
该参数可以明显增加每次数据库访问时的检索数据量,从而提高系统性能。
建议将该参数设置为 200。
当需要删除数据时,尽量使用 TRUNCATE 语句替代 DELETE 语句。
执行 TRUNCATE 命令时,回滚段不会存放任何可被恢复的信息,所有数据不能被恢复。
因此,TRUNCATE 命令执行时间短,且资源消耗少。
在使用 Oracle 时,尽量多使用 COMMIT 命令。
oracle性能优化,SQL语句全优化,SQL语句执行效率问题oracle性能优化文档共50条选择其中4条1. 选用适合的ORACLE优化器ORACLE的优化器共有3种: a. RULE (基于规则) b. COST (基于成本) c. CHOOSE (选择性)设置缺省的优化器,可以通过对init.ora文件中OPTIMIZER_MODE参数的各种声明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS . 你当然也在SQL句级或是会话(session)级对其进行覆盖. 为了使用基于成本的优化器(CBO, Cost-Based Optimizer) , 你必须经常运行analyze 命令,以增加数据库中的对象统计信息(object statistics)的准确性. 如果数据库的优化器模式设置为选择性(CHOOSE),那么实际的优化器模式将和是否运行过analyze命令有关. 如果table已经被analyze过, 优化器模式将自动成为CBO , 反之,数据库将采用RULE形式的优化器. 在缺省情况下,ORACLE采用CHOOSE优化器, 为了避免那些不必要的全表扫描(full table scan) , 你必须尽量避免使用CHOOSE优化器,而直接采用基于规则或者基于成本的优化器.2. 访问Table的方式ORACLE 采用两种访问表中记录的方式:a. 全表扫描全表扫描就是顺序地访问表中每条记录. ORACLE采用一次读入多个数据块(database block)的方式优化全表扫描,这样的访问方式是效率最低的.b. 通过ROWID访问表你可以采用基于ROWID的访问方式情况,提高访问表的效率, , ROWID包含了表中记录的物理位置信息..ORACLE采用索引(INDEX)实现了数据和存放数据的物理位置(ROWID)之间的联系. 通常索引提供了快速访问ROWID的方法,因此那些基于索引列的查询就可以得到性能上的提高.3. 共享SQL语句为了不重复解析相同的SQL语句,在第一次解析之后, ORACLE将SQL语句存放在内存中.这块位于系统全局区域SGA(system global area)的共享池(shared buffer pool)中的内存可以被所有的数据库用户共享. 因此,当你执行一个SQL语句(有时被称为一个游标)时,如果它和之前的执行过的语句完全相同, ORACLE就能很快获得已经被解析的语句以及最好的执行路径. ORACLE的这个功能大大地提高了SQL的执行性能并节省了内存的使用. 可惜的是ORACLE只对简单的表提供高速缓冲(cache buffering) ,这个功能并不适用于多表连接查询. 数据库管理员必须在init.ora中为这个区域设置合适的参数,当这个内存区域越大,就可以保留更多的语句,当然被共享的可能性也就越大了. 当你向ORACLE 提交一个SQL语句,ORACLE会首先在这块内存中查找相同的语句. 这里需要注明的是,ORACLE对两者采取的是一种严格匹配,要达成共享,SQL语句必须完全相同(包括空格,换行等). 共享的语句必须满足三个条件:A. 字符级的比较: 当前被执行的语句和共享池中的语句必须完全相同. 例如:SELECT * FROM EMP;和下列每一个都不同SELECT * from EMP;Select * From Emp;SELECT * FROM EMP;B. 两个语句所指的对象必须完全相同: 例如:用户对象名如何访问Jack sal_limit private synonymWork_city public synonymPlant_detail public synonymJill sal_limit private synonymWork_city public synonymPlant_detail table owner考虑一下下列SQL语句能否在这两个用户之间共享.SQL 能否共享原因select max(sal_cap) from sal_limit 不能每个用户都有一个private synonym - sal_limit, 它们是不同的对象select count(*) from work_city where sdesc like 'NEW%' 能两个用户访问相同的对象public synonym - work_cityselect a.sdesc,b.location from work_city a , plant_detail b where a.city_id = b.city_id 不能用户jack 通过private synonym访问plant_detail 而jill 是表的所有者,对象不同C. 两个SQL语句中必须使用相同的名字的绑定变量(bind variables) 例如:第一组的两个SQL语句是相同的(可以共享),而第二组中的两个语句是不同的(即使在运行时,赋于不同的绑定变量相同的值)select pin , name from people where pin = :blk1.pin;select pin , name from people where pin = :blk1.pin;select pin , name from people where pin = :blk1.ot_ind;select pin , name from people where pin = :blk1.ov_ind;4. 选择基础表Oracle的SQL语句执行效率问题查找与解决方法一、识别占用资源较多的语句的方法(4种方法)1. 测试组和最终用户反馈的与反应缓慢有关的问题。
S ql语句优化原则一、优化原则1、避免使用硬编码,改用绑定变量实现。
举例:String str =’ select * from t_zx_ryjbxxb where xm=’+params;上面这条语句使用了硬编码,使用这种方式存在两方面问题:每次执行sql语句时都需要重新解析sql语句;可能会遭遇sql注入攻击。
如在上面的语句中输入张三' or 1='1,则会把所有的记录都显示出来。
解决的方法就是使用占位符代替硬编码。
如下:String str =’select * from t_zx_ryjbxxb where xm=?’;2、当插入的数据为数据表中的记录数量的10%以上,首先需要删除该表的索引来提高数据的插入效率,当数据插入后,再建立索引。
3、避免在索引列上使用函数或计算,在where子句中,如果索引是函数的一部分,优化器将不再使用索引而使用全表扫描。
举例:低效:select * from dept where sal*12 >2500;高效:select * from dept where sal>2500/12;4、避免在索引列上使用not和“!=”,索引只能告诉什么存在于表中,而不能告诉什么不存在于表中,当数据库遇到not 和“!=”时,就会停止使用索引而去执行全表扫描。
5、使用关联查询替代in ,可以提高查询的效率。
6、使用not exists子查询替代not in。
在子查询中,NOT IN子句将执行一个内部的排序和合并。
无论在哪种情况下,NOT IN都是最低效的(因为它对子查询中的表执行了一个全表遍历)。
为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS.举例:select * from t_zx_ryjbxxb where rybh not in(select rybh from t_zx_cqrb) and jwh=''select * from t_zx_ryjbxxb a where not exists(select1from t_zx_cqrb b where a.rybh =b.rybh)使用union-all 替代union:当SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并,然后在输出最终结果前进行排序。
Oracle的SQL语句优化一、操作符优化1、IN 操作符用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格。
但是用IN的SQL性能总是比较低的,从Oracle执行的步骤来分析用IN的SQL 与不用IN的SQL有以下区别:ORACLE试图将其转换成多个表的连接,如果转换不成功则先执行IN里面的子查询,再查询外层的表记录,如果转换成功则直接采用多个表的连接方式查询。
由此可见用IN的SQL至少多了一个转换的过程。
一般的SQL都可以转换成功,但对于含有分组统计等方面的SQL就不能转换了。
推荐方案:在业务密集的SQL当中尽量不采用IN操作符,用EXISTS 方案代替。
2、NOT IN操作符此操作是强列不推荐使用的,因为它不能应用表的索引。
推荐方案:用NOT EXISTS 方案代替3、IS NULL 或IS NOT NULL操作(判断字段是否为空)判断字段是否为空一般是不会应用索引的,因为索引是不索引空值的。
推荐方案:用其它相同功能的操作运算代替,如:a is not null 改为a>0 或a>’’等。
不允许字段为空,而用一个缺省值代替空值,如申请中状态字段不允许为空,缺省为申请。
4、> 及< 操作符(大于或小于操作符)大于或小于操作符一般情况下是不用调整的,因为它有索引就会采用索引查找,但有的情况下可以对它进行优化,如一个表有100万记录,一个数值型字段A,30万记录的A=0,30万记录的A=1,39万记录的A=2,1万记录的A=3。
那么执行A>2与A>=3的效果就有很大的区别了,因为A>2时ORACLE会先找出为2的记录索引再进行比较,而A>=3时ORACLE则直接找到=3的记录索引。
5、LIKE操作符LIKE操作符可以应用通配符查询,里面的通配符组合可能达到几乎是任意的查询,但是如果用得不好则会产生性能上的问题,如LIKE ‘%5400%’ 这种查询不会引用索引,而LIKE ‘X5400%’则会引用范围索引。
Oracle语句优化规则整理目录1.选用适合的ORACLE优化器 --------------------------------------------------------------------- 32.访问Table的方式ORACLE 采用两种访问表中记录的方式---------------------------- 33. 共享SQL语句 ---------------------------------------------------------------------------------------- 34. 选择最有效率的表名顺序(只在基于规则的优化器中有效) --------------------------- 55.WHERE子句中的连接顺序。
-------------------------------------------------------------------- 66.SELECT子句中避免使用‘ * ’------------------------------------------------------------- 67.减少访问数据库的次数-------------------------------------------------------------------------- 78.使用DECODE函数来减少处理时间------------------------------------------------------------ 89.整合简单,无关联的数据库访问 ------------------------------------------------------------- 810.删除重复记录 -------------------------------------------------------------------------------------- 911.用TRUNCATE替代DELETE ----------------------------------------------------------------------- 912.尽量多使用COMMIT ------------------------------------------------------------------------------- 913.计算记录条数 ------------------------------------------------------------------------------------- 1014.用Where子句替换HAVING子句-------------------------------------------------------------- 1015.减少对表的查询 ---------------------------------------------------------------------------------- 1116.通过内部函数提高SQL效率。
千里之行,始于足下。
oracle数据库sql优化Oracle数据库是关系型数据库系统中的一种,在实际应用中,它的性能往往是关键因素之一。
为了提高Oracle数据库的性能,我们可以进行SQL优化。
SQL优化可以减少查询时间、减少资源消耗,提高数据库的整体性能。
首先,我们可以通过索引来优化SQL查询。
索引可以加快数据库的查找速度,减少查询的时间。
在选择索引时,我们可以根据查询的条件和数据的分布情况进行选择,合理选择索引可以大大提高查询效率。
另外,我们还可以考虑使用合适的查询语句。
比如,使用where子句来限制查询的范围,避免全表扫描;使用join来连接多个表,减少查询的次数;使用子查询来优化查询的复杂度等。
此外,在设计数据库时,我们也要考虑到数据的规范化和反规范化。
规范化有助于提高数据的一致性和可维护性,但在查询性能方面可能会受到一定的影响。
因此,对于经常被查询的数据,我们可以考虑进行反规范化,将其冗余存储在多个表中,以提高查询性能。
另外,我们还可以通过设置合适的数据库参数来优化SQL。
比如,通过调整SGA和PGA的大小来合理分配内存资源;通过调整数据库的缓冲池来提高缓存命中率;通过设置合适的日志模式来提高事务处理的效率等。
另外,一个高效的数据库应用还需要考虑到并发访问的问题。
通过合理的数据库设计和应用程序的编写,可以减少多个用户同时访问数据库时的冲突和阻塞,提高并发访问的效率。
第1页/共2页锲而不舍,金石可镂。
总之,通过合理的索引设计、合适的查询语句、数据库参数的优化和并发访问的处理,我们可以大大提高Oracle数据库的性能。
当然,在实际应用中,SQL优化是一个持续的过程,需要不断地进行监控和调整,以保持数据库的高性能。
I.概念
A.选择性和基数
1.选择性:选择性(selectivity)介于0和1之间。
代表选中记录占总数的百分
比。
例如,如果一个操作需要从一张表读取120条记录,在应用一个过滤条
件后返回了其中18条记录,选择性就是0.15(18/120)
2.基数:一个操作返回的记录条数称为基数(cardinality)
3.两者关系:cardinality=selectivity*num_rows
4.查询基数计算:
a.不包含聚合操作
查询语句返回记录数
b.包含聚合函数例如group by
聚合函数:对数据进行汇总处理的函数,如max,min,avg等
根据汇总前的选择条件计算基数。
B.逻辑读和物理读
1.逻辑读:当服务器进程访问到高速缓存(buffer cache)中的一个数据块的时候
就执行了一次逻辑读。
2.物理读:当服务器进程需要访问高速缓存不存在的数据块时产生一次物理读。
需要打开数据文件,读取这个数据块,并且将数据块存放到高速缓存中。
II.执行计划
A.获取执行计划的方法
1.执行SQL语句explain plan,然后查询结果输出表
explain plan for select * from scott.emp where deptno=10 order by ename;
select * from table(dbms_xplan.display);
2.sqlplus或pl/sql developer中的set autotrace traceonly;
可以给出执行计划和逻辑读的统计信息。
在PL/SQL DEVELOPER里按F5
select * from scott.emp where deptno=10 order by ename;
3.查询自动工作量资料库(Automatic Workload Repository)或statspack报表
B.解释执行计划
1.父子关系
执行计划为树形结构。
树的每一个节点都代表一个操作,如,表访问、连接
或排序。
在各节点之间存在父子关系。
规则:
⏹父有多个子
⏹子只有一个父
⏹唯一没有父的操作是树的根
⏹父子关系用缩进来表示。
一个父的所有孩子缩进相同的字符数
⏹父在孩子的前面。
靠孩子最近的是他的父亲
下面是执行计划的一部分,
⏹操作1是树的根,它有三个孩子:2,5,和8
⏹操作2有两个孩子:3和4
⏹操作3和4没有孩子
⏹操作5有一个孩子:6
⏹操作6有一个孩子:7
⏹操作7没有孩子
⏹操作8有一个孩子:9
⏹操作9没有孩子
III.优化SQL
A.找出不理想的访问路径
目标:消耗资源最少,而消耗资源用逻辑读来衡量。
为何使用逻辑读度量?
⏹逻辑读是受制于CPU能力的操作,可以反映CPU的使用情况
⏹逻辑读可能导致物理读。
因此减少逻辑读,很可能会降低I/O 操作次数
⏹逻辑读数量可以很方便的获取到
1.经验法则:
⏹每个返回行少于5个逻辑读的访问路径比较好
⏹每个返回行10~15个逻辑读是正常
⏹每个返回行15~20个逻辑读很可能是低效的。
2.检查平均每行逻辑读数量的方法
a.使用SQL跟踪。
set autot trace
3.低效率的原因
a.条件列没有建立索引
b.提供了索引,但SQL语句的语法限制了索引使用
4.解决办法
a.选择性较强的SQL:使用索引访问比较高效
b.选择性较弱的SQL: 使用全表扫描比较高效
B.具有弱选择性的SQL语句
1.全表扫描
在所有的表上都可以进行全表扫描。
在执行计划中,TABLE ACCESS FULL操作
对应全表扫描。
在全表扫描的过程中,数据库引擎顺序读取所有数据块。
2.全索引扫描
当索引包含查询所需要的所有数据的时候,全表扫描可以用全索引扫描(full
index scan)替代。
因为索引数据通常比表数据小的多,可以减少逻辑读。
C.强选择性的SQL语句
1.索引访问
索引访问是最常用的访问路径。
要利用索引,需要在WHERE子句中至少应用
一个通过索引的限制条件。
a.等于条件与B-树索引
1.INDEX UNIQUE SCAN
用于唯一索引
SELECT * FROM t WHERE id = 6;
第一步,通过操作2的谓词条件,对列id上的条件使用索引t_pk得到rowid。
第二步,使用rowid来访问表T
2.INDEX RANGE SCAN
用于非唯一性索引。
和a的差别是根据限制条件抽取多个rowid
SELECT * FROM t WHERE n1 = 6;
b.范围条件和B-索引
对B-树索引来说,范围条件和非唯一索引上的等于条件是一样的,使用
INDEX RANGE SCAN操作。
对范围条件来说,索引唯一性是无关的。
总会返
回多个rowid。
SELECT * FROM t WHERE id BETWEEN6AND19;
c.IN条件
IN条件没有特定的访问路径。
在执行计划中,INLIST ITERATOR操作指出因为IN条件的原因部分执行计划被多次执行。
基本上,IN条件只是一系列的等于条件。
注意和索引和表访问相关的操作对IN列表中的每一个值执行了一次。
SELECT * FROM t WHERE id IN (6, 8, 9, 28);
d.like条件
1.SELECT name FROM t WHERE name like‘%张三%’
2.SELECT name FROM t WHERE name like‘张三%’
如果不是以通配符开头,LIKE条件和范围条件一样处理。
否则就要使用全表扫描或全索引扫描。
e.min/max函数和B-索引
1.不指定范围条件,INDEX FULL SCAN。
实际上不运行全索引扫描,仅得
到最左边或最右边的索引键
SELECT MIN(id) FROM t;
2.指定范围条件,INDEX RANGE SCAN(MIN/MAX),当查询条件对索引列
指定条件时使用
SELECT MIN(id) FROM t WHERE id > 42;
f.基于函数的索引
对索引列进行函数转换的时候,无法用到索引。
如果不能改写限制条件,只有在限制条件列上建立函数索引。
SQL:SELECT * FROM t WHERE upper(c1) = 'SELDON';
执行计划:
增加函数索引,CREATE INDEX i_c1_upper ON t (upper(c1));
新的执行计划:
逻辑读由500减少到了2个。
g.组合索引
带有多列的索引成为组合索引
作用:可以应用由and连接的多个SQL条件组成的限制。
注意:or不可以应用场景:多个and条件列上的唯一值较少,索引选择性不强,
SQL:SELECT/*+index(t i_n2)*/* FROM t WHERE n1=6AND n2=42AND n3=11;N2列上索引选择性不强
增加组合索引:
create index I_N123 on T (N1, N2, N3);
逻辑读由82减少到了4个。
h.只访问索引
当索引中包括处理查询所需要的所有数据时,可以执行只扫描索引操作。
SQL:SELECT n1 FROM t WHERE c1 LIKE'A%'
对于此类情况,要想使用只扫描索引操作,即使没有对某列应用限制条件也应该将其添加到索引中。
索引键中包含SQL语句中引用的所有列,而不止是Where条件中的列。
使用索引存储冗余数据来最小化逻辑读的量。
增加联合索引:CREATE INDEX t_n1_c1 ON t(c1,n1);
逻辑读由113个减少到了9个
IV.使用索引的注意事项
A.避免在索引列上使用计算
B.避免在索引列上使用函数
如:select * from table_name where to_char(number_column)=’12345’;
select * from table_name where number_column =to_number(’12345’);
C.like查询避免使用通配符%开头
D.使用not exists代替not in
1.select * from t1 a where id not in(select id form t2);
2.select * from t1 a where not exists(select 1 from t2 where t1.id=t2.id);
E.多个选择性不强的条件,建立组合索引
F.在查询列和条件列上建立组合索引
G.在进行排序的列上建立索引
1.select * from t1 order by n1 desc;
H.强制使用索引:使用提示(hint)。