6._바인드_변수의_부작용과_해법
2012.04.22 17:55
- SQL 수행 절차
SQL Parsing > Optimization > Row-Source Generation > Execution
- 바인드 변수 사용시
. 최초 수행시 최적화처리후 실행 계획을 캐시에 적재
. 실행시점에서 값을 바인딩하며 반복 재사용 => 변수를 바인딩하는 시점 = 실행 시점
즉 최적화 하는 시점에는 조건절 컬럼의 데이터 분포도를 활용하지 못한다.
. 평균 분포를 가정한 실행 계획을 생성한다.
. 카디널리티(Cardinality)
카디널리티(Cardinality) = 선택도(Selecivity) * 전체 레코드수
오후 5:41:18 SQL> create table t as select rownum no from dual connect by level <= 1000;
Table created
오후 5:41:35 SQL> analyze table t compute statistics for table for all columns;
Table analyzed
오후 5:41:37 SQL> 오후 5:41:45 SQL> explain plan for select * from t where no <= :no;
Explained
오후 5:42:00 SQL> select * from table(dbms_xplan.display(null,null,'basic rows'));
PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Plan hash value: 2153619298 ------------------------------------------ | Id | Operation | Name | Rows | ------------------------------------------ | 0 | SELECT STATEMENT | | 50 | | 1 | TABLE ACCESS FULL| T | 50 | ------------------------------------------
8 rows selected
오후 5:42:02 SQL> 오후 5:42:19 SQL> 오후 5:42:19 SQL> 오후 5:42:19 SQL> explain plan for select * from t where no between :no1 and :no2; explain plan for select * from t where no between :no1 and :no2;
Explained 오후 5:42:20 SQL> select * from table(dbms_xplan.display(null,null,'basic rows')); select * from table(dbms_xplan.display(null,null,'basic rows'));
PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Plan hash value: 1401356643 ------------------------------------------- | Id | Operation | Name | Rows | ------------------------------------------- | 0 | SELECT STATEMENT | | 3 | | 1 | FILTER | | | | 2 | TABLE ACCESS FULL| T | 3 | -------------------------------------------
9 rows selected
오후 5:42:20 SQL> |
바인드 변수를 사용한 경우 연산 종류에 따른 카디널리티를 유추 하는 것을 볼수 있다.
오후 5:46:47 SQL> explain plan for select * from t where no <= 100; explain plan for select * from t where no <= 100;
Explained 오후 5:46:47 SQL> select * from table(dbms_xplan.display(null,null,'basic rows')); select * from table(dbms_xplan.display(null,null,'basic rows'));
PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Plan hash value: 2153619298 ------------------------------------------ | Id | Operation | Name | Rows | ------------------------------------------ | 0 | SELECT STATEMENT | | 99 | | 1 | TABLE ACCESS FULL| T | 99 | ------------------------------------------
8 rows selected 오후 5:46:47 SQL> explain plan for select * from t where no between 500 and 600; explain plan for select * from t where no between 500 and 600;
Explained 오후 5:46:47 SQL> select * from table(dbms_xplan.display(null,null,'basic rows')); select * from table(dbms_xplan.display(null,null,'basic rows'));
PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Plan hash value: 2153619298 ------------------------------------------ | Id | Operation | Name | Rows | ------------------------------------------ | 0 | SELECT STATEMENT | | 99 | | 1 | TABLE ACCESS FULL| T | 99 | ------------------------------------------
8 rows selected
오후 5:46:48 SQL> |
리터럴 sql를 사용하는 경우에는 정확한 결과 건수를 추출 한다.
- 바인드 변수를 사용할 때는 컬럼 히스토그램에 근거 하지 않고 카디널리트를 구하는 정해진 계산식에 기초해 비용을 계산한다.
- 변수 값의 변화에 따라 최적이 아닌 실행 계획을 수행 할 수 있다.
(1) 바인드 변수 Peeking (SQL Server : Parameter Sniffing)
- 바인드 변수의 부작용을 극복하기 위한 oracle 9i 부터 바인드 변수 peeking 기능을 도입
- 첫 번째 수행 되면서 하드파싱 될때 딸려온 바인드 변수 값을 살짝 훔쳐 보고 실행 계획을 수립
- 문제점
. 하드 파싱된 Query가 선택도가 높은 데이철를 액세스 하고 나면 선택도가 낮은 다음 Query는 최악의 실행 계획이 된다.
. 반대로 처음 선택도가 낮은 Query 로 하드 파싱 되고 추후 선택도가 높은 Query가 처리 되어도 최악의 실행 게획이 된다.
. 운영중에 실행 계획이 자주 바뀌면서 성능이 들쭉 날쭉 한 것이 더 큰 문제가 될 수 있다.
- 이러한 이유로 바인드 변수 Peeking는 비활성화 시켜 놓은 상태
ater system set "_optim_peek_user_binds"=FALSE;
(2) 적응적 커서 공유(Adaptive Cursor Sharing)
- Peeking 기능의 부작용을 해결 하기 위해 11g에서 걔선된 기능
- 처리 방법
. 처음 선택도가 높은 변수 값으로 하드 파싱 => Full Scan
. 선택도가 낮은 값이 입력되면 Child커서 캐싱 => Index Scan
. 선택도가 높은 값이 들어오면 Full Scan 실행 계획으로 수행
. 선택도가 낮은 값이 들어오면 Index Scan 실행 계획으로 수행
- 해당 정보의 관련 View
. v$sql_cs_statistics
. v$sql_cs_histogram
. v$sql_cs_selectivity
- 사용
. 조건절 컬럼에 히스토그램이 생성되 있어야 한다.
.v$sql.is_bind_sensitive = 'Y' : Bind Sensitive 커서
옵티마이저가 변수값에 따라 실행계획을 달리 가져갈 필요가 있다고 판단되는 SQL
.v$sql.is_bind_aware = 'Y' : Bind Aware 커서
이전일량에 비해 많은 일량을 처리한 것으로 판단되면 bind Aware모드로 저환
기존 커서 사용중지및 새로운 커서 생성, 선택도가 비슷한 것끼리 같은 커서 공유
- 수행 예
오전 7:05:42 SQL> select 도시,count(1) from 아파트매물 group by 도시;
select 도시,count(1) from 아파트매물 group by 도시;
도시 COUNT(1)
------ ----------
서울시 152345
경기도 110311
강원도 159
충청도 11475
전라도 4665
제주도 244
경상도 1222
7 rows selected
(3) 입력값에 따라 SQL 분리
- Access path 의 중요한 컬럼의 데이터 분포가 균일하지 않은 상황에서 바인드 변수의 부작용을 피하기 위한 실행 계획 분리
예) select /*+ FULL(아파트매물) */ * from 아파트매물 where :city in ('서울시','경기도') and 도시 = :city
union all
select /*+ INDEX(아파트매물 IX_아파트매물) */ * from 아파트매물 where :city not in ('서울시','경기도') and 도시 = :city
;
- 또다른 문제점
oltp 상에서 union all 등에 의해 query 문이 길어지만 라이브러리 캐쉬 효율이 떨어진다.
Application 상에서 query를 분리하여 사용하는것이 바람직하다
(4) 예외적으로 Literal 상수값 사용
- 입력값에 따라 SQL을 분리의 한계 존재 : 값의 종류가 많은 경우, 종류가 변하는 경우 source 수정 필요
- 값의 종류가 소수 일때는 바인드 변수보다 오히려 Literal 상수를 사용하는 것이 바람직
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
46 | 9._Static_vs._Dynamic_SQL | 남송휘 | 2012.05.07 | 5588 |
45 |
2._User_Call_vs._Recursive_Call
![]() | 정찬호 | 2012.05.07 | 4596 |
44 |
1._Call_통계
![]() | 정찬호 | 2012.05.07 | 4488 |
43 |
5장._데이터베이스_Call_최소화_원리
![]() | 운영자 | 2012.05.07 | 5116 |
42 | 11._Static_SQL_구현을_위한_기법들 | dasini | 2012.05.06 | 3948 |
41 |
4._커서_공유
![]() | 남송휘 | 2012.04.26 | 16512 |
» | 6._바인드_변수의_부작용과_해법 | 시와처 | 2012.04.22 | 4812 |
39 | 5._바인드_변수의_중요성 | 시와처 | 2012.04.22 | 4505 |
38 | 8._애플리케이션_커서_캐싱 | 박영창 | 2012.04.21 | 5438 |
37 | 7._세션_커서_캐싱 | 박영창 | 2012.04.21 | 8118 |
36 |
10._V$SQL
![]() | 정찬호 | 2012.04.09 | 6805 |
35 |
9._ASH(Active_Session_History)
![]() | 정찬호 | 2012.04.09 | 6288 |
34 | 4장._라이브러리_캐시_최적화_원리 | dasini | 2012.04.08 | 2938 |
33 |
12._데이터베이스_성능_고도화_정석_해법
![]() | 남송휘 | 2012.04.08 | 4744 |
32 | 11._End-To-End_성능관리 | 남송휘 | 2012.04.08 | 3240 |
31 | 3._라이브러리_캐시_구조 | dasini | 2012.04.05 | 5383 |
30 | 2._SQL_처리과정 | dasini | 2012.04.05 | 21945 |
29 | 1._SQL과_옵티마이저 | dasini | 2012.04.05 | 3824 |
28 | 5._V$SYSSTAT | AskZZang | 2012.04.03 | 4772 |
27 | 4._DBMS_XPLAN_패키지 | AskZZang | 2012.04.03 | 5773 |