资源描述
ORACLE 数据库操作手册2.0
中国通信集团公司安徽有限公司
计费业务部
2007年11月
修改记录
版本
日期
编辑者
编辑内容
1.0
2023/2/10
见春蕾
形成初稿
1.1
2023/8/31
见春蕾
根据实际情况修订部分章节
2.0
2023/11/05
见春蕾
一、在第一章(数据库使用注意事项)中增长了关于批量更新数据的大事务分次提交的规定、客户端的配置方法、修改密码方法;
二、在第二章(SQL编写注意事项)中增长了关于提醒(Hints)的使用。
三、增长了第四章(跟踪SQL执行计划),阐述了相关的理论知识和SQL执行计划的跟踪方法。
目录
ORACLE 数据库操作手册2.0 1
第一章 数据库使用注意事项 5
二、不使用数据库时请及时关闭数据库连接,但是也不能频繁的连接和断开 5
三、执行了DML操作,请按业务规则,不要忘掉执行COMMIT或ROLLBACK。 5
四、假如是查询和记录不涉及到当天的业务时,不要在生产环境里操作,在BCV库中操作。BCV天天晚上12点同步一次,数据和用户口令、密码和生产环境相同。 5
五、关联表都很大的查询和记录也尽量用BCV库。 6
六、生产环境营业时间(特别是营业高峰时间,目前是上午8:00-10:00,下午3:00-4:00)严禁做大数据量的查询和记录,每个查询的执行时间要控制在1分钟内。 6
七、不要执行索引和表的信息的收集。 6
八、编写程序的时候,注意SQL语句规范,尽量使用变量绑定,减少共享池的使用。 6
九、按照标准规定编写pl/sql等程序,注意事务的提交、回滚和对各种异常情况的解决。 6
十、要查看表字段名或随机的少量数据时候,使用desc、也可以使用where1=2或者rowcount<n来查看,而尽量不要直接执行select * from tablename,然后kill会话。 6
十一、尽量使用索引,避免出现全表扫描,性能影响比单机更大。 6
十二、对分区表建立索引时,使用local选项。 6
十三、不要在事务中引入Trigger,建议在事务中实现。 6
十四、批量更新数据的大的事务分次提交。 6
十五、客户端的配置。 7
十六、修改密码。 7
第二章 SQL编写注意事项 9
一、SELECT 子句中避免使用* 9
二、查找总记录数时,尽量不要用count(*),而要指定一个有索引的字段。 9
三、将大的历史表创建为分区表,便于数据转储和删除。 9
四、使用分区表进行查询时,尽量把分区键作为查询条件的第一个条件。 9
五、Sequence采用cache/noorder,假如在使用sequence上的列建索引,建议加大cache值。 9
六、在FROM子句中包含多个表的情况下,选择记录条数最少的表作为基础表,放在FROM子句的最后面。 9
七、WHERE子句中的连接顺序 10
八、在需要无条件删除表中数据时,用truncate代替delete。 11
九、语句中尽量使用表的索引字段,避免做大表的全表扫描。 11
十、 带通配符(%)的like语句 11
十一、用EXISTS替代IN 11
十二、用NOT EXISTS替代NOT IN 12
十三、尽也许的用UNION-ALL 替换UNION 12
十四、Order by语句建议 13
十五、避免使用NOT 13
十六、使用DECODE函数来减少解决时间 14
十七、删除反复记录 14
十八、假如可以使用where条件,尽量不要在having中限制数据 14
十九、尽量不要使数据排序 14
二十、使用提醒(Hints) 15
第三章oracle和sybase的SQL区别 15
一、大小写 15
二、限制记录数量 15
三、列的选择 16
四、连接 16
五、字符串函数 16
六、日期函数 16
七、数据类型转换函数: 17
八、空值替代函数: 17
九、sybase的where语句执行[ ]正则符号,但是oracle9i不支持。 17
十、数字取舍 17
第四章 跟踪SQL执行计划 18
一、理论 18
(一)ORACLE优化器 18
(二)访问TABLE的方式 18
(三) 索引访问方式 19
二、SET TRACE跟踪sql执行计划 19
第一章 数据库使用注意事项
一、对BOSS1.5营帐库,营业网址严格按照规定进行配置,不可随意更换。
营业网址规定按照下面方式进行分派配置,假如随意更换,会增长营业主机间的数据交互,影响数据库性能,减少营业工作效率。
合肥、六安、阜阳、宿州、亳州、淮北、黄山、铜陵配置:
:7001/WebRoot/login.jsp
或者
芜湖、蚌埠、淮南、马鞍山、安庆、滁州、宣城、巢湖、池州,配置如下:
:8001/WebRoot/login.jsp
或者
二、不使用数据库时请及时关闭数据库连接,但是也不能频繁的连接和断开
数据库连接也是数据库的宝贵资源,数据库支持的数据库连接有限,当不需要使用数据库时,请“优雅”的退出数据库吧,假如能正常退出,请别“结束任务”或KILL -9。假如正在执行SQL的时候忽然异常终端,请联系数据库管理员检查解决,以防止数据库一直占用该SQL相关资源。
三、执行了DML操作,请按业务规则,不要忘掉执行COMMIT或ROLLBACK。
不要只执行语句,而不控制事务。当你执行一条DML语句时,数据库会为你分派锁、回滚段、REDO LOG BUFFER等资源。事务结束后,这些资源才干得以释放。
四、假如是查询和记录不涉及到当天的业务时,不要在生产环境里操作,在BCV库中操作。BCV天天晚上12点同步一次,数据和用户口令、密码和生产环境相同。
bcv是一个节点的数据库,所有的地市的查询的连接配置是同一个,如下:
YZDBBCV =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 10.153.192.45)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = yzdb)
)
)
五、关联表都很大的查询和记录也尽量用BCV库。
六、生产环境营业时间(特别是营业高峰时间,目前是上午8:00-10:00,下午3:00-4:00)严禁做大数据量的查询和记录,每个查询的执行时间要控制在1分钟内。
七、不要执行索引和表的信息的收集。
八、编写程序的时候,注意SQL语句规范,尽量使用变量绑定,减少共享池的使用。
九、按照标准规定编写pl/sql等程序,注意事务的提交、回滚和对各种异常情况的解决。
十、要查看表字段名或随机的少量数据时候,使用desc、也可以使用where1=2或者rowcount<n来查看,而尽量不要直接执行select * from tablename,然后kill会话。
十一、尽量使用索引,避免出现全表扫描,性能影响比单机更大。
十二、对分区表建立索引时,使用local选项。
十三、不要在事务中引入Trigger,建议在事务中实现。
十四、批量更新数据的大的事务分次提交。
在营帐数据库系统繁忙时候,大于300万的数据刷新,建议分次提交,减少异常发生。系统空闲时,大于800万的数据刷新,建议分次提交。
十五、客户端的配置。
方法一、直接修改tnsnames.ora
YZDBBCV =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 10.147.192.45)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = yzdb)
)
)
方法二、使用客户端工具
十六、修改密码。
用sql*plus使用账号连接数据库
可以从菜单进入
也可以从命令行窗口进入
方法一、使用password命令
方法二、使用alter命令
Alter user 账号 identified by 密码
密码规则问题:
有字符、数字、特殊字符
要六位以上
和以前密码不能有三个以上相同的字符
第二章 SQL编写注意事项
一、SELECT 子句中避免使用*
在SELECT子句中列出所有的列时,使用*很方便,但是效率低。由于ORACLE在解析的过程中,会查询数据字典,将*依次转换成所有的列名。所以,直接在SELECT子句中写出想要显示的列。
二、查找总记录数时,尽量不要用count(*),而要指定一个有索引的字段。
例如索引列为index,使用count(index),这样能运用索引。
三、将大的历史表创建为分区表,便于数据转储和删除。
四、使用分区表进行查询时,尽量把分区键作为查询条件的第一个条件。
五、Sequence采用cache/noorder,假如在使用sequence上的列建索引,建议加大cache值。
六、在FROM子句中包含多个表的情况下,选择记录条数最少的表作为基础表,放在FROM子句的最后面。
由于在基于规则的优化器中,ORACLE的解析器按照从右到左的顺序解决FROM子句中的表名。FROM子句中写在最后的表将被最先解决。
例如:
表 TAB1 16,384 条记录
表 TAB2 5 条记录
选择TAB2作为基础表 (最佳的方法)
select count(*) from tab1,tab2... 执行时间0.96秒
选择TAB1作为基础表 (不佳的方法)
select count(*) from tab2,tab1... 执行时间26.09秒
假如有3个以上的表连接查询,那就需要选择交叉表作为基础表,交叉表是指那个被其他表所引用的表
例如:
EMP表描述了LOCATION表和CATEGORY表的交集
SELECT *
FROM LOCATION L,
CATEGORY C,
EMP E
WHERE E.EMP_NO BETWEEN 1000 AND 2023
AND E.CAT_NO = C.CAT_NO
AND E.LOCN = L.LOCN
将比下列SQL更有效率
SELECT *
FROM EMP E ,
LOCATION L ,
CATEGORY C
WHERE E.CAT_NO = C.CAT_NO
AND E.LOCN = L.LOCN
AND E.EMP_NO BETWEEN 1000 AND 2023
七、WHERE子句中的连接顺序
ORACLE采用自下而上的顺序解析WHERE子句。根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。
例如:
(低效,执行时间156.3秒)
SELECT *
FROM EMP E
WHERE SAL > 50000
AND JOB = 'MANAGER'
AND 25 < (SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO);
(高效,执行时间10.6秒)
SELECT *
FROM EMP E
WHERE 25 < (SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO)
AND SAL > 50000
AND JOB = 'MANAGER';
八、在需要无条件删除表中数据时,用truncate代替delete。
九、语句中尽量使用表的索引字段,避免做大表的全表扫描。
例如Where子句中有联接的列,即使最后的联接值为一个静态值,也不会使用索引。
select * from employee
where first_name||''||last_name ='Beill Cliton';
这条语句没有使用基于last_name创建的索引。
当采用下面这种SQL语句的编写,Oracle系统就可以采用基于last_name创建的索引。
Select * from employee
where first_name ='Beill' and last_name ='Cliton';
十、 带通配符(%)的like语句
例如SQL语句:
select * from employee where last_name like '%cliton%';
由于通配符(%)在搜寻词首出现,所以Oracle系统不使用last_name的索引。通配符如此使用会减少查询速度。当通配符出现在字符串其他位置时,优化器就能运用索引。在下面的查询中索引得到了使用:
select * from employee where last_name like 'c%';
十一、用EXISTS替代IN
在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率.
低效:
SELECT *
FROM EMP (基础表)
WHERE EMPNO > 0
AND DEPTNO IN (SELECT DEPTNO
FROM DEPT
WHERE LOC ='MELB')
高效:
SELECT *
FROM EMP (基础表)
WHERE EMPNO > 0
AND EXISTS (SELECT 'X'
FROM DEPT
WHERE DEPT.DEPTNO = EMP.DEPTNO
AND LOC = 'MELB')
十二、用NOT EXISTS替代NOT IN
在子查询中,NOT IN子句将执行一个内部的排序和合并. 无论在哪种情况下,NOT IN都是最低效的 (由于它对子查询中的表执行了一个全表遍历). 为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS.
例如:
SELECT …
FROM EMP
WHERE DEPT_NO NOT IN (SELECT DEPT_NO
FROM DEPT
WHERE DEPT_CAT='A');
为了提高效率.改写为:
(方法一: 高效)
SELECT ….
FROM EMP A,DEPT B
WHERE A.DEPT_NO = B.DEPT(+)
AND B.DEPT_NO IS NULL
AND B.DEPT_CAT(+) = 'A'
(方法二: 最高效)
SELECT ….
FROM EMP E
WHERE NOT EXISTS (SELECT 'X'
FROM DEPT D
WHERE D.DEPT_NO = E.DEPT_NO
AND DEPT_CAT = 'A');
十三、尽也许的用UNION-ALL 替换UNION
当SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行排序.
假如用UNION ALL替代UNION, 这样排序就不是必要了. 效率就会因此得到提高.
举例:
低效:
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
高效:
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
UNION ALL
SELECT ACCT_NUM, BALANCE_AMT
FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95'
十四、Order by语句建议
ORDER BY语句决定了Oracle如何将返回的查询结果排序。Order by语句对要排序的列没有什么特别的限制,也可以将函数加入列中(象联接或者附加等)。任何在Order by语句的非索引项或者有计算表达式都将减少查询速度。
仔细检查order by语句以找出非索引项或者表达式,它们会减少性能。解决这个问题的办法就是重写order by语句以使用索引,也可认为所使用的列建立此外一个索引,同时应绝对避免在order by子句中使用表达式。
十五、避免使用NOT
在查询时经常在where子句使用一些逻辑表达式,如大于、小于、等于以及不等于等等,也可以使用and(与)、or(或)以及not(非)。NOT可用来对任何逻辑运算符号取反。下面是一个NOT子句的例子:
... where not (status ='VALID')
假如要使用NOT,则应在取反的短语前面加上括号,并在短语前面加上NOT运算符。NOT运算符包含在此外一个逻辑运算符中,这就是不等于(<>)运算符。换句话说,即使不在查询where子句中显式地加入NOT词,NOT仍在运算符中,见下例:
... where status <>'INVALID';
再看下面这个例子:
select * from employee where salary<>3000;
对这个查询,可以改写为不使用NOT:
select * from employee where salary<3000 or salary>3000;
虽然这两种查询的结果同样,但是第二种查询方案会比第一种查询方案更快些。第二种查询允许Oracle对salary列使用索引,而第一种查询则不能使用索引。
十六、使用DECODE函数来减少解决时间
使用DECODE函数可以避免反复扫描相同记录或反复连接相同的表.
例如:
SELECT COUNT(*),SUM(SAL)
FROM EMP
WHERE DEPT_NO = 0020
AND ENAME LIKE 'SMITH%';
SELECT COUNT(*),SUM(SAL)
FROM EMP
WHERE DEPT_NO = 0030
AND ENAME LIKE 'SMITH%';
可以用DECODE函数高效地得到相同结果
SELECT COUNT(DECODE(DEPT_NO,0020,'X',NULL)) D0020_COUNT,
COUNT(DECODE(DEPT_NO,0030,'X',NULL)) D0030_COUNT,
SUM(DECODE(DEPT_NO,0020,SAL,NULL)) D0020_SAL,
SUM(DECODE(DEPT_NO,0030,SAL,NULL)) D0030_SAL
FROM EMP WHERE ENAME LIKE 'SMITH%';
类似的,DECODE函数也可以运用于GROUP BY 和ORDER BY子句中.
十七、删除反复记录
DELETE FROM EMP E
WHERE E.ROWID > (SELECT MIN(X.ROWID)
FROM EMP X
WHERE X.EMP_NO = E.EMP_NO);
十八、假如可以使用where条件,尽量不要在having中限制数据
十九、尽量不要使数据排序
引起排序的条件
- Order by
- Group by
- Union,intersect,minus
- Distinct
二十、使用提醒(Hints)
对于表的访问,可以使用两种Hints:FULL 和 ROWID
l FULL hint 告诉ORACLE使用全表扫描的方式访问指定表.
例如:
SELECT /*+ FULL(EMP) */ *
FROM EMP
WHERE EMPNO = 7893;
l ROWID hint 告诉ORACLE使用TABLE ACCESS BY ROWID的操作访问表.
通常, 你需要采用TABLE ACCESS BY ROWID的方式特别是当访问大表的时候, 使用这种方式, 你需要知道ROIWD的值或者使用索引。
假如一个大表没有被设定为缓存(CACHED)表而你希望它的数据在查询结束是仍然停留在SGA中,你就可以使用CACHE hint 来告诉优化器把数据保存在SGA中。 通常CACHE hint 和 FULL hint 一起使用。
例如:
SELECT /*+ FULL(WORKER) CACHE(WORKER)*/ *
FROM WORK;
索引hint 告诉ORACLE使用基于索引的扫描方式. 你不必说明具体的索引名称
例如:
SELECT /*+ INDEX(a index_name) */ LODGING
FROM LODGING a
WHERE MANAGER = ‘BILL GATES';
ORACLE hints 还涉及ALL_ROWS, FIRST_ROWS, RULE,USE_NL, USE_MERGE, USE_HASH 等等。可以根据具体情况具体使用。
第三章oracle和sybase的SQL区别
一、大小写
SYBASE的SQL中数据库名、表名和列名分大小写,应遵循定义时的写法;ORACLE 并不区分。
二、限制记录数量
在SYBASE SQL中限制纪录的数量,需要用 EXEC SQL SET ROWCOUNT n, 用完需要执行EXEC SQL SET ROWCOUNT 0 恢复; 而 ORACLE 中只需要在 SQL中用 SELECT * FROM tbl_name where rowcount<n来限制即可。
三、列的选择
ORACLE执行数据查询的时候,SELECT语句必须选择针对的数据表。在Oracle数据库内有一种特殊的表DUAL。从DUAL表选择数据常被用来通过SELECT语句计算常数表达式,由于DUAL只有一行数据,所以常数只返回一次。
Oracle下的DUAL查询如下所示:
SELECT 'x' FROM dual
在sybase中,查询则是下面这个样子:
SELECT 'x'
四、连接
Oracle用|| 符号作为连接符,而sybase的连接符是加号:+ 。
Oracle查询如下所示:
Select 'Name' || 'Last Name' From tableName
相应的sybase查询如下所示:
Select 'Name' + 'Last Name'
五、字符串函数
返回字符串长度函数
sybase: char_length(string) 或datalength(string)
oracle: length(string)
LENGTH和LEN
sybase: SELECT LEN('SQLMAG') "Length in characters"
oracle: SELECT LENGTH('SQLMAG') "Length in characters" FROM DUAL;
六、日期函数
取当前系统日期时间
sybase: getdate() 返回datetime eg:select getdate()
oracle: sysdate 返回date eg:select sysdate from dual;
日期的加法
sybase: select dateadd(mm,12,getdate())
oracle: select add_months(sysdate,12) from dual
日期的减法
sybase: SELECT datediff(dd, GetDate(),dateadd(mm,12,getdate()))
oracle: SELECT sysdate -add_months(sysdate,12) FROM dual
七、数据类型转换函数:
sybase中转换函数为convert(datatype,expression[,style]))
在oracle中不可用,应用以下转换函数:
日期转换字符to_char(date)
例如:select to_char(sysdate,’yyyy/mm/dd hh24:mi:ss’) from dual;
结果: 1999/09/08 16:25:30
select to_char(sysdate,’yyyymmdd’) from dual;
结果: 19990908
数字转换字符to_char(numbers)
字符转换日期to_date(string)
例如:select to_date(‘1999/09/08 16:25:30’,’yyyy/mm/dd hh24:mi:ss’)
from dual;
字符转换数字to_ number(string)
八、空值替代函数:
sybase中用 isnull(expr1,expr2)
oracle 中不能用isnull(),只能用nvl(expr1,expr2)
例如:
sybase:select isnull(pro_table_status, '0') from pos.product;
oracle: select nvl(pro_table_status, '0') from pos.product;
九、sybase的where语句执行[ ]正则符号,但是oracle9i不支持。
十、数字取舍
Oracle数据库内有一个TRUNC函数,该函数返回m位十进制数的n位;假如省略m则n就是0位。m的值可认为负,表达截去小数点左边m位数字。
在Sybase下可以用Round或者Floor。
以下是Oracle查询:
SELECT TRUNC(15.79,1) "Truncate" FROM DUAL;
下面是同类查询的sybase版本:
SELECT ROUND(15.79, 0) rounded , ROUND(15.79, 0,1) truncated
SELECT FLOOR(ROUND(15.79, 0)), FLOOR(ROUND(15.79, 0,1) )
第四章 跟踪SQL执行计划
一、理论
(一)ORACLE优化器
l Oracle的优化器有3种
基于规则 RULE
基于成本 COST
基于选择 CHOOSE
l 设立缺省的优化器,可以通过对init.ora文献中OPTIMIZER_MODE参数设立,也可以在会话(session)级对其进行覆盖.
l 假如OPTIMZER_MODE=RULE,则激活基于规则的优化器(RBO)。基于规则的优化器按照一系列的语法规则来推测也许执行途径和比较可替换的执行途径。
l 假如OPTIMZER_MODE=COST,则激活基于成本的优化器(CBO)。它使用ANALYZE语句来生成数据库对象的记录数据。这些记录数据涉及表的行数、平均长度及索引中不同的关键字数等。基于这些记录数据,成本优化器可以计算出可获得的执行途径的成本。并选择具有最小的成本执行途径。在CBO模式下,需要经常运营ANALYZE 命令来保证数据的准确性。
l 假如OPTIMZER_MODE=CHOOSE,实际的优化器模式将和是否运营过analyze命令有关. 假如table已经被analyze过, 优化器模式将自动成为CBO , 反之,数据库将采用RULE形式的优化器。
(二)访问TABLE的方式
ORACLE 采用两种访问表中记录的方式:
l 全表扫描
全表扫描就是顺序地访问表中每条记录. ORACLE采用一次读入多个数据块的方式优化全表扫描。
l ROWID定为访问
ORACLE采用索引实现了数据和存放数据的物理位置(ROWID)之间的联系。 通常索引提供了快速访问ROWID的方法,因此那些基于索引列的查询就可以得到性能上的提高。
(三) 索引访问方式
Oracle有两种索引访问方式
l 索引唯一扫描 ( INDEX UNIQUE SCAN)
如:表LOADING有两个索引 : 建立在LOADING列上的唯一性索引LOADING_PK和建立在MANAGER列上的非唯一性索引IDX_MANAGER。
SELECT * FROM LOADING WHERE LOADING = ‘ROSE HILL’;
在内部,上述SQL将被提成两步执行,一方面,LOADING_PK 索引将通过索引唯一扫描的方式被访问,获得相相应的ROWID,通过ROWID访问表的方式执行下一步检索。
假如被检索返回的列涉及INDEX列中,ORACLE将不执行第二步的解决(通过ROWID访问表)。 由于检索数据保存在索引中,单单访问索引就可以完全满足查询结果。
SELECT LOADING FROM LOADING WHERE LOADING = ‘ROSE HILL’;
l 2、索引范围查询(INDEX RANGE SCAN)
合用于两种情况:
1、 基于一个范围的检索
2、 基于非唯一性索引的检索
例1:
SELECT LOADING FROM LOADING WHERE LOADING LIKE ‘M%’;
WHERE子句条件涉及一系列值, ORACLE将通过索引范围查询的方式查询LODGING_PK 。 由于索引范围查询将返回一组值, 它的效率就要比索引唯一扫描低一些。
例2:
SELECT LOADING FROM LOADING WHERE MANAGER = ‘BILL GATES’;
这个SQL的执行分两步,IDX_MANAGER的索引范围查询(得到所有符合条件记录的ROWID) 和下一步同过ROWID访问表得到LOADING列的值。 由于IDX_MANAGER是一个非唯一性的索引,数据库不能对它执行索引唯一扫描。由于SQL返回LOADING列,而它并不存在于IDX_MANAGER索引中, 所以在索引范围查询后会执行一个通过ROWID访问表的操作。WHERE子句中, 假如索引列所相应的值的第一个字符由通配符(WILDCARD)开始, 索引将不被采用。
SELECT LOADING FROM LOADING WHERE MANAGER LIKE ‘%HANMAN’;
在这种情况下,ORACLE将使用全表扫描。
二、SET TRACE跟踪sql执行计划
举例:
SQL> list
1 SELECT *
2 FROM dept, emp
3* WHERE emp.deptno = dept.deptno
SQL> set autotrace traceonly
/*traceonly 可以不显示执行结果*/
SQL> /
14 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1 TABLE ACCESS (FULL) OF 'EMP'
3 1 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT'
4 3 INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE)
Statistics
----------------------------------------------------------
0 recursive calls
2 db block gets
30 consistent gets
0 physical reads
0 redo size
2598 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
14 rows processed
通过以上分析,可以得出实际的执行环节是:
1. TABLE ACCESS (FULL) OF 'EMP'
2. INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE)
3. TABLE ACCESS (BY INDEX ROWID) OF 'DEPT'
4. NESTED LOOPS (JOINING 1 AND 3)
注: 目前许多第三方的工具如TOAD和ORACLE自身提供的工具如OMS的SQL Analyze都提供了极其方便的EXPLAIN PLAN工具。
展开阅读全文