技术交流
随笔 - 64  文章 - 24  trackbacks - 0
<2008年4月>
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

恭候有志之事参与技术交流。交流QQ 12888986 MSN jinxin.1024@hotmail.com 用一句古话,叫“有志者事竟成”

常用链接

留言簿

随笔分类

随笔档案

文章分类

文章档案

最新随笔

搜索

  •  

积分与排名

  • 积分 - 12135
  • 排名 - 700

最新评论

阅读排行榜

评论排行榜

刚开始用SQL Server的时候,我没有用显示执行计划来对查询进行分析。我曾经一直认为我递交的SQL查询都是最优的,而忽略了查询性能究竟如何,从而对“执行计划”重视不够。在我职业初期,我只要能获取数据就很开心,而不去考虑数据是如何返回的,“执行计划”对我的查询作了什么工作。我以为SQL Server会自己去处理查询的性能问题的。作为一个刚进入IT行业或者刚学到新技术的软件工程师,在编写代码前不太可能有时间去学习其实必须掌握的知识。也许这是因为IT行业竞争太激烈的缘故。

随着时间的流逝,数据库容量慢慢变大了。终于某天,客户对应用系统的查询性能感到不满意了。他面带怒容来找我,抱怨由于查询太慢,使得他需要花更多的时间来处理公务。最初,我建议客户升级其系统资源,例如作为临时解决方案,增加硬盘容量。虽然硬盘价格现在很便宜了,但是客户还是要求我提供一个永久性的解决方案,检查和好好调试查询语句,来替代那种无休止地升级资源的临时方案。因为客户的满意度对IT行业来说是十分重要的,因此我不得不考虑他的个人建议。我答应他一定会检查和调整我的代码。


如何入手呢?

在刚进入IT行业时,我知道SQL Server的基础只是。说实话,向客户承诺检查系统的时候,我还没有一点入手的头绪。不过我相信我可以通过GOOGL和BOL来获取相应的信息。

我阅读了一些关于SQL Server的书籍,BOL,以及在网上搜索的信息。于是我知道了“显示执行计划”的概念。可以在查询管理器中将该选项的开关设置为ON。“显示执行计划”是一个图形化工具,可以帮助开发者和DBA分析,优化查询,从而改善性能。

“显示执行计划”中不同的任务具有不同的图标。本文中我主要对“Table Scan”、“Index Scan”、“Index Seek”、“Cluster Index Scan”以及“Clustered Index Seek”感兴趣。也许在以后,可以对别的任务进行另外介绍。

时间以F1方程式的速度开始流逝,我觉得该是我全面理解“Table Scan”、“Index Scan”、“Index Seek”、“Clustered Index Scan”、和“Clustered Index Seek”如何工作的时候了。

我准备开始分析并优化我的查询。在分析之前,我想到了一些问题。

  • MS-SQL Server什么时候使用"Table Scan"?
  • MS-SQL Server什么时候使用"Index Scan"?
  • MS-SQL Server什么时候使用"Index Seek"?
  • MS-SQL Server什么时候使用"Clustered Index Scan"?
  • MS-SQL Server什么时候使用"Clustered Index Seek"?

 

我主要关注SQL Server是根据什么来使用“执行计划”分析查询的。在经过一段时间学习后,我了解了一些相关知识。这些知识应该对开发和DBA新手有帮助。于是我决定写这篇文章,共享我的知识以帮助别人来理解“执行计划”。

如果你喜欢,可以慢慢读完,也可以在SQL Server上,模拟我下面做的实验。


开始入手

为了解释“显示执行计划”中的“Table Scan”、“Index Scan”、“Index Seek”、“Clustered Index Scan”和“Clustered Index Seek”,先创建新表,并添加一些示例数据进去。下面是创建新表的脚本:

 

Create Table PerformanceIssue
(
    PRID UniqueIdentifier NOT NULL,
    PRCode Int NOT NULL,
    PRDesc Varchar (100) NOT NULL
)
ON [PRIMARY]

 

表创建后需要添加一些数据。使用下面的脚本添加100,000条记录进去。脚本执行时间可能比较长,请耐心等待其执行完毕。

 

Declare @Loop Int
Declare @PRID UniqueIdentifier
Declare @ PRDesc Varchar (100)

Set @Loop = 1
Set @ PRDesc = ''

WHILE @Loop <= 100000
BEGIN
   Set @PRID = NewID()
   Set @PRDesc = ' PerformanceIssue - ' + Convert( Varchar(10),@Loop )
   Insert Into PerformanceIssue Values (@PRID, @Loop, @PRDesc)
   Set @Loop = @Loop + 1
END

 

脚本成功执行后,数据就添加进去了。

用下面语句来看一下表的内容:

 

Select PRID, PRCode, PRDesc
From PerformanceIssue
GO

 

由于记录较长,因此这里就不列出查询结果了。

正如我前面讲到,我想解释何时会有“Table Scan”、“Index Scan”、“Index Seek”、“Clustered Index Scan”和“Clustered Index Seek”。上述哪个会改善性能呢?

当SQL Server返回数据时,我们想知道SQL Server采取何种扫描机制来协助获取数据。首先看一下“Table Scan”。我们想了解什么时候“Table Scan”会产生。

选择“显示执行计划”或者使用热键“Alt + Q”来激活“显示执行计划”,当然也可以用快捷键“Ctrl+K”。

看一下执行下面查询后的“执行计划”结果。

 

Select PRID, PRCode, PRDesc
From PerformanceIssue
GO


上面的“执行计划”中,SQL Server用到了“Table Scan”。我问自己为什么会有“Table Scan”,SQL Server是根据什么来使用该方法的。难道是因为我想获取所有100,000条记录吗?于是我换了一个角度进行思考,如果来避免查询中出现“Table Scan”呢?此时我对SQL Server的扫描机制还不是很清楚,那么该如何优化查询呢?下面的SELECT查询中仅选择两列:[PRID, PRCode]。

 

Select PRID, PRCode
From PerformanceIssue
GO


查询执行后,执行计划和第一个查询一样。于是将查询改变为只检索一个字段 [PRID]。

 

Select PRID
From PerformanceIssue

GO


查询执行后,执行计划仍然和第一个查询的相同。对“Estimated row size”属性不需要太大关注。意思我立刻决定只获取一条记录,看看执行计划会如何。查询语句如下:

 

Select PRID, PRCode, PRDesc
From PerformanceIssue
Where PRID = 'D386C151-5F74-4C2A-B527-86FEF9712955'
-- PRID GUID value might be differ in your machine

GO

 

执行完成后,执行计划显示:

查询仍然使用了“Table Scan”方法来显示数据。

那么,我需要想其它办法来避免“Table Scan”。首先我想到应该给表加上索引。于是我在PRID字段上创建非聚集索引。添加了索引后是否就能避免“Table Scan”?下面我们开始讨论关于“Index Scan”和“Index Seek”的主题。


Index Scan 和 Index Seek

首先在PRID字段上创建非聚集索引。

 

CREATE UNIQUE NONCLUSTERED INDEX UNC_PRID
ON PerformanceIssue (PRID)
GO

 

本文假定读者已经知道非聚集索引如何工作的知识。了解非聚集索引更详细的信息,请阅读BOL相关主题,也可参看 http://www.sql-server-performance.com/gv_index_data_structures.asp。下面我们详细讲述“Index Scan”是如何工作的。

执行下面语句并查看执行计划的结果。

 

Select PRID, PRCode, PRDesc
From PerformanceIssue
GO


奇怪了,“Table Scan”仍然用到了。为什么SQL Server没有用到那个非聚集索引?于是继续优化查询语句,选择检索两个字段 [PRID, PRCode] 。

 

Select PRID, PRCode From PerformanceIssue
GO


执行结果是和上一个查询结果一摸一样。于是修改查询为只检索一个字段 [PRID] 。

 

Select PRID
From PerformanceIssue
GO

 

执行计划结果如下:

“Index Scan”在查询中被用到了,这很好。很自然,接下来的问题就是“Index Scan”什么时候会被用到。字段PRID上有一个索引,查询语句中选中的字段为PRID。执行查询的时候,SQL Server扫描索引页,因此用到了“Index Scan”方法。前面的查询中选择了有索引的和没有索引的字段,SQL Server无法使用“Index Scan”。当查询中只选择有索引的字段时,SQL Server就使用了“Index Scan”。我不清楚SQL Server底层到底是如何判断的,不过通过这些试验,我认为当查询中只选择有索引的字段时,SQL Server就使用“Index Scan”方法

下面看“Index Seek”方法何时产生。当我看到“Seek”这个词时,第一反应就是条件查询这个主意。

我尝试三种不同的带WHERE语法的查询语句,以找出那种会用“Index Seek”。第一种语句如下:

 

Select PRID, PRCode, PRDesc
From PerformanceIssue
Where PRCode = 8
GO

 

结果显示,执行计划使用了“Table Scan”。

第二种语句如下:

 

Select PRID, PRCode, PRDesc
From PerformanceIssue
Where PRDesc = ' PerformanceIssue - 8'
GO

 

执行计划仍然使用“Table Scan”方法。

第三种查询语句如下:

 

Select PRID, PRCode, PRDesc
From PerformanceIssue
Where PRID = 'D386C151-5F74-4C2A-B527-86FEF9712955'

-- PRID GUID value might be differ in your machine
GO



查询用到了“Index Seek”和“Bookmark Lookup”方法。用到“Index Seek”是因为WHERE后面使用带索引的字段PRID来进行过滤。“Bookmark Lookup”方法被用到是因为查询中选择了没有索引的字段。如果去掉这两个没有索引的字段,那么“Bookmark Lookup”方法就可以去掉。当然如果只返回PRID字段,那么该查询就没什么意义了,因为WHERE语句后面已经给出PRID具体取值了。

我认为“Index Seek”在性能改善上比“Index Scan”和“Table Scan”要好,这主要表现在下面几个方面:

 

  1. “Index Seek”不需要对表和索引页进行扫描;而“Table Scan”和“Index Scan”需要。
  2. “Index Seek”利用“WHERE”来过滤获取的数据,这样比用“Index Scan”和“Table Scan”快很多。

 

当我完成这些测试后,我同事问我一个很有意思的问题:SQL Server什么时候使用“Clustered Index Scan”和“Clustered Index Seek”?下面对“Clustered Index Scan”和“Clustered Index Seek”进行实验。

我决定在PRCode上建一个聚集索引来测试“Clustered Index Scan”和“Clustered Index Seek”。


Clustered Index Scan & Clustered Index Seek

下面的脚本删除PRID字段上的索引,并在PRCode字段上创建聚集索引。

 

Drop Index PerformanceIssue.UNC_PRID
GO
CREATE UNIQUE CLUSTERED INDEX UC_PRCode
ON PerformanceIssue( PRCode)
GO
-------------
Clustered index has been created successfully.
Index has been created.

 

关于聚集索引的基础知识请查阅联机帮助的相关主题或者 http://www.sql-server-performance.com/gv_index_data_structures.asp。下面我们将重点放在“Clustered Index Scan”和“Clustered Index Seek”如何被使用上。

执行下面查询语句:

 

Select PRID, PRCode, PRDesc
From PerformanceIssue
GO

 

查询执行后,可以看到执行计划中用到了“Clustered Index Scan”。

下面用三种不同的WHERE方式来试验何时SQL Server会用到“Clustered Index Seek”。第一种形式如下:

 

Select PRID, PRCode, PRDesc
From PerformanceIssue
Where PRDesc = ' PerformanceIssue - 8'
GO

 

查询执行后,可以看到执行计划中用到了“Clustered Index Scan”。

第二种形式如下:

 

Select PRID, PRCode, PRDesc
From PerformanceIssue
Where PRID = 'D386C151-5F74-4C2A-B527-86FEF9712955'

-- PRID GUID value might be differ in your machine
GO

 

查询执行后,发现执行计划中用到的仍然是“Clustered Index Scan”。

第三种形式:

 

Select PRID, PRCode, PRDesc
From PerformanceIssue
Where PRCode = 8
GO

 

这次执行计划用到了“Clustered Index Seek”。

当在WHERE后用到PRCode字段的时候,“Clustered Index Seek”被用到。执行计划对聚集索引表检索的时候,因为在选取的字段中,包括没有索引的字段,所以不用用到“Bookmark Lookup”方法。

我个人认为,从改善性能角度考虑,“Clustered Index Seek”比“Clustered Index Scan”和“Index Seek”要好。

 

  1. “Clustered Index Seek”不需要扫描整个聚集索引页。
  2. 和“Index Scan”相比,对于检索选择的字段包含那些没有索引的字段时,“Clustered Index Seek”不会有“Bookmark Lookup”方法出现。

 

通过这些试验,我对执行计划的应用积累了实际经验。我知道哪种扫描机制可以提高性能,从而是的客户满意。

 

posted @ 2008-04-08 23:38 金家寶 阅读(62) | 评论 (0)编辑 收藏

怎样查看sql的执行计划

如何启用AutoTrace 查看SQL执行计划

通过以下方法可以把Autotrace的权限授予Everyone,
如果你需要限制Autotrace权限,可以把对public的授权改为对特定user的授权。


D:\oracle\ora92>sqlplus /nolog
SQL*Plus: Release 9.2.0.1.0 - Production on 星期二 6月 3 15:16:03 2003
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
SQL> connect sys as sysdba
请输入口令:
已连接。
SQL> [b]@?\rdbms\admin\utlxplan[/b]
表已创建。
SQL> create public synonym plan_table for plan_table;
同义词已创建。
SQL> grant all on plan_table to public ;
授权成功。
SQL>[b] @?\sqlplus\admin\plustrce[/b]
SQL>
SQL> drop role plustrace;
drop role plustrace
*
ERROR 位于第 1 行:
ORA-01919: 角色'PLUSTRACE'不存在
SQL> create role plustrace;
角色已创建
SQL>
SQL> grant select on v_$sesstat to plustrace;
授权成功。
SQL> grant select on v_$statname to plustrace;
授权成功。
SQL> grant select on v_$session to plustrace;
授权成功。
SQL> grant plustrace to dba with admin option;
授权成功。
SQL>
SQL> set echo off


DBA用户首先被授予了plustrace角色,然后我们可以把plustrace授予public
这样所有用户都将拥有plustrace角色的权限.


SQL> [b]grant plustrace to public ;[/b]

授权成功。
然后我们就可以使用AutoTrace的功能了.


SQL> connect eqsp/eqsp
已连接。
SQL> set autotrace on
SQL> set timing on
SQL>


关于Autotrace几个常用选项的说明:
SET AUTOTRACE OFF ---------------- 不生成AUTOTRACE 报告,这是缺省模式
SET AUTOTRACE ON EXPLAIN ------ AUTOTRACE只显示优化器执行路径报告
SET AUTOTRACE ON STATISTICS -- 只显示执行统计信息
SET AUTOTRACE ON ----------------- 包含执行计划和统计信息
SET AUTOTRACE TRACEONLY ------ 同set autotrace on,但是不显示查询输出

SQL> set autotrace traceonly
SQL> select table_name from user_tables;
已选择98行。
已用时间: 00: 00: 00.04
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1 NESTED LOOPS (OUTER)
3 2 NESTED LOOPS (OUTER)
4 3 NESTED LOOPS (OUTER)
5 4 NESTED LOOPS (OUTER)
6 5 NESTED LOOPS
7 6 TABLE ACCESS (BY INDEX ROWID) OF 'OBJ$'
8 7 INDEX (RANGE SCAN) OF 'I_OBJ2' (UNIQUE)
9 6 TABLE ACCESS (CLUSTER) OF 'TAB$'
10 9 INDEX (UNIQUE SCAN) OF 'I_OBJ#' (NON-UNIQUE)
11 5 TABLE ACCESS (BY INDEX ROWID) OF 'OBJ$'
12 11 INDEX (UNIQUE SCAN) OF 'I_OBJ1' (UNIQUE)
13 4 INDEX (UNIQUE SCAN) OF 'I_OBJ1' (UNIQUE)
14 3 TABLE ACCESS (CLUSTER) OF 'USER$'
15 14 INDEX (UNIQUE SCAN) OF 'I_USER#' (NON-UNIQUE)
16 2 TABLE ACCESS (CLUSTER) OF 'SEG$'
17 16 INDEX (UNIQUE SCAN) OF 'I_FILE#_BLOCK#' (NON-UNIQUE)
18 1 TABLE ACCESS (CLUSTER) OF 'TS$'
19 18 INDEX (UNIQUE SCAN) OF 'I_TS#' (NON-UNIQUE)

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1389 consistent gets
0 physical reads
0 redo size
2528 bytes sent via SQL*Net to client
569 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
98 rows processed
SQL>
posted @ 2008-04-08 23:32 金家寶 阅读(129) | 评论 (0)编辑 收藏

怎样查看sql的执行计划

如何启用AutoTrace 查看SQL执行计划

通过以下方法可以把Autotrace的权限授予Everyone,
如果你需要限制Autotrace权限,可以把对public的授权改为对特定user的授权。


D:\oracle\ora92>sqlplus /nolog
SQL*Plus: Release 9.2.0.1.0 - Production on 星期二 6月 3 15:16:03 2003
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
SQL> connect sys as sysdba
请输入口令:
已连接。
SQL> [b]@?\rdbms\admin\utlxplan[/b]
表已创建。
SQL> create public synonym plan_table for plan_table;
同义词已创建。
SQL> grant all on plan_table to public ;
授权成功。
SQL>[b] @?\sqlplus\admin\plustrce[/b]
SQL>
SQL> drop role plustrace;
drop role plustrace
*
ERROR 位于第 1 行:
ORA-01919: 角色'PLUSTRACE'不存在
SQL> create role plustrace;
角色已创建
SQL>
SQL> grant select on v_$sesstat to plustrace;
授权成功。
SQL> grant select on v_$statname to plustrace;
授权成功。
SQL> grant select on v_$session to plustrace;
授权成功。
SQL> grant plustrace to dba with admin option;
授权成功。
SQL>
SQL> set echo off


DBA用户首先被授予了plustrace角色,然后我们可以把plustrace授予public
这样所有用户都将拥有plustrace角色的权限.


SQL> [b]grant plustrace to public ;[/b]

授权成功。
然后我们就可以使用AutoTrace的功能了.


SQL> connect eqsp/eqsp
已连接。
SQL> set autotrace on
SQL> set timing on
SQL>


关于Autotrace几个常用选项的说明:
SET AUTOTRACE OFF ---------------- 不生成AUTOTRACE 报告,这是缺省模式
SET AUTOTRACE ON EXPLAIN ------ AUTOTRACE只显示优化器执行路径报告
SET AUTOTRACE ON STATISTICS -- 只显示执行统计信息
SET AUTOTRACE ON ----------------- 包含执行计划和统计信息
SET AUTOTRACE TRACEONLY ------ 同set autotrace on,但是不显示查询输出

SQL> set autotrace traceonly
SQL> select table_name from user_tables;
已选择98行。
已用时间: 00: 00: 00.04
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 NESTED LOOPS
2 1 NESTED LOOPS (OUTER)
3 2 NESTED LOOPS (OUTER)
4 3 NESTED LOOPS (OUTER)
5 4 NESTED LOOPS (OUTER)
6 5 NESTED LOOPS
7 6 TABLE ACCESS (BY INDEX ROWID) OF 'OBJ$'
8 7 INDEX (RANGE SCAN) OF 'I_OBJ2' (UNIQUE)
9 6 TABLE ACCESS (CLUSTER) OF 'TAB$'
10 9 INDEX (UNIQUE SCAN) OF 'I_OBJ#' (NON-UNIQUE)
11 5 TABLE ACCESS (BY INDEX ROWID) OF 'OBJ$'
12 11 INDEX (UNIQUE SCAN) OF 'I_OBJ1' (UNIQUE)
13 4 INDEX (UNIQUE SCAN) OF 'I_OBJ1' (UNIQUE)
14 3 TABLE ACCESS (CLUSTER) OF 'USER$'
15 14 INDEX (UNIQUE SCAN) OF 'I_USER#' (NON-UNIQUE)
16 2 TABLE ACCESS (CLUSTER) OF 'SEG$'
17 16 INDEX (UNIQUE SCAN) OF 'I_FILE#_BLOCK#' (NON-UNIQUE)
18 1 TABLE ACCESS (CLUSTER) OF 'TS$'
19 18 INDEX (UNIQUE SCAN) OF 'I_TS#' (NON-UNIQUE)

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1389 consistent gets
0 physical reads
0 redo size
2528 bytes sent via SQL*Net to client
569 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
98 rows processed
SQL>
posted @ 2008-04-08 23:32 金家寶 阅读(92) | 评论 (0)编辑 收藏
问题:在drop procedure的时候发现一直没反应,查询原因
SQL> conn sys/pwd@sid as sysdba
已连接。
SQL> oradebug username
ORA-00070: 命令gdyf无效
SQL> oradebug setmypid
已处理的语句
SQL> oradebug hanganalyze 3
Hang Analysis in d:\oracle\admin\oracle\udump\oracle_ora_3200.trc
内容如下:
Dump file d:\oracle\admin\oracle\udump\oracle_ora_3200.trc
Tue Mar 18 15:39:01 2008
ORACLE V9.2.0.5.0 - Production vsnsta=0
vsnsql=12 vsnxtr=3
Windows 2000 Version 5.0 Service Pack 4, CPU type 586
Oracle9i Enterprise Edition Release 9.2.0.5.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.5.0 - Production
Windows 2000 Version 5.0 Service Pack 4, CPU type 586
Instance name: oracle
Redo thread mounted by this instance: 1
Oracle process number: 82
Windows thread id: 3200, image: ORACLE.EXE
*** SESSION ID:(26.2234) 2008-03-18 15:39:01.390
*** 2008-03-18 15:39:01.390
==============
HANG ANALYSIS:
==============
Open chains found:
Chain 1 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
    <0/48/20150/0x45a2b2e8/3336/No Wait>
-- <0/40/11993/0x45a29c68/3284/library cache lock>
Other chains found:
Chain 2 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
    <0/8/1/0x45a1ca68/2796/wakeup time manager>
Chain 3 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
    <0/26/2234/0x45a2dc28/3200/No Wait>
Chain 4 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
    <0/29/2338/0x45a25528/672/db file sequential read>
Chain 5 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
    <0/30/23502/0x45a23728/3224/db file sequential read>
Chain 6 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
    <0/64/22233/0x45a1f3a8/1892/No Wait>
Chain 7 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
    <0/69/1878/0x45a1dd28/2084/No Wait>
Extra information that will be dumped at higher levels:
[level  4] :   1 node dumps -- [REMOTE_WT] [LEAF] [LEAF_NW]
[level  5] :   6 node dumps -- [SINGLE_NODE] [SINGLE_NODE_NW] [IGN_DMP]
[level  6] :   1 node dumps -- [NLEAF]
[level 10] :  73 node dumps -- [IGN]
State of nodes
([nodenum]/cnode/sid/sess_srno/session/ospid/state/start/finish/[adjlist]/predecessor):
[0]/0/1/1/0x4520da08/3160/IGN/1/2//none
[1]/0/2/1/0x45a652ac/2828/IGN/3/4//none
[2]/0/3/1/0x4520e378/1924/IGN/5/6//none
[3]/0/4/1/0x45a65c1c/3308/IGN/7/8//none
[4]/0/5/1/0x4520ece8/156/IGN/9/10//none
[5]/0/6/1/0x45a6658c/1884/IGN/11/12//none
[6]/0/7/1/0x4520f658/3064/IGN/13/14//none
[7]/0/8/1/0x45a66efc/2796/SINGLE_NODE/15/16//none
[8]/0/9/18325/0x4520ffc8/2496/IGN/17/18//none
[12]/0/13/17667/0x452112a8/1928/IGN/19/20//none
[13]/0/14/18771/0x45a68b4c/816/IGN/21/22//none
[14]/0/15/9177/0x45211c18/2816/IGN/23/24//none
[15]/0/16/16965/0x45a694bc/3108/IGN/25/26//none
[16]/0/17/19671/0x45212588/2724/IGN/27/28//none
[17]/0/18/25029/0x45a69e2c/3272/IGN/29/30//none
[18]/0/19/11291/0x45212ef8/3080/IGN/31/32//none
[19]/0/20/25825/0x45a6a79c/3164/IGN/33/34//none
[20]/0/21/26486/0x45213868/448/IGN/35/36//none
[21]/0/22/21584/0x45a6b10c/2316/IGN/37/38//none
[22]/0/23/37646/0x452141d8/3340/IGN/39/40//none
[23]/0/24/5364/0x45a6ba7c/1468/IGN/41/42//none
[24]/0/25/33844/0x45214b48/2920/IGN/43/44//none
[25]/0/26/2234/0x45a6c3ec/3200/SINGLE_NODE_NW/45/46//none
[26]/0/27/28532/0x452154b8/2848/IGN/47/48//none
[28]/0/29/2338/0x45215e28/672/SINGLE_NODE/49/50//none
[29]/0/30/23502/0x45a6d6cc/3224/SINGLE_NODE/51/52//none
[31]/0/32/17993/0x45a6e03c/2580/IGN/53/54//none
[32]/0/33/21925/0x45217108/2584/IGN/55/56//none
[33]/0/34/20841/0x45a6e9ac/1316/IGN/57/58//none
[34]/0/35/19307/0x45217a78/3076/IGN/59/60//none
[35]/0/36/19269/0x45a6f31c/3092/IGN/61/62//none
[36]/0/37/11711/0x452183e8/2908/IGN/63/64//none
[37]/0/38/29651/0x45a6fc8c/2156/IGN/65/66//none
[38]/0/39/13933/0x45218d58/3332/IGN/67/68//none
[39]/0/40/11993/0x45a705fc/3284/NLEAF/69/72/[47]/none
[40]/0/41/23604/0x452196c8/3280/IGN/73/74//none
[41]/0/42/30238/0x45a70f6c/3312/IGN/75/76//none
[43]/0/44/15405/0x45a718dc/2528/IGN/77/78//none
[45]/0/46/33109/0x45a7224c/1920/IGN/79/80//none
[47]/0/48/20150/0x45a72bbc/3336/LEAF_NW/70/71//39
[48]/0/49/30884/0x4521bc88/2436/IGN/81/82//none
[49]/0/50/17150/0x45a7352c/2620/IGN/83/84//none
[50]/0/51/24541/0x4521c5f8/2376/IGN/85/86//none
[51]/0/52/20825/0x45a73e9c/2924/IGN/87/88//none
[52]/0/53/8516/0x4521cf68/764/IGN/89/90//none
[53]/0/54/16868/0x45a7480c/3320/IGN/91/92//none
[55]/0/56/14359/0x45a7517c/3356/IGN/93/94//none
[56]/0/57/32976/0x4521e248/2624/IGN/95/96//none
[57]/0/58/30428/0x45a75aec/3212/IGN/97/98//none
[58]/0/59/12175/0x4521ebb8/3268/IGN/99/100//none
[59]/0/60/15084/0x45a7645c/3032/IGN/101/102//none
[60]/0/61/31222/0x4521f528/1912/IGN/103/104//none
[61]/0/62/20108/0x45a76dcc/2564/IGN/105/106//none
[62]/0/63/32235/0x4521fe98/3376/IGN/107/108//none
[63]/0/64/22233/0x45a7773c/1892/SINGLE_NODE_NW/109/110//none
[64]/0/65/27250/0x45220808/1948/IGN/111/112//none
[65]/0/66/33424/0x45a780ac/3252/IGN/113/114//none
[66]/0/67/41625/0x45221178/3360/IGN/115/116//none
[67]/0/68/33495/0x45a78a1c/2420/IGN/117/118//none
[68]/0/69/1878/0x45221ae8/2084/SINGLE_NODE_NW/119/120//none
[70]/0/71/7937/0x45222458/3380/IGN/121/122//none
[71]/0/72/18116/0x45a79cfc/1448/IGN/123/124//none
[72]/0/73/37603/0x45222dc8/2936/IGN/125/126//none
[73]/0/74/23965/0x45a7a66c/2480/IGN/127/128//none
[74]/0/75/7067/0x45223738/3300/IGN/129/130//none
[75]/0/76/8541/0x45a7afdc/1068/IGN/131/132//none
[76]/0/77/9178/0x452240a8/2360/IGN/133/134//none
[77]/0/78/25889/0x45a7b94c/2864/IGN/135/136//none
[78]/0/79/11006/0x45224a18/2996/IGN/137/138//none
[79]/0/80/19934/0x45a7c2bc/3384/IGN/139/140//none
[80]/0/81/24305/0x45225388/3136/IGN/141/142//none
[81]/0/82/27089/0x45a7cc2c/2744/IGN/143/144//none
[82]/0/83/15792/0x45225cf8/3236/IGN/145/146//none
[83]/0/84/19887/0x45a7d59c/2788/IGN/147/148//none
[86]/0/87/20152/0x45226fd8/2284/IGN/149/150//none
[87]/0/88/7617/0x45a7e87c/2776/IGN/151/152//none
[88]/0/89/33192/0x45227948/3248/IGN/153/154//none
[89]/0/90/22038/0x45a7f1ec/2652/IGN/155/156//none
[90]/0/91/31249/0x452282b8/2852/IGN/157/158//none
[91]/0/92/15647/0x45a7fb5c/3088/IGN/159/160//none
[92]/0/93/3053/0x45228c28/3100/IGN/161/162//none
====================
END OF HANG ANALYSIS
====================


发现是如下出现问题:
Chain 1 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
    <0/48/20150/0x45a2b2e8/3336/No Wait>
-- <0/40/11993/0x45a29c68/3284/library cache lock>

当前drop的session为40,然后查询48的session,居然是前面做重编译时候未成功退出的一个SESSION
然后orakill 这个session后正常drop完成
posted @ 2008-04-08 23:30 金家寶 阅读(65) | 评论 (0)编辑 收藏

C、语句级别
这些需要用到Hint,比如:
SQL> SELECT /*+ RULE */ a.userid,
2 b.name,
3 b.depart_name
4 FROM tf_f_yhda a,
5 tf_f_depart b
6 WHERE a.userid=b.userid;

4、为什么有时一个表的某个字段明明有索引,当观察一些语的执行计划确不走索引呢?如何解决呢 ?

A、不走索引大体有以下几个原因
♀你在Instance级别所用的是all_rows的方式
♀你的表的统计信息(最可能的原因)
♀你的表很小,上文提到过的,Oracle的优化器认为不值得走索引。

B、解决方法
♀可以修改init<SID>.ora中的OPTIMIZER_MODE这个参数,把它改为Rule或Choose,重起数据库。也可以使用4中所提的Hint.
♀删除统计信息
SQL>analyze table table_name delete statistics;
♀表小不走索引是对的,不用调的。

5、其它相关

A、如何看一个表或索引是否是统计信息

SQL>SELECT * FROM user_tables
2 WHERE table_name=<table_name>
3 AND num_rows is not null;
SQL>SELECT * FROM user_indexes
2 WHERE table_name=<table_name>
3 AND num_rows is not null;

b、如果我们先用CBO的方式,我们应及时去更新表和索引的统计信息,以免生形不切合实的执行计划。

SQL> ANALYZE TABLE table_name COMPUTE STATISTICS;
SQL> ANALYZE INDEX index_name ESTIMATE STATISTICS;

具体的ANALYZE语句请参照Oracle8i/9i 的refrence文档。
<================end of file“Oracle的优化器(Optimizer)”=====================>


下面的是我的关于一点执行计划的理解:

1。首先要启动trace的选项:
set autotrace trace eXPlain
如果出现下面的错误:

SQL>  set autotrace trace explain
SP2-0613: Unable to verify PLAN_TABLE format or existence
SP2-0611: Error enabling EXPLAIN report

那么要先运行下面的语句:
 @?/rdbms/admin/utlxplan.sql;

2。分析下面的执行计划:

SQL> select ename,dname    from emp, dept   where emp.deptno=dept.deptno     and dept.dname in ('ACCOUNTING','RESEARCH','SALES','OPERATIONS');

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)

关于前面的两个数字,第一个是状态ID,第二个是父ID。
就是如下所示:0-->1-->2
                        
                         -->3-->4
在上图里,0的执行依靠1,1的执行又依赖2和3,2是没有子ID的,所以2最先执行,然后是4,在然后是3;然后2和3的结果传回1。
在这个里面0行有个字“Optimizer=CHOOSE”,这个就是上文说的那个oracle的优化器了。
还有,看这个“ INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE)”,就知道这个语句运行的时候是走INDEX的。

posted @ 2008-04-08 23:19 金家寶 阅读(46) | 评论 (0)编辑 收藏
技术交流