[Q]如果设置自动跟踪
[A]用system登录
执行$ORACLE_HOME/rdbms/admin/utlplan.sql创建计划表
执行$ORACLE_HOME/rdbms/admin/plustrce.sql创建plustrace角色
如果想计划表让每个用户都能使用,则
SQLcreate public synonym plan_table for plan_table;
SQL grant all on plan_table to public;
如果想让自动跟踪的角色让每个用户都能使用,则
SQL grant plustrace to public;
通过如下语句开启/停止跟踪
SET AUTOTRACE ON |OFF
| ON EXPLAIN | ON STATISTICS | TRACEONLY | TRACEONLY EXPLAIN
[Q]如果跟踪自己的会话或者是别人的会话
[A]跟踪自己的会话很简单
Alter session set sql_trace true|false
Or
Exec dbms_session.set_sql_trace(TRUE);
如果跟踪别人的会话,需要调用一个包
exec dbms_system.set_sql_trace_in_session(sid,serial#,true|false)
跟踪的信息在user_dump_dest 目录下可以找到或通过如下脚本获得文件名称(适用于Win环境,如果是unix需要做一定修改)
SELECT p1.value||'\'||p2.value||'_ora_'||p.spid||'.ora' filename
FROM
v$process p,
v$session s,
v$parameter p1,
v$parameter p2
WHERE p1.name = 'user_dump_dest'
AND p2.name = 'db_name'
AND p.addr = s.paddr
AND s.audsid = USERENV ('SESSIONID')
最后,可以通过Tkprof来解析跟踪文件,如
Tkprof 原文件 目标文件 sys=n
[Q]怎么设置整个数据库系统跟踪
[A]其实文档上的alter system set sql_trace=true是不成功的
但是可以通过设置事件来完成这个工作,作用相等
alter system set events
'10046 trace name context forever,level 1';
如果关闭跟踪,可以用如下语句
alter system set events
'10046 trace name context off';
其中的level 1与上面的8都是跟踪级别
level 1:跟踪SQL语句,等于sql_trace=true
level 4:包括变量的详细信息
level 8:包括等待事件
level 12:包括绑定变量与等待事件
[Q]怎么样根据OS进程快速获得DB进程信息与正在执行的语句
[A]有些时候,我们在OS上操作,象TOP之后我们得到的OS进程,怎么快速根据OS信息获得DB信息呢?
我们可以编写如下脚本:
$more whoit.sh
#!/bin/sh
sqlplus /nolog <<EOF
connect / as sysdba
col machine format a30
col program format a40
set line 200
select sid,serial# ,username,osuser,machine,program,process,to_char(logon_time,'yyyy/mm/dd hh24:mi:ss')
from v\$session where paddr in
( select addr from v\$process where spid in($1));
select sql_text from v\$sqltext_with_newlines
where hash_value in
(select SQL_HASH_VALUE from v\$session where
paddr in (select addr from v\$process where spid=$1)
)
order by piece;
exit;
EOF
然后,我们只要在OS环境下如下执行即可
$./whoit.sh Spid
[Q]怎么样分析表或索引
[A]命令行方式可以采用analyze命令
如Analyze table tablename compute statistics;
Analyze index|cluster indexname estimate statistics;
ANALYZE TABLE tablename COMPUTE STATISTICS
FOR TABLE
FOR ALL [LOCAL] INDEXES
FOR ALL [INDEXED] COLUMNS;
ANALYZE TABLE tablename DELETE STATISTICS
ANALYZE TABLE tablename VALIDATE REF UPDATE
ANALYZE TABLE tablename VALIDATE STRUCTURE
[CASCADE]|[INTO TableName]
ANALYZE TABLE tablename LIST CHAINED ROWS [INTO TableName]
等等。
如果想分析整个用户或数据库,还可以采用工具包,可以并行分析
Dbms_utility(8i以前的工具包)
Dbms_stats(8i以后提供的工具包)
如
dbms_stats.gather_schema_stats(User,estimate_percent=100,cascade= TRUE);
dbms_stats.gather_table_stats(User,TableName,degree = 4,cascade = true);
这是对命令与工具包的一些总结
1、对于分区表,建议使用DBMS_STATS,而不是使用Analyze语句。
a) 可以并行进行,对多个用户,多个Table
b) 可以得到整个分区表的数据和单个分区的数据。
c) 可以在不同级别上Compute Statistics:单个分区,子分区,全表,所有分区
d) 可以倒出统计信息
e) 可以用户自动收集统计信息
2、DBMS_STATS的缺点
a) 不能Validate Structure
b) 不能收集CHAINED ROWS, 不能收集CLUSTER TABLE的信息,这两个仍旧需要使用Analyze语句。
c) DBMS_STATS 默认不对索引进行Analyze,因为默认Cascade是False,需要手工指定为True
3、对于oracle 9里面的External Table,Analyze不能使用,只能使用DBMS_STATS来收集信息。
[Q]怎么样快速重整索引
[A]通过rebuild语句,可以快速重整或移动索引到别的表空间
rebuild有重建整个索引数的功能,可以在不删除原始索引的情况下改变索引的存储参数
语法为
alter index index_name rebuild tablespace ts_name
storage(……);
如果要快速重建整个用户下的索引,可以用如下脚本,当然,需要根据你自己的情况做相应修改
SQL set heading off
SQL set feedback off
SQL spool d:\index.sql
SQL SELECT 'alter index ' || index_name || ' rebuild '
||'tablespace INDEXES storage(initial 256K next 256K pctincrease 0);'
FROM all_indexes
WHERE ( tablespace_name != 'INDEXES'
OR next_extent != ( 256 * 1024 )
)
AND owner = USER
SQLspool off
另外一个合并索引的语句是
alter index index_name coalesce,这个语句仅仅是合并索引中同一级的leaf block
消耗不大,对于有些索引中存在大量空间浪费的情况下,有一些作用。
[Q]如何使用Hint提示
[A] 在select/delete/update后写/*+ hint */
如 select /*+ index(TABLE_NAME INDEX_NAME) */ col1...
注意/*和+之间不能有空格
如用hint指定使用某个索引
select /*+ index(cbotab) */ col1 from cbotab;
select /*+ index(cbotab cbotab1) */ col1 from cbotab;
select /*+ index(a cbotab1) */ col1 from cbotab a;
其中
TABLE_NAME是必须要写的,且如果在查询中使用了表的别名,在hint也要用表的别名来代替表名;
INDEX_NAME可以不必写,Oracle会根据统计值选一个索引;
如果索引名或表名写错了,那这个hint就会被忽略;
[Q]怎么样快速复制表或者是插入数据
[A]快速复制表可以指定Nologging选项
如:Create table t1 nologging
as select * from t2;
快速插入数据可以指定append提示,但是需要注意
noarchivelog模式下,默认用了append就是nologging模式的。
在archivelog下,需要把表设置程Nologging模式。
如insert /*+ append */ into t1
select * from t2
注意:如果在9i环境中并设置了FORCE LOGGING,则以上操作是无效的,并不会加快,当然,可以通过如下语句设置为NO FORCE LOGGING。
Alter database no force logging;
是否开启了FORCE LOGGING,可以用如下语句查看
SQL select force_logging from v$database;
[Q]怎么避免使用特定索引
[A]在很多时候,Oracle会错误的使用索引而导致效率的明显下降,我们可以使用一点点技巧而避免使用不该使用的索引,如:
表test,有字段a,b,c,d,在a,b,c上建立联合索引inx_a(a,b,c),在b上单独建立了一个索引Inx_b(b)。
在正常情况下,where a=? and b=? and c=?会用到索引inx_a,
where b=?会用到索引inx_b
但是,where a=? and b=? and c=? group by b会用到哪个索引呢?在分析数据不正确(很长时间没有分析)或根本没有分析数据的情况下,oracle往往会使用索引inx_b。通过执行计划的分析,这个索引的使用,将大大耗费查询时间。
当然,我们可以通过如下的技巧避免使用inx_b,而使用inx_a。
where a=? and b=? and c=? group by b||'' --如果b是字符
where a=? and b=? and c=? group by b+0 --如果b是数字
通过这样简单的改变,往往可以是查询时间提交很多倍
当然,我们也可以使用no_index提示,相信很多人没有用过,也是一个不错的方法:
select /*+ no_index(t,inx_b) */ * from test t
where a=? and b=? and c=? group by b
[Q]Oracle什么时候会使用跳跃式索引扫描
[A]这是9i的一个新特性跳跃式索引扫描(Index Skip Scan).
例如表有索引index(a,b,c),当查询条件为
where b=?的时候,可能会使用到索引index(a,b,c)
如,执行计划中出现如下计划:
INDEX (SKIP SCAN) OF 'TEST_IDX' (NON-UNIQUE)
Oracle的优化器(这里指的是CBO)能对查询应用Index Skip Scans至少要有几个