日期:2014-05-16 浏览次数:20567 次
1.识别'低效执行'的SQL语句
SELECT EXECUTIONS , DISK_READS, BUFFER_GETS, ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio, ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run, SQL_TEXT FROM V$SQLAREA WHERE EXECUTIONS>0 AND BUFFER_GETS > 0 AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8 ORDER BY 4 DESC;
?
2.先查询后取结果集
举例:模仿SQL Server实现Top x从结果集获取指定数量(x)的数据条数? select top 1 f from A;
select f from (select f from A where f=0) where rownum <= 1;
?
3.WHERE子句的顺序约定
表连接子句必须写在其它WHERE子句之前,那些可以过滤掉最大数量记录的条件建议写在WHERE子句的末尾。
原因:ORACLE采用自下而上的顺序解析WHERE子句
4.SELECT子句中避免使用星号(*)
ORACLE在解析的过程中, 会将星号依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间.
5.删除重复记录
DELETE FROM A WHERE A.ROWID > (SELECT MIN(B.ROWID) FROM B WHERE B.id = A.id);
?
6.用EXISTS替换DISTINCT
当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT. 一般可以考虑用EXIST替换
例如-->
低效: SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D,EMP E WHERE D.DEPT_NO = E.DEPT_NO 高效: SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X' FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);
?
EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果.
7.WHERE子句中, 如果索引列所对应的值的第一个字符由通配符(WILDCARD)开始, 索引将不被采用.
8.基础表的选择
基础表(Driving Table)是指被最先访问的表(通常以全表扫描的方式被访问). 根据优化器的不同, SQL语句中基础表的选择是不一样的.
如果用CBO (COST BASED OPTIMIZER),优化器会检查SQL语句中的每个表的物理大小,索引的状态,然后选用花费最低的执行路径.
如果用RBO (RULE BASED OPTIMIZER) , 并且所有的连接条件都有索引对应, 在这种情况下, 基础表就是FROM 子句中列在最后的那个表.
9. 避免在索引列上使用IS NULL和IS NOT NULL
避免在索引中使用任何可以为空的列,ORACLE将无法使用该索引 .
10.WHERE子句使用的索引和ORDER BY子句中所使用的索引不能并列.
11.内部发生的类型转换,索引将失效!
为了避免ORACLE对字段进行隐式的类型转换, 最好把类型转换用显式表现出来. 注意当字符和数值比较时, ORACLE会优先转换数值类型到字符类型.
12.‘!=' 将不使用索引. 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中.
13.‘||'是字符连接函数. 就象其他函数那样, 停用了索引.
14.‘+'是数学函数. 就象其他数学函数那样, 停用了索引.
15.下面的例子中,相同的索引列不能互相比较,这将会启用全表扫描.
不使用索引:
SELECT ACCOUNT_NAME, AMOUNT FROM TRANSACTION WHERE ACCOUNT_NAME = NVL(:ACC_NAME,ACCOUNT_NAME);
?
使用索引:
SELECT ACCOUNT_NAME, AMOUNT FROM TRANSACTION WHERE ACCOUNT_NAME LIKE NVL(:ACC_NAME,'%');
?
如果一定要对使用函数的列启用索引, ORACLE新的功能: 基于函数的索引(Function-Based Index) 也许是一个较好的方案.
CREATE INDEX EMP_I ON EMP (UPPER(ename)); /*建立基于函数的索引*/ SELECT * FROM emp WHERE UPPER(ename) = ‘BLACKSNAIL'; /*将使用索引*/
?
16.? 手工创建快照
SQL>EXEC dbms_workload_repository.create_snapshot ? 产生AWR报告 SQL>@$ORACLE_HOME/rdbms/admin/awrrpt.sql
?
17.在 Alter table 或 Create table 后加 cache 子句来使表成为缓存表(不被请出)
?