Fosdccf.blog.chinaunix.net
sdccf
全部博文(19283)
Linux酷软(214)
tmp(0)
PostgreSQL(93)
Solaris(383)
AIX(173)
SCOUNIX(575)
DB2(1005)
Shell(386)
C/C++(1187)
MySQL(1750)
Sybase(465)
Oracle(3695)
Informix(548)
HP-UX(0)
IBM AIX(2)
Sun Solaris(0)
BSD(1)
Linux(8597)
SCO UNIX(23)
2011年(1)
2009年(125)
2008年(19094)
2007年(63)
clifford
linky521
曾德标
fengzhan
leon_yu
mcuflowe
yt200902
guanyuji
GY123456
snow888
carlos94
丸喵喵
sean229
cxunix
可怜的猪
cqxc413
xzzgege
wb123456
分类: Oracle
2008-04-30 15:16:47
Oracle的consistent gets是如何计算的呢?1.单表扫描SQL> execute show_space('TEST1','WWJ');Unformatted Blocks ..................... 0FS1 Blocks (0-25) ..................... 0FS2 Blocks (25-50) ..................... 1FS3 Blocks (50-75) ..................... 0FS4 Blocks (75-100)..................... 0Full Blocks ..................... 33Total Blocks............................ 40Total Bytes............................. 327,680Total MBytes............................ 0Unused Blocks........................... 1Unused Bytes............................ 8,192Last Used Ext FileId.................... 5Last Used Ext BlockId................... 3,321Last Used Block......................... 7PL/SQL 过程已成功完成。多次运行,获得稳定的consistent getsSQL> select * from test1;已选择12402行。执行计划----------------------------------------------------------Plan hash value: 4122059633---------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 12402 | 169K| 9 (0)| 00:00:01 || 1 | TABLE ACCESS FULL| TEST1 | 12402 | 169K| 9 (0)| 00:00:01 |---------------------------------------------------------------------------统计信息---------------------------------------------------------- 0 recursive calls 0 db block gets 861 consistent gets 0 physical reads 0 redo size 379486 bytes sent via SQL*Net to client 9471 bytes received via SQL*Net from client 828 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 12402 rows processed数据究竟分布在多少个块上?SQL> SELECT count(DISTINCT dbms_rowid.rowid_block_number(ROWID)) FROM test1;COUNT(DISTINCTDBMS_ROWID.ROWID------------------------------ 34也可以用show_space的结果,Full Blocks + FS2 Blocks (25-50) =34公式:consistent gets = rownum / fetch array size + used datablock 861 = CEIL(12402 / 15) + 342.Hash join,TEST11表结构和TETS1一致,数据量,数据块都一致。SQL> SELECT * FROM TEST1 A2 WHERE NOT EXISTS(SELECT b.c13 FROM test11 b4 WHERE b.c1 = a.c1)5 /已选择8671行。执行计划-------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 35 | 665 | 20 (10)| 00:00:01 ||* 1 | HASH JOIN RIGHT ANTI| | 35 | 665 | 20 (10)| 00:00:01 || 2 | TABLE ACCESS FULL | TEST11 | 12404 | 62020 | 9 (0)| 00:00:01 || 3 | TABLE ACCESS FULL | TEST1 | 12402 | 169K| 9 (0)| 00:00:01 |-------------------------------------------------------------------------------统计信息---------------------------------------------------------- 650 consistent getsconsistent gets = rownum / fetch array size + probe table's block + build table's block + 其它probe表为test1,sql将请求他所有的块,所有产生34次一致读build表为test11,进程将它读取到hash区域,产生34次一致读650 = CEIL (8671/15)+34+34+4其它也许是oracle在请求hash内存产生的内部一致读,可以忽略。3.FILTER操作。这个sql的结果和2一样,但很低效。从对产生一致读的分析,我们还可以了解为什么filter在这里很低效。但是关于filter的机制,我找了几天也没有在任何文档看到,这里仅仅是我自己的设想。SQL> SELECT * FROM test1 a WHERE a.c1 NOT IN (SELECT b.c1 FROM test11 b);已选择8671行。执行计划-----------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-----------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 12401 | 169K| 58720 (5)| 00:11:45 ||* 1 | FILTER | | | | | || 2 | TABLE ACCESS FULL| TEST1 | 12402 | 169K| 9 (0)| 00:00:01 ||* 3 | TABLE ACCESS FULL| TEST11 | 1 | 5 | 9 (0)| 00:00:01 |-----------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 1 - filter( NOT EXISTS (SELECT /*+ */ 0 FROM "TEST11" "B" WHERE LNNVL("B"."C1"<>:B1))) 3 - filter(LNNVL("B"."C1"<>:B1)) PS:这里可以看出optimizer已经把sql改写为NOT EXISTS了,但是却是LNNVL("B"."C1"<>:B1)连接,已经很接近产生hash的sql。统计信息---------------------------------------------------------- 380719 consistent gets首先,我认为oracle会把TEST1的所有所有数据,装载进一个list,这里产生34个一致读。然后依次读取这个list中的每一个值,再根据这个值对TEST11进行过滤。FILTER过滤是怎么做的呢?最初我曾经以为oracle会把两个表做descartes,然后再做<>过滤。但和实际descartes比,成本相差太大。所以应该不是descartes。那是什么呢?从这里观察:TABLE ACCESS FULL| TEST11 | 1 |这个1 是ROWS,表示这里的operation只包含一行。再看: 1 - filter( NOT EXISTS (SELECT /*+ */ 0 FROM "TEST11" "B" WHERE LNNVL("B"."C1"<>:B1))) 3 - filter(LNNVL("B"."C1"<>:B1))LNNVL是oracle的函数,意思是IS NULL OR NOT TRUE,这样我认为过程是这样的,绑定变量:B1实际是list的一个取值。首先判断在TEST11里面是否存在空值比较或者C1=:B1的,如果发现了一行满足条件那么NOT EXISTS条件就不成立。java伪代码如下:List list = new Linklist();//创建链表list = Test1Dao.listC1();//循环链表while(list.size >0){String c1 = list.remove(0);//在test11中寻找if(Test11Dao.find(c1)){ //找到了,不满足条件}else{ //告诉client没有找到,满足,返回结果 }}这样list的每一条记录都会请求test11的块,但是它的机制是发现一行即返回,所以每次他可能会扫描1~34块,产生相应数量的一致读。那么我来模拟计算过程,通过如下SQL:WITH t AS (SELECT c1,dense_rank() over(ORDER BY dbms_rowid.rowid_block_number(ROWID)) bn FROM test11)SELECT test1.c1,nvl(t.bn,34),SUM(nvl(t.bn,34)) over() FROM test1LEFT JOIN t ON t.c1= test1.c1结果节选如下:rownum c1 bn sum(bn)1 58153 1 3671992 55746 1 3671993 17523 1 367199...550 48108 5 367199551 22515 5 367199552 66287 5 367199...4162 7724 34 3671994163 28976 34 3671994164 6128 34 3671994165 39064 null 3671994166 8441 null 3671994167 51435 null 367199首先,我假设oracle在做filter时候,选择数据块的顺序是和client获得数据的顺序是差不多的。SELECT c1,dense_rank() over(ORDER BY dbms_rowid.rowid_block_number(ROWID)) bn FROM test11获得的,是test11的数据,和每条数据按数据块位置的排序。然后和test1做连接,这样bn的结果就是test1中每条记录,要做多少次块请求,才能获得结果。如果bn为null说明在test11中没有test1需要的值,则需要扫描所有34块才能得知。这样sum(sn)就统计出所有请求产生的一致读。那么380719 ≈367199 + CEIL(8671/15)+34 +34 + 其它+误差实际已经比较接近了。如果有人知道真相,请告诉我。4.SQL> select * from test1 where 1=2不会产生一致读,oracle优化器会立刻知道这是一个否条件。0 consistent gets5.SQL> select * from test1 where c1<0; 37 consistent gets除了数据存在的34个块,还有3个extent header块。...对一致读的计算,暂时就到这里,以后会对更多的优化器行为,做一致读算法描述。实际本文是我在思考filter的机制的过程,所记录的(我曾在itpub发帖询问,未获答案)。
原文:http://valen.blog.ccidnet.com/blog-htm-itemid-273622-do-showone-type-blog-uid-51502.html
上一篇:Oracle并发插入的机制
下一篇:http://valen.blog.ccidnet.com/blog-htm-itemid-2715
登录 注册