第十四章:常用Oracle工具
点击数:1934发布日期:2020-04-19 15:23:48 来源:老鹰
第十四章:常用Oracle工具在实际生产中的使用案例
14.1 10053事件介绍及使用案例
1. 10053事件介绍
10053是Oracle官方非公开的一个事件,用来跟踪Oracle选择执行计划的过程,比如当发现一个SQL应该使用索引,但却选择了全表扫描,或者没有选择正确的索引,可以采用10053事件来找到问题的根源所在。
10053事件有两个级别:
Level 2:2级是1级的一个子集,它包含以下内容:
Column statistics
Single Access Paths
Join Costs
Table Joins Considered
Join Methods Considered (NL/MS/HA)
Level 1: 1级比2级更详细,它除了2级的内容外,还包括了:
Parameters used by the optimizer
Index statistics
启用10053事件的命令如下:
alter session set events='10053 trace name context forever, level 1';
alter session set events='10053 trace name context forever, level 2';
关闭10053事件:
alter session set events '10053 trace name context off';
2. 10053诊断案例之索引选择不当导致SQL性能下降
(1) 问题描述
在AWR报告里可见如下单次逻辑读较高的SQL:
Gets CPU Elapsed
Buffer Gets Executions per Exec %Total Time (s) Time (s) SQL Id
-------------- ------------ ------------ ------ -------- --------- -------------
71,412,938 652 109,529.0 27.3 639.27 671.98 2z49614gwr98z
SELECT A.CREDIT_NO, A.TRAN_TYPE, A.PAY_ACCNO, C.ACC_NAME, C.OPENACC_DEPT, A.REC
V_ACCNO, A.RECV_ACC_NAME, A.RECV_OPENACC_DEPT, A.AMOUNT, A.USEOF, A.CREDIT_NO, A
.STATUS, A.OPER_NAME, TO_CHAR(A.MAK_DATE, 'YYYY-MM-DD HH24:MI:SS'),A.CHECK_NAME,
TO_CHAR(A.CHK_DATE, 'YYYY-MM-DD HH24:MI:SS'),A.ADMIN_NAME, TO_CHAR(A.APP_DATE,
24,292,778 230 105,620.8 9.3 217.71 218.02 2cnsd4n2tzdxq
SELECT A.CREDIT_NO, A.TRAN_TYPE, A.PAY_ACCNO, C.ACC_NAME, C.OPENACC_DEPT, A.REC
V_ACCNO, A.RECV_ACC_NAME, A.RECV_OPENACC_DEPT, A.AMOUNT, A.USEOF, A.CREDIT_NO, A
.STATUS, A.OPER_NAME, TO_CHAR(A.MAK_DATE, 'YYYY-MM-DD HH24:MI:SS'),A.CHECK_NAME,
TO_CHAR(A.CHK_DATE, 'YYYY-MM-DD HH24:MI:SS'),A.ADMIN_NAME, TO_CHAR(A.APP_DATE,
14,604,128 141 103,575.4 5.6 128.52 128.92 g9823uvsvt121
SELECT A.CREDIT_NO, A.TRAN_TYPE, A.PAY_ACCNO, C.ACC_NAME, C.OPENACC_DEPT, A.REC
V_ACCNO, A.RECV_ACC_NAME, A.RECV_OPENACC_DEPT, A.AMOUNT, A.USEOF, A.CREDIT_NO, A
.STATUS, A.OPER_NAME, TO_CHAR(A.MAK_DATE, 'YYYY-MM-DD HH24:MI:SS'),A.CHECK_NAME,
TO_CHAR(A.CHK_DATE, 'YYYY-MM-DD HH24:MI:SS'),A.ADMIN_NAME, TO_CHAR(A.APP_DATE,
11,524,114 107 107,702.0 4.4 103.30 123.25 ffsvcpfwfqcf1
SELECT A.CREDIT_NO, A.TRAN_TYPE, A.PAY_ACCNO, C.ACC_NAME, C.OPENACC_DEPT, A.REC
V_ACCNO, A.RECV_ACC_NAME, A.RECV_OPENACC_DEPT, A.AMOUNT, A.USEOF, A.CREDIT_NO, A
.STATUS, A.OPER_NAME, TO_CHAR(A.MAK_DATE, 'YYYY-MM-DD HH24:MI:SS'),A.CHECK_NAME,
TO_CHAR(A.CHK_DATE, 'YYYY-MM-DD HH24:MI:SS'),A.ADMIN_NAME, TO_CHAR(A.APP_DATE,
这是个典型的OLTP系统,4个SQL的单次执行逻辑读都达到了10万以上,显然如此之高的逻辑读是不合理的,在执行次数不多的情况下,其影响不大,一旦执行次数大幅增加,必然带来严重的性能问题。
(2)问题分析
取一条完整的SQL:
SELECT A.CREDIT_NO, A.TRAN_TYPE, A.PAY_ACCNO, C.ACC_NAME, C.OPENACC_DEPT, A.RECV_ACCNO,
A.RECV_ACC_NAME, A.RECV_OPENACC_DEPT, A.AMOUNT, A.USEOF, A.CREDIT_NO, A.STATUS, A.OPER_NAME,
TO_CHAR(A.MAK_DATE, 'YYYY-MM-DD HH24:MI:SS'),A.CHECK_NAME, TO_CHAR(A.CHK_DATE, 'YYYY-MM-DDHH24:MI:SS'),
A.ADMIN_NAME, TO_CHAR(A.APP_DATE, 'YYYY-MM-DD HH24:MI:SS'), A.MEMO1, A.MEMO2,
A.FOLLOWINFO, A.CANCEL_REASON, A.DEL_REASON, A.CUR_TYPE, 0,TO_CHAR(A.ACC_DATE, 'YYYY-MM-DDHH24:MI:SS'),
A.BALANCE,A.PAY_TYPE,A.TRANSFER_TYPE, A.FLAG,A.GENDAN FROM YINGSU_BARGAIN A, YINGSU_ACCOUNT C
WHERE A.STATUS IN ('0','1','2','3','4','5','6','7','8','9','A','B','C') AND A.CUST_ID =RPAD(:a1,21) AND
A.PAY_CUSTID = C.CUST_ID AND A.TRAN_TYPE IN('0','1','2','3','A','R','P','S','D','I','O','G','F','W')
and A.PAY_ACCNO = C.ACC_NO AND A.OPER_ID =RPAD(:a2,6) AND A.MAK_DATE between
to_DATE(:a3||'000000','YYYYMMDDHH24MISS') and to_DATE(:a4||'235959','YYYYMMDDHH24MISS') AND A.PAY_ACCNO
=RPAD(:a5,32) AND rownum < 5000 ORDER BY A.CREDIT_NO;
根据mak_date取值范围的不同,Oracle优化器会产生了2种不同的执行计划:
计划1:
---------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 470 | 10 (10)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | SORT ORDER BY | | 1 | 470 | 10 (10)| 00:00:01 |
|* 3 | COUNT STOPKEY | | | | | |
| 4 | NESTED LOOPS | | 1 | 470 | 9 (0)| 00:00:01 |
|* 5 | TABLE ACCESS BY INDEX ROWID| YINGSU_BARGAIN | 1 | 368 | 7 (0)| 00:00:01 |
|* 6 | INDEX RANGE SCAN | YINGSU_BARGAIN_OPERID | 4 | | 3 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID| YINGSU_ACCOUNT | 1 | 102 | 2 (0)| 00:00:01 |
|* 8 | INDEX UNIQUE SCAN | YINGSU_ACCOUNT_PK21026280981402 | 1 | | 1 (0)| 00:00:01 |
计划2:
---------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 9 (100)| |
| 1 | FILTER | | | | | |
| 2 | SORT ORDER BY | | 1 | 467 | 9 (12)| 00:00:01 |
| 3 | COUNT STOPKEY | | | | | |
| 4 | NESTED LOOPS | | 1 | 467 | 8 (0)| 00:00:01 |
| 5 | TABLE ACCESS BY INDEX ROWID| YINGSU_BARGAIN | 1 | 365 | 6 (0)| 00:00:01 |
| 6 | INDEX RANGE SCAN | YINGSU_BARGAIN_MAKEDATE | 3 | | 3 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID| YINGSU_ACCOUNT | 1 | 102 | 2 (0)| 00:00:01 |
| 8 | INDEX UNIQUE SCAN | YINGSU_ACCOUNT_PK21026280981402 | 1 | | 1 (0)| 00:00:01 |
从红色字体可以看出,这两种执行计划的不同之处在于选择了不同的索引,而优化器为什么会产生2种不同的选择,这取决于索引的选择率,而索引的选择率又是如何得到的呢?显然是Oracle优化器根据表及索引的统计信息计算得出的:
考虑到数据库的统计信息是在每周六晚上进行收集,以mak_date这一列为例,在20100227晚间进行了数据库统计信息的收集,这样,统计信息里就记录了mak_date这一列的最大值和最小值,比如最大值20100227 22:00:00 ,最小值为20020101 00:00:00,之后,当这条SQL再次被查询时,优化器会对这条SQL重新解析,产生新的执行计划,由于mak_date的值是采用绑定变量赋予的,在第一次解析这条SQL时,将对绑定变量值进行窥视,根据窥视到的值,产生一个合适的执行计划,这意味着第一次窥视到的绑定变量值决定了该SQL 的执行计划。
在mak_date的查询条件中,
AND A.MAK_DATE between to_DATE(:a3||'000000', 'YYYYMMDDHH24MISS') and to_DATE(:a4||'235959', 'YYYYMMDDHH24MISS')
绑定变量:a3和:a4取值有多种可能,为了说明问题,可以简化为2种可能,一种是位于20100227 22:00:00和20020101 00:00:00这两个边界之间,另一种就是位于这两个边界之外,这两种情况,就产生了上述两种不同的执行计划。 通过查看这两种情况下的10053trace文件,可以跟踪到优化器是如何根据不同的绑定变量窥视值来计算索引的选择率,进而根据索引的选择率,最终选择了走哪一个索引。
1. 绑定变量值位于2个边界之间
BIND#2
oacdty=96 mxl=32(08) mxlc=00 mal=00 scl=00 pre=00
oacflg=03 fl2=1000000 frm=01 csi=01 siz=0 off=64
kxsbbbfp=9fffffffbf3de838 bln=32 avl=08 flg=01
value="20100225"
Bind#3
oacdty=96 mxl=32(08) mxlc=00 mal=00 scl=00 pre=00
oacflg=03 fl2=1000000 frm=01 csi=01 siz=0 off=96
kxsbbbfp=9fffffffbf3de858 bln=32 avl=08 flg=01
value="20100226"
这种情况下,Oracle优化器计算得到索引YINGSU_BARGAIN_MAKEDATE的选择率:
Access Path: index (RangeScan)
Index: YINGSU_BARGAIN_MAKEDATE
resc_io: 139.00 resc_cpu: 1225738
ix_sel: 7.7741e-04 ix_sel_with_filters: 7.7741e-04
Cost: 139.46 Resp: 139.46 Degree: 1
经过与索引yingsu_bargain_operid对比,发现索引yingsu_bargain_makedate的成本较高,因而最后选择了走索引yingsu_bargain_operid
Access Path: index (AllEqRange)
Index: YINGSU_BARGAIN_OPERID
resc_io: 7.00 resc_cpu: 58198
ix_sel: 2.3398e-05 ix_sel_with_filters: 2.3398e-05
Cost: 7.02 Resp: 7.02 Degree: 1
Best:: AccessPath: IndexRange Index: YINGSU_BARGAIN_OPERID
Cost: 7.02 Degree: 1 Resp: 7.02 Card: 0.00 Bytes: 0
2. 绑定变量值位于边界之外
Bind#2
oacdty=96 mxl=32(08) mxlc=00 mal=00 scl=00 pre=00
oacflg=03 fl2=1000000 frm=01 csi=01 siz=0 off=64
kxsbbbfp=9fffffffbf3f1ea0 bln=32 avl=08 flg=01
value="20100303"
Bind#3
oacdty=96 mxl=32(08) mxlc=00 mal=00 scl=00 pre=00
oacflg=03 fl2=1000000 frm=01 csi=01 siz=0 off=96
kxsbbbfp=9fffffffbf3f1ec0 bln=32 avl=08 flg=01
value="20100304"
这种情况下,Oracle优化器错误的估计了索引yingsu_bargain_makedate的选择率:
Using prorated density: 1.5749e-05 of col #3 as selectivity of out-of-range value pred
Access Path: index (RangeScan)
Index: YINGSU_BARGAIN_MAKEDATE
resc_io: 6.00 resc_cpu: 47796
ix_sel: 1.5767e-05 ix_sel_with_filters: 1.5767e-05
Cost: 6.02 Resp: 6.02 Degree: 1
索引yingsu_bargain_makedate的选择率明显减小,而索引yingsu_bargain_operid的选择率没有发生变化:
Using prorated density: 7.3262e-05 of col #8 as selectivity of out-of-range value pred
Access Path: index (AllEqRange)
Index: YINGSU_BARGAIN_OPERID
resc_io: 7.00 resc_cpu: 58198
ix_sel: 2.3398e-05 ix_sel_with_filters: 2.3398e-05
Cost: 7.02 Resp: 7.02 Degree: 1
最后,优化器选择了走索引yingsu_bargain_makedate。
Best:: AccessPath: IndexRange Index: YINGSU_BARGAIN_MAKEDATE
Cost: 6.02 Degree: 1 Resp: 6.02 Card: 0.00 Bytes: 0
通过上述2种情况,可以发现,Oracle优化器会根据绑定变量窥视值以及统计信息提供的数据,来确定相应索引的选择率,对于在统计信息边界之内的绑定变量值,这种计算是接近事实的,而对于位于统计信息边界之外的绑定变量值,优化器给出了一个过低的selectivity,而这个过低的selectivity是无法反应真实的数据分布情况,这最终导致了cost计算错误,产生了不恰当的执行计划。
(3) 解决方案
在定位问题根源后,可以有以下解决方案:
1. 对性能高的执行计划创建SQL Profile,并绑定到SQL上,具体方法在后面有介绍
2. 删除索引yingsu_bargain_makedate,这样优化器就选择了正确索引
3. 修改SQL,加提示,强制使用效率较高的索引
3. 10053诊断案例之采样比例过低导致执行计划选择错误
某生产系统发现单个SQL耗时较高,占全库的30.9%,AWR里报告如下:
Elapsed CPU Elap per % Total
Time (s) Time (s) Executions Exec (s) DB Time SQL Id
---------- ---------- ------------ ---------- ------- -------------
11,089 504 31,166 0.4 30.9 acura616y0jnz
SELECT COUNT(*) FROM YINGSU_DEL_TIME a,YINGSU_BARGAIN b WHERE a.credit_no = b
.credit_no AND b.cust_id = RPAD(:1,21) AND a.INFO_TYPE = '0' AND b.st
atus = 'A' AND b.cancel_reason is not null AND a.OPER_BROWSE = '0' AND
b.oper_id = RPAD(:2,6) union all SELECT COUNT(*) FROM YINGSU_DEL_TIME a,BB_L
调查发现周六表统计信息收集后该SQL执行计划发生变化
SNAP_ID E_TIME PLAN_HASH_VALUE BUFFER_GETS_DELTA DISK_READS_DELTA EXECUTIONS_DELTA OPTIMIZER_COST
---------- ---------------- --------------- ----------------- ---------------- ---------------- --------------=
23750 2010-10-23 23:00 3114794725 7 1 1 136
23751 2010-10-23 23:30 506460792 2330 2022 33 144
好的执行计划选择了yingsu_bargain_his表的yingsu_bargain_his_cust_stat索引
Plan hash value: 3114794725
-------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 57 (100)| | | |
| 1 | UNION-ALL | | | | | | | |
| 2 | SORT AGGREGATE | | 1 | 62 | | | | |
| 3 | NESTED LOOPS | | 1 | 62 | 9 (0)| 00:00:01 | | |
| 4 | TABLE ACCESS BY INDEX ROWID | YINGSU_BARGAIN | 1 | 45 | 7 (0)| 00:00:01 | | |
| 5 | INDEX RANGE SCAN | YINGSU_BARGAIN_STATUS | 4 | | 3 (0)| 00:00:01 | | |
| 6 | TABLE ACCESS BY INDEX ROWID | YINGSU_DEL_TIME | 1 | 17 | 2 (0)| 00:00:01 | | |
| 7 | INDEX UNIQUE SCAN | IDX_YINGSU_DEL_TIME | 1 | | 1 (0)| 00:00:01 | | |
| 8 | SORT AGGREGATE | | 1 | 63 | | | | |
| 9 | NESTED LOOPS | | 1 | 63 | 48 (0)| 00:00:01 | | |
| 10 | TABLE ACCESS BY GLOBAL INDEX ROWID| YINGSU_BARGAIN_HIS | 1 | 46 | 46 (0)| 00:00:01 | ROW L | ROW L |
| 11 | INDEX RANGE SCAN | YINGSU_BARGAIN_HIS_CUST_STAT | 49 | | 4 (0)| 00:00:01 | | |
| 12 | TABLE ACCESS BY INDEX ROWID | YINGSU_DEL_TIME | 1 | 17 | 2 (0)| 00:00:01 | | |
| 13 | INDEX UNIQUE SCAN | IDX_YINGSU_DEL_TIME | 1 | | 1 (0)| 00:00:01 | | |
-------------------------------------------------------------------------------------------------------------------------------
该执行计划运行时逻辑读和物理读都较低
SNAP_ID E_TIME PLAN_HASH_VALUE BUFFER_GETS_DELTA DISK_READS_DELTA EXECUTIONS_DELTA
---------- ---------------- --------------- ----------------- ---------------- ----------------
23671 2014-10-22 07:30 3114794725 2513 660 254
23672 2014-10-22 08:00 3114794725 23101 6796 1374
23673 2014-10-22 08:30 3114794725 99472 29480 7131
23674 2014-10-22 09:00 3114794725 172454 46467 12888
23675 2014-10-22 09:30 3114794725 188126 55096 15037
23676 2014-10-22 10:01 3114794725 173177 51324 13805
23677 2014-10-22 10:30 3114794725 152507 46270 12515
23678 2014-10-22 11:00 3114794725 150677 47006 12501
23679 2014-10-22 11:30 3114794725 141880 40961 11454
23680 2014-10-22 12:00 3114794725 94010 27581 8142
23681 2014-10-22 12:30 3114794725 40787 11399 3854
23682 2014-10-22 13:00 3114794725 43900 11782 4102
差的执行计划选择了yingsu_bargain_his表的yingsu_bargain_his_custmak索引
Plan hash value: 506460792
-------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop
-------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 176 (100)| | | |
| 1 | UNION-ALL | | | | | | | |
| 2 | SORT AGGREGATE | | 1 | 63 | | | | |
| 3 | NESTED LOOPS | | 1 | 63 | 9 (0)| 00:00:01 | | |
| 4 | TABLE ACCESS BY INDEX ROWID | YINGSU_BARGAIN | 1 | 46 | 8 (0)| 00:00:01 | | |
| 5 | INDEX RANGE SCAN | YINGSU_BARGAIN_STATUS | 6 | | 3 (0)| 00:00:01 | | |
| 6 | TABLE ACCESS BY INDEX ROWID | YINGSU_DEL_TIME | 1 | 17 | 1 (0)| 00:00:01 | | |
| 7 | INDEX UNIQUE SCAN | IDX_YINGSU_DEL_TIME | 1 | | 0 (0)| | | |
| 8 | SORT AGGREGATE | | 1 | 63 | | | | |
| 9 | NESTED LOOPS | | 1 | 63 | 167 (1)| 00:00:03 | | |
| 10 | TABLE ACCESS BY GLOBAL INDEX ROWID| YINGSU_BARGAIN_HIS | 1 | 46 | 166 (1)| 00:00:02 | ROW L | ROW L |
| 11 | INDEX RANGE SCAN | YINGSU_BARGAIN_HIS_CUSTMAK | 191 | | 6 (0)| 00:00:01 | | |
| 12 | TABLE ACCESS BY INDEX ROWID | YINGSU_DEL_TIME | 1 | 17 | 1 (0)| 00:00:01 | | |
| 13 | INDEX UNIQUE SCAN | IDX_YINGSU_DEL_TIME | 1 | | 0 (0)| | | |
-------------------------------------------------------------------------------------------------------------------------------
该执行计划运行时逻辑读和物理读都较高
SNAP_ID E_TIME PLAN_HASH_VALUE BUFFER_GETS_DELTA DISK_READS_DELTA EXECUTIONS_DELTA
---------- ---------------- --------------- ----------------- ---------------- ----------------
23809 2010-10-25 04:30 506460792 25 13 2
23810 2010-10-25 05:00 506460792 84 69 1
23811 2010-10-25 05:30 506460792 9 2 1
23812 2010-10-25 06:00 506460792 270 183 7
23813 2010-10-25 06:30 506460792 1103 927 12
23814 2010-10-25 07:01 506460792 5445 4443 54
23815 2010-10-25 07:30 506460792 56972 49209 191
23816 2010-10-25 08:00 506460792 411418 269546 1186
23817 2010-10-25 08:30 506460792 2848607 1075016 7033
23818 2010-10-25 09:00 506460792 5189883 2192857 14172
23819 2010-10-25 09:30 506460792 5196879 2703510 16994
23820 2010-10-25 10:00 506460792 4788809 2344351 15721
23821 2010-10-25 10:30 506460792 4008804 2247444 14569
23822 2010-10-25 11:00 506460792 3513755 1980171 13517
23823 2010-10-25 11:30 506460792 3326510 1930302 12831
索引情况如下:
sys@B2B>select index_name,column_position,column_name from dba_ind_columns where index_name in ('YINGSU_BARGAIN_HIS_CUST_STAT','YINGSU_BARGAIN_HIS_CUSTMAK') and table_owner='B2C20' order by 1,2;
INDEX_NAME COLUMN_POSITION COLUMN_NAME
------------------------------ --------------- ----------------------------------------
YINGSU_BARGAIN_HIS_CUSTMAK 1 CUST_ID
YINGSU_BARGAIN_HIS_CUSTMAK 2 MAK_DATE
YINGSU_BARGAIN_HIS_CUST_STAT 1 CUST_ID
YINGSU_BARGAIN_HIS_CUST_STAT 2 STATUS
进一步分析索引相关统计信息,对于索引YINGSU_BARGAIN_HIS_CUST_STAT,发现Oracle收集的统计信息偏差较大,索引YINGSU_BARGAIN_HIS_CUST_STAT包含了2列CUST_ID和STATUS,查询这两列的统计值:
sys@B2B>select table_name,column_name,num_distinct,density ,num_nulls from dba_tab_columns where column_name in('CUST_ID','STATUS') and table_name='YINGSU_BARGAIN_HIS';
TABLE_NAME COLUMN_NAME NUM_DISTINCT DENSITY NUM_NULLS
------------------------------ ---------------------------------------- ------------ ---------- ----------
YINGSU_BARGAIN_HIS CUST_ID 166607 6.0021E-06 0
YINGSU_BARGAIN_HIS STATUS 5 .2 0
再查询该索引的统计值:
sys@B2B>select table_name,index_name,blevel,num_rows,leaf_blocks,distinct_keys,clustering_factor from dba_indexes where table_name='YINGSU_BARGAIN_HIS' and index_name='YINGSU_BARGAIN_HIS_CUST_STAT';
TABLE_NAME INDEX_NAME BLEVEL NUM_ROWS LEAF_BLOCKS DISTINCT_KEYS CLUSTERING_FACTOR
------------------------------ ------------------------------ ---------- ---------- ----------- ------------- -----------------
YINGSU_BARGAIN_HIS YINGSU_BARGAIN_HIS_CUST_STAT&a
图文推荐
序言
2020-04-19 查看:2270
第十五章:Oracle 12c介绍
2020-04-19 查看:2207
第十四章:常用Oracle工具
2020-04-19 查看:1934
第十三章:Oracle Golde...
2020-04-19 查看:2199
第十二章:DataGuard
2020-04-19 查看:1796