최적화 사례 4 - 잘못된 큰 시계 HASH + 병행 --- > 올 바른 Nested loop
한 친구 가 저 를 찾 아와 서 SQL 을 최적화 시 켰 어 요. 논리 적 으로 103 만 개, 물리 적 으로 103 만 개 를 읽 고 19 초 를 뛰 어야 완 주 할 수 있다.
다음은 SQL 및 실행 계획 입 니 다.
SELECT "A1"."SERV_ID"
,"A1"."ATTR_ID"
,"A1"."ATTR_VAL"
,"A1"."EFF_DATE"
,NVL("A1"."EXP_DATE", TO_DATE(NULL, NULL))
,"A2"."OP_SEQ"
,"A2"."OP_TYPE"
FROM COMM."USER_INFO_OPLOG_MASTER2" "A2"
,COMM."SERV_ATTR" "A1"
WHERE "A2"."MEMOP_DATE" IS NULL
AND "A2"."TABLE_NAME" = 'SERV_ATTR'
AND "A1"."SERV_ID" = "A2"."TABLE_COLUMN_1"
AND "A1"."AGREEMENT_ID" = "A2"."TABLE_COLUMN_2"
AND "A1"."ATTR_ID" = "A2"."TABLE_COLUMN_3"
ORDER BY "A2"."OP_SEQ"
563 rows selected.
Elapsed: 00:00:19.50
Execution Plan
----------------------------------------------------------
Plan hash value: 669020553
---------------------------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 150K| 17M| | 61528 (3)| 00:12:19 | | | |
| 1 | PX COORDINATOR | | | | | | | | | |
| 2 | PX SEND QC (ORDER) | :TQ10002 | 150K| 17M| | 61528 (3)| 00:12:19 | Q1,02 | P->S | QC (ORDER) |
| 3 | SORT ORDER BY | | 150K| 17M| 20M| 61528 (3)| 00:12:19 | Q1,02 | PCWP | |
| 4 | PX RECEIVE | | 150K| 17M| | 61526 (3)| 00:12:19 | Q1,02 | PCWP | |
| 5 | PX SEND RANGE | :TQ10001 | 150K| 17M| | 61526 (3)| 00:12:19 | Q1,01 | P->P | RANGE |
|* 6 | HASH JOIN | | 150K| 17M| | 61526 (3)| 00:12:19 | Q1,01 | PCWP | |
| 7 | BUFFER SORT | | | | | | | Q1,01 | PCWC | |
| 8 | PX RECEIVE | | 147K| 11M| | 1069 (1)| 00:00:13 | Q1,01 | PCWP | |
| 9 | PX SEND BROADCAST | :TQ10000 | 147K| 11M| | 1069 (1)| 00:00:13 | | S->P | BROADCAST |
| 10 | TABLE ACCESS BY INDEX ROWID| USER_INFO_OPLOG_MASTER2 | 147K| 11M| | 1069 (1)| 00:00:13 | | | |
|* 11 | INDEX RANGE SCAN | IDX_INFO_OPLOG_M2COMB_11502 | 6113 | | | 33 (0)| 00:00:01 | | | |
| 12 | PX BLOCK ITERATOR | | 229M| 9427M| | 60101 (2)| 00:12:02 | Q1,01 | PCWC | |
|* 13 | TABLE ACCESS FULL | SERV_ATTR | 229M| 9427M| | 60101 (2)| 00:12:02 | Q1,01 | PCWP | |
---------------------------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
6 - access("A1"."SERV_ID"="A2"."TABLE_COLUMN_1" AND "A1"."AGREEMENT_ID"="A2"."TABLE_COLUMN_2" AND "A1"."ATTR_ID"="A2"."TABLE_COLUMN_3")
11 - access("A2"."MEMOP_DATE" IS NULL AND "A2"."TABLE_NAME"='SERV_ATTR')
filter("A2"."TABLE_NAME"='SERV_ATTR')
13 - filter(SYS_OP_BLOOM_FILTER(:BF0000,"A1"."SERV_ID","A1"."AGREEMENT_ID","A1"."ATTR_ID"))
Note
-----
- dynamic sampling used for this statement (level=6)
Statistics
----------------------------------------------------------
30 recursive calls
0 db block gets
1039308 consistent gets
1003269 physical reads
716 redo size
31187 bytes sent via SQL*Net to client
927 bytes received via SQL*Net from client
39 SQL*Net roundtrips to/from client
11 sorts (memory)
0 sorts (disk)
563 rows processed
실행 계획 을 보면 대략 세 가지 문제 가 있다.
< 1 > 원래 SQL 은 hint paraller 알림 으로 병행 하지 않 았 지만 실제 실행 계획 을 보면 병행 을 했 습 니 다. 이 두 표 에 기본 병행 도 를 설정 한 것 같 습 니 다.일반적으로 데이터 창고 에서 이렇게 할 수 있 지만 이 친구 에 게 물 어 보 았 다. 그들의 데이터 베이스 시스템 은 OLTP 와 OLAP 혼합 시스템 이기 때문에 표 에 높 은 병행 도 를 설정 하 는 것 을 권장 하지 않 는 다. 그러면 CBO 는 병행 + 전체 표 스 캔 을 선택 하 는 경향 이 더욱 강 할 것 이다.
<2 > ID = 13 의 술어 정 보 는 "(SYS OP BLOOM FILTER: BF 0000," A1 "," SERV ID "," A1 "," AGREEMENT ID "," A1 "," ATTR ID ")" 이 있 습 니 다. 10g R2 이후 CBO 유 틸 리 티 알고리즘 은 부 릉 필터 링 알고리즘 을 추 가 했 습 니 다. 보통 두 표 에서 HASH JOIN + 를 병행 할 때 HASH JOIN 의 피 구동 표 에 나타 나 지만 제 가 SQL 을 최적화 한 경험 을 보면이 새로운 기능 은 BUG 가 많 습 니 다. 특히 드라이버 의 데이터 양 이 매우 많 을 때 이 알고리즘 을 사용 하 는 것 이 더 큰 영향 을 미 칠 수 있 으 므 로 데이터 시스템 에서 이 매개 변 수 를 disable 로 해결 하 는 것 을 권장 합 니 다.
<3> 이 SQL 이 최종 적 으로 돌아 온 결 과 는 563 줄 에 불과 하 다 는 것 을 알 수 있 습 니 다. 이 를 통 해 Nested loop 내장 순환 을 가 는 것 이 HASH 가 있 는 것 보다 효율 적 일 것 으로 추 정 됩 니 다.
다음은 다음 SQL 을 통 해 제 판단 을 입증 하 겠 습 니 다.
A2 ------USER_INFO_OPLOG_MASTER2 이 표 의 총 데 이 터 량 은 67 만 개 이다.
A1-------SERV_ATTR 이 표 의 총 데 이 터 량 은 2 억 여 개 이다.
SQL 실행:
select count(*) from COMM.USER_INFO_OPLOG_MASTER2 where MEMOP_DATE is null and TABLE_NAME='SERV_ATTR';
결 과 는:
COUNT(*) ---------- 53677
A2 이 시 계 는 걸 러 낸 후 5 만 여 개 만 되 돌려 줍 니 다.
A1 표 의 색인 정 보 를 살 펴 보 겠 습 니 다.
****************************************************************************************
INDEX INFO
****************************************************************************************
TABLE TABLE Index COLUMN Col
OWNER NAME Name Unique NAME Pos DESC
--------------- ----------------------------------- ------------------------------ --------- ------------------------- ---- ----
COMM SERV_ATTR IDX_SERV_ATTR_AGREEMENT_ID NONUNIQUE AGREEMENT_ID 1 ASC
IDX_SERV_ATTR_ATTR_ID NONUNIQUE ATTR_ID 1 ASC
IDX_SERV_ATTR_INTERNET NONUNIQUE ATTR_VAL 1 ASC
ATTR_ID 2 ASC
IDX_SERV_ATTR_SERV_ID NONUNIQUE SERV_ID 1 ASC
IDX_SERV_ATTR_VAL8 NONUNIQUE ATTR_VAL 1 ASC
PK_SERV_ATTR UNIQUE SERV_ID 1 ASC
AGREEMENT_ID 2 ASC
ATTR_ID 3 ASC
A1 표 에 연합 키 가 세 워 져 있 습 니 다: SERVID AGREEMENT_ID ATTR_ID 이 세 열 을 보면 SQL 이라는 세 열 이 바로 A1 과 A2 의 연결 열 입 니 다. 그러면 잘 되 겠 습 니 다. 저 는 A2 에 게 순환 하 는 구동 표를 만 들 라 고 했 습 니 다. A1 은 피 구동 표를 만 들 었 습 니 다. 그러면 A1 은 반드시 메 인 키 PK 를 통 해 가 야 합 니 다.SERV_ATTR 은 색인 을 유일 하 게 스 캔 한 후에 다시 표 시 를 하면 성능 이 그리 낮 지 않 을 것 이다.
다음 HINT 를 넣 고 set autotrace traceonly 로 가라 고 했 어 요. 실행 계획 과 논리 읽 기:
/*+ use_nl(A1,A2) index(A1,PK_SERV_ATTR) leading(A2) */
Elapsed: 00:00:05.45
Execution Plan
----------------------------------------------------------
Plan hash value: 4263321111
----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 142K| 16M| | 286K (1)| 00:57:13 |
| 1 | SORT ORDER BY | | 142K| 16M| 19M| 286K (1)| 00:57:13 |
| 2 | NESTED LOOPS | | 142K| 16M| | 282K (1)| 00:56:26 |
| 3 | NESTED LOOPS | | 142K| 16M| | 282K (1)| 00:56:26 |
| 4 | TABLE ACCESS BY INDEX ROWID| USER_INFO_OPLOG_MASTER2 | 140K| 10M| | 1489 (1)| 00:00:18 |
|* 5 | INDEX RANGE SCAN | IDX_INFO_OPLOG_M2COMB_11502 | 9438 | | | 49 (0)| 00:00:01 |
|* 6 | INDEX UNIQUE SCAN | PK_SERV_ATTR | 1 | | | 2 (0)| 00:00:01 |
| 7 | TABLE ACCESS BY INDEX ROWID | SERV_ATTR | 1 | 43 | | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("A2"."TABLE_NAME"='SERV_ATTR' AND "A2"."MEMOP_DATE" IS NULL)
6 - access("A1"."SERV_ID"="A2"."TABLE_COLUMN_1" AND "A1"."AGREEMENT_ID"="A2"."TABLE_COLUMN_2" AND
"A1"."ATTR_ID"="A2"."TABLE_COLUMN_3")
Note
-----
- dynamic sampling used for this statement (level=6)
Statistics
----------------------------------------------------------
7 recursive calls
0 db block gets
60044 consistent gets
5440 physical reads
8824 redo size
19160 bytes sent via SQL*Net to client
762 bytes received via SQL*Net from client
24 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
345 rows processed
결국 5 초 만 에 달 려 논리 독 서 는 종전 103 만 명 에서 6 만 명 으로 줄 었 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.