Oracle 10g的隐含参数_complex_view_merging引发的性能问题
今天在Oracle 10g上碰到一个奇怪的问题,有一条sql在数据库1上很快,在数据库2上很慢,数据库2的数据是从数据库1上导的,数据量差不多。
在数据库1上执行0.01s。
SQL> SELECT A.*,
2 B.INCREASE_ID,
3 B.TRANSACTION_ID,
4 B.LINK_CARD_ID,
5 B.VALIDATE_FLAG,
6 B.ASSET_VALUE_SHARING,
7 B.RELATED_DEVICE_ID,
8 B.PARENT_CARD_CODE,
9 B.PROJECT_VALUE,
10 B.DELETE_FLAG,
11 B.DEPRECIATION_ADJUST_VALUE,
12 T.TRANSACTION_MODE_CODE,
13 T.TRANSACTION_NO,
14 T.TRANSACTION_FROM,
15 T.FROM_MODEL,
16 (SELECT T.FULL_PATH
17 FROM AM_TECH_OBJECT_NODE_0900 T
18 WHERE T.TECH_OBJECT_ID = A.DEVICE_ID
19 AND T.NODE_TYPE = 2
20 AND ROWNUM = 1) AS FULL_PATH,
21 AAC.FULL_NAME CLASSIFY_FULL_PATH
22 FROM V_ASSET_CARD_0900 A,
23 GG_ASSET_INCREASE_ITEM B,
24 GG_ASSET_TRANSACTION T,
25 AM_ASSET_CLASSIFY AAC
26 WHERE A.CARD_ID = B.CARD_ID
27 AND B.TRANSACTION_ID = T.TRANSACTION_ID
28 AND A.CLASSIFY_ID = AAC.DEVICE_CLASSIFY_ID(+)
29 AND B.TRANSACTION_ID = '0101109514';
已用时间: 00: 00: 00.01
执行计划
----------------------------------------------------------
Plan hash value: 3643758043
-------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 21 | 24129 | 167 (0)| 00:00:03 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID | AM_TECH_OBJECT_NODE_0900 | 1 | 73 | 4 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | IDX_TECH_NODE_ID_0900 | 1 | | 3 (0)| 00:00:01 |
| 4 | NESTED LOOPS OUTER | | 21 | 24129 | 167 (0)| 00:00:03 |
| 5 | NESTED LOOPS | | 21 | 22533 | 146 (0)| 00:00:02 |
| 6 | NESTED LOOPS | | 20 | 12700 | 106 (0)| 00:00:02 |
| 7 | NESTED LOOPS | | 20 | 10900 | 46 (0)| 00:00:01 |
| 8 | NESTED LOOPS | | 20 | 2000 | 6 (0)| 00:00:01 |
| 9 | TABLE ACCESS BY INDEX ROWID| GG_ASSET_TRANSACTION | 1 | 42 | 2 (0)| 00:00:01 |
|* 10 | INDEX UNIQUE SCAN | PK_GG_ASSET_TRANSACTION | 1 | | 1 (0)| 00:00:01 |
| 11 | TABLE ACCESS BY INDEX ROWID| GG_ASSET_INCREASE_ITEM | 20 | 1160 | 4 (0)| 00:00:01 |
|* 12 | INDEX RANGE SCAN | TRANSACTION_DETAIL_REF_TRANSAC | 20 | | 1 (0)| 00:00:01 |
| 13 | TABLE ACCESS BY INDEX ROWID | GG_ASSET_CARD_0900 | 1 | 445 | 2 (0)| 00:00:01 |
|* 14 | INDEX UNIQUE SCAN | PK_GG_ASSET_CARD_0303 | 1 | | 1 (0)| 00:00:01 |
| 15 | TABLE ACCESS BY INDEX ROWID | GG_ASSET_VALUE_0900 | 1 | 90 | 3 (0)| 00:00:01 |
|* 16 | INDEX RANGE SCAN | ID_FAV_CARD_VALIDITY_0303 | 1 | | 2 (0)| 00:00:01 |
| 17 | TABLE ACCESS BY INDEX ROWID | AM_ASSET_0900 | 1 | 438 | 2 (0)| 00:00:01 |
|* 18 | INDEX UNIQUE SCAN | PK_AM_ASSET_0900 | 1 | | 1 (0)| 00:00:01 |
| 19 | TABLE ACCESS BY INDEX ROWID | AM_ASSET_CLASSIFY | 1 | 76 | 1 (0)| 00:00:01 |
|* 20 | INDEX UNIQUE SCAN | PK_AM_ASSET_CLASSIFY | 1 | | 0 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM=1)
3 - access("T"."TECH_OBJECT_ID"=:B1 AND "T"."NODE_TYPE"=2)
10 - access("T"."TRANSACTION_ID"='0101109514')
12 - access("B"."TRANSACTION_ID"='0101109514')
14 - access("GG_ASSET_CARD"."CARD_ID"="B"."CARD_ID")
16 - access("GG_ASSET_VALUE"."CARD_ID"="GG_ASSET_CARD"."CARD_ID" AND
"GG_ASSET_VALUE"."VALIDITY_DATE_END"="GG_ASSET_CARD"."DECREASE_DATE")
18 - access("AM_ASSET"."DEVICE_ID"="GG_ASSET_CARD"."DEVICE_ID")
20 - access("AM_ASSET"."CLASSIFY_ID"="AAC"."DEVICE_CLASSIFY_ID"(+))
统计信息
----------------------------------------------------------
8 recursive calls
0 db block gets
28 consistent gets
0 physical reads
0 redo size
12384 bytes sent via SQL*Net to client
338 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
在数据库2上很慢,27.48s
SQL> SELECT A.*,
2 B.INCREASE_ID,
3 B.TRANSACTION_ID,
4 B.LINK_CARD_ID,
5 B.VALIDATE_FLAG,
6 B.ASSET_VALUE_SHARING,
7 B.RELATED_DEVICE_ID,
8 B.PARENT_CARD_CODE,
9 B.PROJECT_VALUE,
10 B.DELETE_FLAG,
11 B.DEPRECIATION_ADJUST_VALUE,
12 T.TRANSACTION_MODE_CODE,
13 T.TRANSACTION_NO,
14 T.TRANSACTION_FROM,
15 T.FROM_MODEL,
16 (SELECT T.FULL_PATH
17 FROM AM_TECH_OBJECT_NODE_0900 T
18 WHERE T.TECH_OBJECT_ID = A.DEVICE_ID
19 AND T.NODE_TYPE = 2
20 AND ROWNUM = 1) AS FULL_PATH,
21 AAC.FULL_NAME CLASSIFY_FULL_PATH
22 FROM V_ASSET_CARD_0900 A,
23 GG_ASSET_INCREASE_ITEM B,
24 GG_ASSET_TRANSACTION T,
25 AM_ASSET_CLASSIFY AAC
26 WHERE A.CARD_ID = B.CARD_ID
27 AND B.TRANSACTION_ID = T.TRANSACTION_ID
28 AND A.CLASSIFY_ID = AAC.DEVICE_CLASSIFY_ID(+)
29 AND B.TRANSACTION_ID = '0101109514';
已选择200行。
已用时间: 00: 00: 27.48
执行计划
----------------------------------------------------------
Plan hash value: 2944357796
-------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 25 | 255K| | 45815 (1)| 00:09:10 |
|* 1 | COUNT STOPKEY | | | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID | AM_TECH_OBJECT_NODE_0900 | 1 | 75 | | 4 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | IDX_TECH_NODE_ID_0900 | 1 | | | 3 (0)| 00:00:01 |
| 4 | NESTED LOOPS OUTER | | 25 | 255K| | 45815 (1)| 00:09:10 |
|* 5 | HASH JOIN | | 25 | 253K| | 45790 (1)| 00:09:10 |
| 6 | NESTED LOOPS | | 25 | 2750 | | 6 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID| GG_ASSET_TRANSACTION | 1 | 53 | | 2 (0)| 00:00:01 |
|* 8 | INDEX UNIQUE SCAN | PK_GG_ASSET_TRANSACTION | 1 | | | 1 (0)| 00:00:01 |
| 9 | TABLE ACCESS BY INDEX ROWID| GG_ASSET_INCREASE_ITEM | 25 | 1425 | | 4 (0)| 00:00:01 |
|* 10 | INDEX RANGE SCAN | TRANSACTION_DETAIL_REF_TRANSAC | 25 | | | 1 (0)| 00:00:01 |
| 11 | VIEW | V_ASSET_CARD_0900 | 280K| 2744M| | 45781 (1)| 00:09:10 |
|* 12 | HASH JOIN | | 280K| 257M| 141M| 45781 (1)| 00:09:10 |
|* 13 | HASH JOIN | | 274K| 137M| 27M| 12222 (1)| 00:02:27 |
| 14 | TABLE ACCESS FULL | GG_ASSET_VALUE_0900 | 292K| 24M| | 910 (2)| 00:00:11 |
| 15 | TABLE ACCESS FULL | GG_ASSET_CARD_0900 | 274K| 114M| | 4073 (1)| 00:00:49 |
| 16 | TABLE ACCESS FULL | AM_ASSET_0900 | 756K| 315M| | 10464 (1)| 00:02:06 |
| 17 | TABLE ACCESS BY INDEX ROWID | AM_ASSET_CLASSIFY | 1 | 76 | | 1 (0)| 00:00:01 |
|* 18 | INDEX UNIQUE SCAN | PK_AM_ASSET_CLASSIFY | 1 | | | 0 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM=1)
3 - access("T"."TECH_OBJECT_ID"=:B1 AND "T"."NODE_TYPE"=2)
5 - access("A"."CARD_ID"="B"."CARD_ID")
8 - access("T"."TRANSACTION_ID"='0101109514')
10 - access("B"."TRANSACTION_ID"='0101109514')
12 - access("AM_ASSET"."DEVICE_ID"="GG_ASSET_CARD"."DEVICE_ID")
13 - access("GG_ASSET_VALUE"."CARD_ID"="GG_ASSET_CARD"."CARD_ID" AND
"GG_ASSET_VALUE"."VALIDITY_DATE_END"="GG_ASSET_CARD"."DECREASE_DATE")
18 - access("A"."CLASSIFY_ID"="AAC"."DEVICE_CLASSIFY_ID"(+))
统计信息
----------------------------------------------------------
218 recursive calls
0 db block gets
70112 consistent gets
26412 physical reads
348 redo size
38174 bytes sent via SQL*Net to client
480 bytes received via SQL*Net from client
15 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
200 rows processed
第一次诊断:起初觉得应该是索引的集群因子的问题,检查了下,差不多。
第二次诊断:感觉是环境、参数不一样引起,开始试验。
使用视图v$sql和v$sql_plan、dbms_xplan.display_cursor查出sql真实的执行计划。
select distinct s.SQL_ID, s.HASH_VALUE, s.CHILD_NUMBER, s.SQL_TEXT
from v$sql s, v$sql_plan p
where s.SQL_ID = p.SQL_ID
and p.PLAN_HASH_VALUE = '3643758043';
select * from table(dbms_xplan.display_cursor(150270666, 0, 'advanced'));
性能慢的数据库:
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('10.2.0.4')
OPT_PARAM('_complex_view_merging' 'false')
ALL_ROWS
............省略............
*/
性能快的数据库:
/*+
BEGIN_OUTLINE_DATA
IGNORE_OPTIM_EMBEDDED_HINTS
OPTIMIZER_FEATURES_ENABLE('10.2.0.4')
ALL_ROWS
............省略............
*/
看到两个执行的大纲有点不同,于是到两个数据库中查这个_complex_view_merging这个隐含参数,性能慢的数据库设置为false,性能快的数据库的设置则为true。
SQL语句中是有视图的,莫非这个隐含参数有问题,按字面的意思是复杂视图的合并,抱着试一试的心情调整了下这个参数:
alter session set "_complex_view_merging" = true;
结果非常快,0.6s。
SQL> SELECT A.*,
2 B.INCREASE_ID,
3 B.TRANSACTION_ID,
4 B.LINK_CARD_ID,
5 B.VALIDATE_FLAG,
6 B.ASSET_VALUE_SHARING,
7 B.RELATED_DEVICE_ID,
8 B.PARENT_CARD_CODE,
9 B.PROJECT_VALUE,
10 B.DELETE_FLAG,
11 B.DEPRECIATION_ADJUST_VALUE,
12 T.TRANSACTION_MODE_CODE,
13 T.TRANSACTION_NO,
14 T.TRANSACTION_FROM,
15 T.FROM_MODEL,
16 (SELECT T.FULL_PATH
17 FROM sz_1230.AM_TECH_OBJECT_NODE_0900 T
18 WHERE T.TECH_OBJECT_ID = A.DEVICE_ID
19 AND T.NODE_TYPE = 2
20 AND ROWNUM = 1) AS FULL_PATH,
21 AAC.FULL_NAME CLASSIFY_FULL_PATH
22 FROM sz_1230.V_ASSET_CARD_0900 A,
23 sz_1230.FM_ASSET_INCREASE_ITEM B,
24 sz_1230.FM_ASSET_TRANSACTION T,
25 sz_1230.AM_ASSET_CLASSIFY AAC
26 WHERE A.CARD_ID = B.CARD_ID
27 AND B.TRANSACTION_ID = T.TRANSACTION_ID
28 AND A.CLASSIFY_ID = AAC.DEVICE_CLASSIFY_ID(+)
29 AND B.TRANSACTION_ID = '0101109514';
已选择200行。
已用时间: 00: 00: 00.06
执行计划
----------------------------------------------------------
Plan hash value: 801438153
-------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 25 | 28475 | 206 (0)| 00:00:03 |
|* 1 | COUNT STOPKEY | | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID | AM_TECH_OBJECT_NODE_0900 | 1 | 75 | 4 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | IDX_TECH_NODE_ID_0900 | 1 | | 3 (0)| 00:00:01 |
| 4 | NESTED LOOPS | | 25 | 28475 | 206 (0)| 00:00:03 |
| 5 | NESTED LOOPS OUTER | | 25 | 26275 | 131 (0)| 00:00:02 |
| 6 | NESTED LOOPS | | 25 | 24375 | 106 (0)| 00:00:02 |
| 7 | NESTED LOOPS | | 25 | 13425 | 56 (0)| 00:00:01 |
| 8 | NESTED LOOPS | | 25 | 2475 | 6 (0)| 00:00:01 |
| 9 | TABLE ACCESS BY INDEX ROWID| FM_ASSET_TRANSACTION | 1 | 42 | 2 (0)| 00:00:01 |
|* 10 | INDEX UNIQUE SCAN | PK_FM_ASSET_TRANSACTION | 1 | | 1 (0)| 00:00:01 |
| 11 | TABLE ACCESS BY INDEX ROWID| FM_ASSET_INCREASE_ITEM | 25 | 1425 | 4 (0)| 00:00:01 |
|* 12 | INDEX RANGE SCAN | TRANSACTION_DETAIL_REF_TRANSAC | 25 | | 1 (0)| 00:00:01 |
| 13 | TABLE ACCESS BY INDEX ROWID | FM_ASSET_CARD_0900 | 1 | 438 | 2 (0)| 00:00:01 |
|* 14 | INDEX UNIQUE SCAN | PK_FM_ASSET_CARD_0303 | 1 | | 1 (0)| 00:00:01 |
| 15 | TABLE ACCESS BY INDEX ROWID | AM_ASSET_0900 | 1 | 438 | 2 (0)| 00:00:01 |
|* 16 | INDEX UNIQUE SCAN | PK_AM_ASSET_0900 | 1 | | 1 (0)| 00:00:01 |
| 17 | TABLE ACCESS BY INDEX ROWID | AM_ASSET_CLASSIFY | 1 | 76 | 1 (0)| 00:00:01 |
|* 18 | INDEX UNIQUE SCAN | PK_AM_ASSET_CLASSIFY | 1 | | 0 (0)| 00:00:01 |
| 19 | TABLE ACCESS BY INDEX ROWID | FM_ASSET_VALUE_0900 | 1 | 88 | 3 (0)| 00:00:01 |
|* 20 | INDEX RANGE SCAN | ID_FAV_CARD_VALIDITY_0303 | 1 | | 2 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(ROWNUM=1)
3 - access("T"."TECH_OBJECT_ID"=:B1 AND "T"."NODE_TYPE"=2)
10 - access("T"."TRANSACTION_ID"='0101109514')
12 - access("B"."TRANSACTION_ID"='0101109514')
14 - access("FM_ASSET_CARD"."CARD_ID"="B"."CARD_ID")
16 - access("AM_ASSET"."DEVICE_ID"="FM_ASSET_CARD"."DEVICE_ID")
18 - access("AM_ASSET"."CLASSIFY_ID"="AAC"."DEVICE_CLASSIFY_ID"(+))
20 - access("FM_ASSET_VALUE"."CARD_ID"="FM_ASSET_CARD"."CARD_ID" AND
"FM_ASSET_VALUE"."VALIDITY_DATE_END"="FM_ASSET_CARD"."DECREASE_DATE")
统计信息
----------------------------------------------------------
0 recursive calls
0 db block gets
3029 consistent gets
0 physical reads
0 redo size
38039 bytes sent via SQL*Net to client
480 bytes received via SQL*Net from client
15 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
200 rows processed
于是将_complex_view_merging全局设置为true, alter system set "_complex_view_merging" = true scope=both;
再看了下其他的oracle 10g的数据库设置都是为true,应该是安装数据库的问题。