(3)校正聚簇因子(CLUSTERING_FACTOR )——下
来源:互联网 发布:淘宝子账号设置权重 编辑:程序博客网 时间:2024/05/16 12:17
1、ASSM带来的性能问题
ASSM通过增加数据的分布的随机性来减少争用。在ASSM下,并发的进程基本都选择不同的块来插入数据行。因此,在我们使用序列或者以日期作为插入顺序的表并在其上面建立索引的话,可能将会导致索引的聚簇因子比较大。
SQL> create tablespace assm datafile '+DG' size 100m autoextend on next 100m maxsize 1g segment space management auto;表空间已创建。SQL> create tablespace mssm datafile '+DG' size 100m autoextend on next 100m maxsize 1g segment space management manual;表空间已创建。SQL> select tablespace_name,segment_space_management from dba_tablespaces where tablespace_name in ('ASSM','MSSM');TABLESPACE_NAME SEGMEN------------------------------ ------ASSM AUTOMSSM MANUALSQL> create table assm_test(id int,flag char(1)) tablespace assm;表已创建。SQL> create table mssm_test(id int,flag char(1)) tablespace mssm;表已创建。SQL> create sequence assm_s;序列已创建。SQL> create sequence mssm_s;序列已创建。
首先创建2序列和2个表,一个创建在ASSM管理的表空间下,另一个创建在手工段空间管理的表空间下。
SQL> create or replace procedure load_assm_data(v_flag char) as 2 begin 3 for i in 1 .. 1000 loop 4 insert into assm_test values (assm_s.nextval, v_flag); 5 end loop; 6 commit; 7 end; 8 /过程已创建。SQL> create or replace procedure load_mssm_data(v_flag char) as 2 begin 3 for i in 1 .. 1000 loop 4 insert into mssm_test values (mssm_s.nextval, v_flag); 5 end loop; 6 commit; 7 end; 8 /过程已创建。
分别创建2个过程用来为表ASSM_TEST和MSSM_TEST加载数据。
SQL> declare 2 jobname varchar2(30); 3 BEGIN 4 FOR I IN 0..4 LOOP 5 JOBNAME:=DBMS_SCHEDULER.GENERATE_JOB_NAME; 6 DBMS_SCHEDULER.CREATE_JOB( 7 job_name=>JOBNAME, 8 job_type=>'STORED_PROCEDURE', 9 job_action=>'LOAD_ASSM_DATA', 10 auto_drop=>TRUE, 11 enabled=>FALSE, 12 number_of_arguments=>1); 13 DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE(JOBNAME,1,CHR(65+I)); DBMS_SCHEDULER.ENABLE(JOBNAME); END LOOP; END; / PL/SQL 过程已成功完成。 SQL> declare jobname varchar2(30); BEGIN FOR I IN 0..4 LOOP JOBNAME:=DBMS_SCHEDULER.GENERATE_JOB_NAME; DBMS_SCHEDULER.CREATE_JOB( job_name=>JOBNAME, job_type=>'STORED_PROCEDURE', job_action=>'LOAD_MSSM_DATA', auto_drop=>TRUE, enabled=>FALSE, number_of_arguments=>1); DBMS_SCHEDULER.SET_JOB_ARGUMENT_VALUE(JOBNAME,1,CHR(65+I)); DBMS_SCHEDULER.ENABLE(JOBNAME); END LOOP; END;PL/SQL 过程已成功完成。
使用JOB的方式,同时启动5个并发进程,向表assm_test和mssm_test插入数据。
SQL> create index assm_test_idx on assm_test(id);索引已创建。SQL> create index mssm_test_idx on mssm_test(id);索引已创建。SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER,'ASSM_TEST',CASCADE=>TRUE);PL/SQL 过程已成功完成。SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER,'MSSM_TEST',CASCADE=>TRUE);PL/SQL 过程已成功完成。SQL> SELECT TABLE_NAME,BLOCKS,NUM_ROWS FROM USER_TABLES WHERE TABLE_NAME IN ('ASSM_TEST','MSSM_TEST');TABLE_NAME BLOCKS NUM_ROWS------------------------------ ---------- ----------ASSM_TEST 20 5000MSSM_TEST 12 5000SQL> SELECT INDEX_NAME,BLEVEL,LEAF_BLOCKS,CLUSTERING_FACTOR FROM USER_INDEXES WHERE TABLE_NAME IN ('ASSM_TEST','MSSM_TEST');INDEX_NAME BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR------------------------------ ---------- ----------- -----------------ASSM_TEST_IDX 1 11 963MSSM_TEST_IDX 1 11 20
很明显,ASSM下的空间管理方式下的聚簇因子远远大于手工段空间管理模式下的。
SQL> SELECT DISTINCT DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) BLOCK# FROM ASSM_TEST; BLOCK#---------- 134 132 141 133 143 135 131 142 145已选择9行。
可以看到,表ASSM_TEST只有20个BLOCKS,实际表的数据只占用了9个BLOCK,但是聚簇因子却达到了963。 这就是ASSM在避免了表争用问题带来的一个副作用。
SQL> SELECT BLOCK#, COUNT(*) 2 FROM (SELECT DISTINCT DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) BLOCK#, FLAG 3 FROM ASSM_TEST) 4 GROUP BY BLOCK#; BLOCK# COUNT(*)---------- ---------- 134 2 132 1 141 1 133 3 143 1 135 4 131 1 142 1 145 1已选择9行。
可以看到大部分块,被一个进程使用,减少了争用。而在MSSM下,一个块基本被多个进程争用。
SQL> SELECT BLOCK#, COUNT(*) 2 FROM (SELECT DISTINCT DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) BLOCK#, FLAG 3 FROM MSSM_TEST) 4 GROUP BY BLOCK#; BLOCK# COUNT(*)---------- ---------- 129 1 134 4 132 4 133 4 135 4 136 4 130 5 131 4已选择8行。
下面看看,ASSM对执行计划的影响:
SQL> SELECT * FROM MSSM_TEST WHERE ID BETWEEN 1 AND 50;已选择49行。执行计划----------------------------------------------------------Plan hash value: 2228967704---------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 49 | 294 | 3 (0)| 00:00:01 || 1 | TABLE ACCESS BY INDEX ROWID| MSSM_TEST | 49 | 294 | 3 (0)| 00:00:01 ||* 2 | INDEX RANGE SCAN | MSSM_TEST_IDX | 49 | | 2 (0)| 00:00:01 |---------------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("ID">=1 AND "ID"<=50)统计信息---------------------------------------------------------- 0 recursive calls 0 db block gets 11 consistent gets 0 physical reads 0 redo size 1385 bytes sent via SQL*Net to client 448 bytes received via SQL*Net from client 5 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 49 rows processed
我们从5000行的数据里选取了50行,选择率大约为1/100。此时索引扫描相对较好。
SQL> SELECT * FROM ASSM_TEST WHERE ID BETWEEN 1 AND 50;已选择49行。执行计划----------------------------------------------------------Plan hash value: 166377213-------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 49 | 294 | 5 (0)| 00:00:01 ||* 1 | TABLE ACCESS FULL| ASSM_TEST | 49 | 294 | 5 (0)| 00:00:01 |-------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 1 - filter("ID"<=50 AND "ID">=1)统计信息---------------------------------------------------------- 0 recursive calls 0 db block gets 27 consistent gets 0 physical reads 0 redo size 1274 bytes sent via SQL*Net to client 448 bytes received via SQL*Net from client 5 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 49 rows processed
但是在ASSM下,ORACLE却选择了成本较高的全表扫描。这就是ASSM的特性带来的对执行计划的影响。如果使用索引,ORACLE计算出来的成本会比全表扫描高。但实际走索引的效率会更好,从逻辑读取也可以看得出来。
SQL> SELECT /*+INDEX(ASSM_TEST)*/ * FROM ASSM_TEST WHERE ID BETWEEN 1 AND 50;已选择49行。执行计划----------------------------------------------------------Plan hash value: 3633427144---------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 49 | 294 | 12 (0)| 00:00:01 || 1 | TABLE ACCESS BY INDEX ROWID| ASSM_TEST | 49 | 294 | 12 (0)| 00:00:01 ||* 2 | INDEX RANGE SCAN | ASSM_TEST_IDX | 49 | | 2 (0)| 00:00:01 |---------------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("ID">=1 AND "ID"<=50)统计信息---------------------------------------------------------- 0 recursive calls 0 db block gets 11 consistent gets 0 physical reads 0 redo size 1385 bytes sent via SQL*Net to client 448 bytes received via SQL*Net from client 5 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 49 rows processed
2、校正CLUSTERING_FACTOR
(1)、重新组织表
SQL> CREATE TABLE ASSM_TEST_2 TABLESPACE ASSM AS SELECT * FROM ASSM_TEST ORDER BY ID;表已创建。SQL> CREATE INDEX ASSM_TEST_2_IDX ON ASSM_TEST_2(ID);索引已创建。SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER,'ASSM_TEST_2',CASCADE=>TRUE);PL/SQL 过程已成功完成。SQL> SELECT TABLE_NAME,BLOCKS,NUM_ROWS FROM USER_TABLES WHERE TABLE_NAME LIKE '%SSM%';TABLE_NAME BLOCKS NUM_ROWS------------------------------ ---------- ----------ASSM_TEST 20 5000MSSM_TEST 12 5000ASSM_TEST_2 11 5000SQL> SELECT INDEX_NAME,BLEVEL,LEAF_BLOCKS,CLUSTERING_FACTOR FROM USER_INDEXES WHERE TABLE_NAME LIKE '%SSM%';INDEX_NAME BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR------------------------------ ---------- ----------- -----------------MSSM_TEST_IDX 1 11 20ASSM_TEST_2_IDX 1 11 8ASSM_TEST_IDX 1 11 963SQL> set autotrace trace;SQL> SELECT * FROM ASSM_TEST_2 WHERE ID BETWEEN 1 AND 50;已选择49行。执行计划----------------------------------------------------------Plan hash value: 1713382986-----------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-----------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 49 | 294 | 3 (0)| 00:00:01 || 1 | TABLE ACCESS BY INDEX ROWID| ASSM_TEST_2 | 49 | 294 | 3 (0)| 00:00:01 ||* 2 | INDEX RANGE SCAN | ASSM_TEST_2_IDX | 49 | | 2 (0)| 00:00:01 |-----------------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("ID">=1 AND "ID"<=50)统计信息---------------------------------------------------------- 1 recursive calls 0 db block gets 11 consistent gets 0 physical reads 0 redo size 1385 bytes sent via SQL*Net to client 448 bytes received via SQL*Net from client 5 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 49 rows processed
我们复制了一个与ASSM_TEST一模一样的表。可以看到,重新组织表后,使ORACLE从全表扫描走了索引扫描。
(2)使用SYS_OP_COUNTCHG()来校正CLUSTERING_FACTOR
SQL> ALTER SESSION SET SQL_TRACE TRUE;会话已更改。SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER,'ASSM_TEST',CASCADE=>TRUE);PL/SQL 过程已成功完成。SQL> ALTER SESSION SET SQL_TRACE FALSE;会话已更改。SQL> select d.value || '/' || lower(rtrim(i.instance, chr(0))) || '_ora_' || 2 from (select p.spidc' trace_file_name p.spid || '.trc' trace_file_name 3 from (select p.spid 4 from v$mystat m, v$session s, v$process p 5 where m.statistic# = 1 6 and s.sid = m.sid 7 and p.addr = s.paddr) p, 8 (select t.instance 9 from v$thread t, v$parameter v 10 where v.name = 'thread' 11 and (v.value = 0 or t.thread# = to_number(v.value))) i, 12 (select value from v$parameter where name = 'user_dump_dest') d;TRACE_FILE_NAME--------------------------------------------------------------------------------/u01/app/diag/rdbms/orcl/orcl/trace/orcl_ora_5714.trcSQL> exit从 Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - ProductionWith the Partitioning, Automatic Storage Management, OLAP, Data Miningand Real Application Testing options 断开[oracle@linux ~]$ su - root口令:[root@linux ~]# cd /u01/event/[root@linux event]# cp /u01/app/diag/rdbms/orcl/orcl/trace/orcl_ora_5714.trc .[root@linux event]# tkprof orcl_ora_5714.trc orcl_ora_5714.txtTKPROF: Release 11.2.0.1.0 - Development on 星期二 2月 5 21:35:29 2013Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved.
启用SQL跟踪,格式化跟踪文件,并在跟踪文件中找到如下SQL语句。
select /*+ no_parallel_index(t, "ASSM_TEST_IDX") dbms_stats cursor_sharing_exact use_weak_name_resl dynamic_sampling(0) no_monitoring no_substrb_pad no_expand index(t,"ASSM_TEST_IDX") */ count(*) as nrw, count(distinct sys_op_lbid(102382,'L',t.rowid)) as nlb,null as ndk, sys_op_countchg(substrb(t.rowid,1,15),1) as clf from "U1"."ASSM_TEST" t where "ID" is not null
其中,NRW=USER_INDEXES.NUM_ROWS,
NLB=USER_INDEXES.LEAF_BLOCKS,
NDK=USER_INDEXES.NUM_DISTINCT,
CLF=USER_INDEXES.CLUSTERING_FACTOR。
修改 sys_op_countchg(substrb(t.rowid,1,15),1) as clf 第二个参数为5(并发的进程数),并在SQLPLUS执行,将得到的CLF值写回到数据字典中。。
SQL> select /*+ no_parallel_index(t, "ASSM_TEST_IDX") dbms_stats 2 cursor_sharing_exact use_weak_name_resl dynamic_sampling(0) no_monitoring 3 no_substrb_pad no_expand index(t,"ASSM_TEST_IDX") */ 4 count(*) as nrw, 5 count(distinct sys_op_lbid(102382, 'L', t.rowid)) as nlb, 6 null as ndk, 7 sys_op_countchg(substrb(t.rowid, 1, 15), 5) as clf from "U1"."ASSM_TEST" t 9 where "ID" is not null; NRW NLB N CLF---------- ---------- - ---------- 5000 11 9SQL> SELECT INDEX_NAME,BLEVEL,LEAF_BLOCKS,CLUSTERING_FACTOR FROM USER_INDEXES WHERE TABLE_NAME LIKE '%SSM%';INDEX_NAME BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR------------------------------ ---------- ----------- -----------------MSSM_TEST_IDX 1 11 20ASSM_TEST_2_IDX 1 11 8ASSM_TEST_IDX 1 11 963SQL> exec dbms_stats.set_index_stats(user,'ASSM_TEST_IDX',CLSTFCT=>9);PL/SQL 过程已成功完成。SQL> SELECT INDEX_NAME,BLEVEL,LEAF_BLOCKS,CLUSTERING_FACTOR FROM USER_INDEXES WHERE TABLE_NAME LIKE '%SSM%';INDEX_NAME BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR------------------------------ ---------- ----------- -----------------MSSM_TEST_IDX 1 11 20ASSM_TEST_2_IDX 1 11 8ASSM_TEST_IDX 1 11 9SQL> set autotrace trace;SQL> SELECT * FROM ASSM_TEST WHERE ID BETWEEN 1 AND 50;已选择49行。执行计划----------------------------------------------------------Plan hash value: 3633427144---------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 49 | 294 | 3 (0)| 00:00:01 || 1 | TABLE ACCESS BY INDEX ROWID| ASSM_TEST | 49 | 294 | 3 (0)| 00:00:01 ||* 2 | INDEX RANGE SCAN | ASSM_TEST_IDX | 49 | | 2 (0)| 00:00:01 |---------------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("ID">=1 AND "ID"<=50)统计信息---------------------------------------------------------- 1 recursive calls 0 db block gets 11 consistent gets 0 physical reads 0 redo size 1385 bytes sent via SQL*Net to client 448 bytes received via SQL*Net from client 5 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 49 rows processed
此时,ORACLE也是从全表扫描转为索引扫描。
(3)总结
当使用当oracle使用MSSM时,freelists > 1:sys_op_countchg函数第二个参数就等于freelists。freelist_groups > 1:sys_op_countchg函数第二个参数就等于freelists * freelist_groups
freelists和freelist_groups可以用这个sql查到: select t.freelists,t.freelist_groups,t.* from user_tables t;
当oracle使用ASSM时,它可以同时分配16个新块并进行格式化。这就意味着新的数据将粗略的散布在这16块中,而不是紧密的聚合在一起。
调用sys_op_countchg()函数并将起参数设定为16,这样已经足以产生一个合理的clustering_factor,以取代当前这个毫无意义的值。但是参数16应该作为上限。如果并发进程的数目一般小于16,那么就应该使用并发进程真正的数目作为参数。
反转键索引、为索引添加列和对索引中的列进行重新排序等。函数sys_op_countchg()对这些问题没有帮助。可以通过创建一个只包括驱动列的索引,并计算该索引的clustering_factor,最后将其值传递给原来的索引。
SQL> select sys_op_countchg(substrb(t.rowid,1,15),5) as clf from ASSM_TEST t where "ID" is not null; CLF---------- 9SQL> SQL> select sys_op_countchg(substrb(t.rowid,1,15),9) as clf from ASSM_TEST t where "ID" is not null; CLF---------- 9SQL> SQL> select sys_op_countchg(substrb(t.rowid,1,15),16) as clf from ASSM_TEST t where "ID" is not null; CLF---------- 9
在前面的例子中,我设置ASSM_TEST表的并发为5,计算出的clustering_factor为9;通过前面我还可以知道ASSM_TEST在数据主要分布在9个块中国,计算出的clustering_factor还是为9;如果设置并发上线16,计算出的clustering_factor还是为9。在实际工作中,我们不好估算并发的准确数字,就直接传递参数为16也未尝不是一个办法。
- (3)校正聚簇因子(CLUSTERING_FACTOR )——下
- (3)聚簇因子(CLUSTERING_FACTOR )——上
- DBA_INDEXES.CLUSTERING_FACTOR 索引的群集因子初探
- clustering_factor
- 下校正
- 图像校正—透视变换
- 相机去畸变,以及双目平行校正----极线校正(一)————之单目畸变校正详细过程
- 相机去畸变,以及双目平行校正----极线校正(二)————之双目平行校正详细过程
- 相机去畸变,以及双目平行校正----极线校正(一)————之单目畸变校正详细过程
- 相机去畸变,以及双目平行校正----极线校正(一)————之单目畸变校正详细过程
- 相机去畸变,以及双目平行校正----极线校正(一)————之单目畸变校正详细过程
- 相机去畸变,以及双目平行校正----极线校正(二)————之双目平行校正详细过程
- 图像预处理——透视变换(三):校正步骤
- MVG读书笔记——射影变换的校正(零)
- MVG读书笔记——射影变换的校正(一)
- MVG读书笔记——射影变换的校正(二)
- MVG读书笔记——射影变换的校正(三)
- Oracle聚簇因子(clustering factor)
- CF Round#10
- 音视频解决方案中的即时通讯开发技术
- OpenWRT自定义组件和编译
- 谈谈语音视频聊天
- 中断触发方式的比较
- (3)校正聚簇因子(CLUSTERING_FACTOR )——下
- windows程序员进阶系列:《软件调试》之四:断点和单步调试
- jQuery笔记
- android不能使用udp获取数据解决
- 萤火虫为增加LED亮度带来灵感
- 监听连接时间过长的解决
- 纳米发电机:摩擦静电驱动手机
- SAP R3 主流系统EAI接口技术剖析
- 在同一个jsp页面上即使用字符流,又使用字节流就会出现以下异常:getOutputStream() has already been called for this response