http://forums.oracle.com/forums/thread.jspa?threadID=664391&tstart=0

http://www.oracle-base.com/articles/10g/Services10g.php#jobs_and_services

11g 에서는 instance_id 가 추가된다고는 하지만..10g에서는 꽁수로 가능함



Posted by maceo

01 1, 2009 14:50 01 1, 2009 14:50
, ,
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/129

10.2.0.4 패치에서 workload capture 까지는 지원하나 capture파일의 재생은 11g에서만 가능하다고 하는군. 젠장 -_-;;;;

http://www.dbta.com/e-edition/Dec08/13-column_kumar.html

혹시 모르니 오라클에 물어나볼까나....

Posted by maceo

12 29, 2008 01:26 12 29, 2008 01:26
, ,
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/128

IO 부하 경감을 위한 KEEP Pool의 활용


여러 사람들의 이야기를 들어보니 Oracle의 Multi Buffer Pool 기능을 잘 사용하지 않는다고들 한다. 그런데 우리 사이트처럼 상당한 량의 Online Transaction과 Batch가 함께 도는 사이트에서는 Multi Buffer Pool이 유용하게 쓰일 수 있다.

일반적으로 KEEP Pool은 항상 read가 일어나야 하는 조그만 테이블들을 KEEP하는 용도라고 알려져 있다. 하지만 우리 사이트에서는 다르게 사용한다. 

Batch와 Online에서 다 같이 많이 쓰는 "큰" 테이블/인덱스들을 KEEP에 올려놓는다.

1. table full scan 으로 테이블을 읽으면 touch count도 올라가지 않을 뿐 아니라 buffer cache의 끝부분에 올라갈 가능성이 높다. (http://ukja.tistory.com/133 참조) 하지만 상대적으로 여유가 많은 KEEP으로 보내게 되면 메모리에 좀 더 오래 머물러 있을 가능성이 높다.

2. 이 테이블을 online에서도 다양한 파라미터로 index range scan하거나 table access by rowid를 할 때 해당 블럭들은 touch count가 높아지면서 KEEP에 좀 더 오래 머물러 있을 가능성이 높아진다. 

KEEP사이즈보다 더 크게 오브젝트를 KEEP해도 무방하다.
KEEP도 기본 버퍼풀과 동일한 알고리즘으로 움직인다. 모자라다고 해서 에러를 내지는 않는다. 오히려 이렇게 하는게 더 좋은 것 같다. full scan이 발생하는 테이블이라고 해서 언제나 모든 블럭이 메모리에 있어야 하는 것은 아니다. 그 중에서 range scan이 많이 들어오는 블럭들은 KEEP에도 오래 머물것이고, 다른 테이블에 대한 full scan이 들어올때는 touch count 가 높아져 있는 블럭들을 제외한 나머지 블럭들은 영역을 내줘도 괜찮은 것 같다.

Recyle Pool 에는 사이즈 크고 가끔 쓰는 테이블들을 올려놓는다.
이를테면 email 발송 솔루션의 발송 대상 테이블 같은 것들이다. (원래는 박스 자체를 분리해야하나..-_-)

정리하자면,

online과 batch가 함께 도는 환경에서는
1. onoline/batch에서 다 같이 자주 쓰는 "큰" 테이블은 KEEP
2. batch에서만 가끔 쓰는 테이블은 Recycle에 넣어서 full scan의 영향도를 최소화하자.

(KEEP에 큰 테이블을 넣는 것은 사실 상식에 반하는 것인데.. 좀 더 검증이 필요하다. KEEP에 넣는 오브젝트들을 다양하게 조절하면서 v$buffer_pool_statistics, v$db_cache_advice의 변화를 계속 관찰하자.)


Posted by maceo

12 27, 2008 02:11 12 27, 2008 02:11
, , ,
Response
No Trackback , a comment
RSS :
http://merritt.co.kr/tt/rss/response/127

IOT 에서 redo log 를 조심하자

Oracle 에서는 IOT를 잘 쓰질 않는다. SQL Server 에서는 Clustered Index를 습관적으로 사용하는데 비해서 오라클에서는 확실히 분위기가 좀 다른 것 같다. 잘만 쓰면 여러모로 좋은 점이 많을텐데 습관의 벽을 잘 넘어서지 않는 것 같다는 생각이 든다.

이번에 통계DB 테이블을 IOT 전환하면서 알아낸 몇가지..

테스트 내역
날짜 + 분류코드로 PK가 잡힌 5억건의 일반 테이블을 IOT로 전환

테스트 결과 요약

  1. 일반적인CTAS nologging 으로 하면 redo, undo가 발생하지 말아야 하지만 IOT 면 redo가 발생한다.
    보통의 IOT테이블에는 direct INSERT가 안먹는다.
  2. 대상 IOT가 Partitioned IOT 면 Direct-INSERT 가능하다.
    11g 에는 매뉴얼에 그렇게 나와있는데 10g R2 매뉴얼에는 IOT 에는 direct insert 가 안된다고 나왔다. 실제 테스트해보면 그렇지 않다. 10g R2 에서 Partitioned IOT 에 CTAS하면 redo 가 최소화된다. 10g R2 매뉴얼에 오류가 있는 것으로 보임.
  3. Including , overflow를 조심해서 쓰자.
    여기에 포함된 컬럼 때문에 redo가 대량으로 생길 수 있다. 조심하자
  4. Insert /*+ append */ 를 쓰지 말고 CTAS를 쓰자.
    Partitioned IOT를 미리 만들어놓고 Insert /*+ append */ 하면 최종 commit 때문에 CTAS보다 redo가 훨씬 많이 발생한다. DML이라서 그렇다. CTAS는 DDL이므로 redo같은게 없음.

결론
일반 테이블을 IOT 전환시 redo 발생을 최소화하기 위하여 Partitoned IOT 를 CTAS nologging 으로 생성하자.

추가 테스트 필요 사항
heap table / IOT table / Partitioned IOT 에 DML (insert/update/delete모두) 을 발생시킬 때 redo/undo 의 양


Posted by maceo

12 26, 2008 18:18 12 26, 2008 18:18
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/126

PX COORDINATOR FORCED SERIAL 이 뜰 경우

병렬 쿼리에서 FORCED SERIAL 이 뜨면서 병렬로 실행이 못되는 경우가 있다.

이럴 때는 쿼리에서 쓰인 Stored Function 을 의심해보자.

Function 중에 parallel_enable 이 되어 있지 않은 놈이 있다면 parallel_enable 을 붙여준다!

자세한 것은 포이어슈타인의 오라클 PL/SQL 프로그래밍을 참조!!!


Plan Table                                                                 
----------------------------------------------------------------------------
| Operation                                 | Name                         |
----------------------------------------------------------------------------
|  PX COORDINATOR FORCED SERIAL             |                              |
|   PX SEND QC (RANDOM)                     |:TQ10010                      |
|    FILTER                                 |                              |
|     HASH GROUP BY                         |                              |
|      PX RECEIVE                           |                              |
|       PX SEND HASH                        |:TQ10009                      |
|        HASH GROUP BY                      |                              |
|         HASH JOIN RIGHT OUTER             |                              |
|          BUFFER SORT                      |                              |
|           PX RECEIVE                      |                              |
|            PX SEND BROADCAST              |:TQ10000                      |
|             VIEW                          |                              |
|              SORT GROUP BY                |                              |
|               TABLE ACCESS BY GLOBAL INDEX|TR_ORD_PRD                    |
|                INDEX RANGE SCAN           |IX5_TR_ORD_PRD                |
|          VIEW                             |                              |
|           HASH GROUP BY                   |                              |
|            PX RECEIVE                     |                              |
|             PX SEND HASH                  |:TQ10008                      |
|              HASH GROUP BY                |                              |
|               HASH JOIN RIGHT OUTER       |                              |
|                PX RECEIVE                 |                              |
|                 PX SEND HASH              |:TQ10006                      |
|                  PX BLOCK ITERATOR        |                              |
|                   TABLE ACCESS FULL       |MB_PRVT_MEM                   |
|                PX RECEIVE                 |                              |
|                 PX SEND HASH              |:TQ10007                      |
|                  HASH JOIN RIGHT OUTER BUF|                              |
|                   PX RECEIVE              |                              |
|                    PX SEND HASH           |:TQ10004                      |
|                     PX BLOCK ITERATOR     |                              |
|                      TABLE ACCESS FULL    |MB_MEM_MG_GR                  |
|                   PX RECEIVE              |                              |
|                    PX SEND HASH           |:TQ10005                      |
|                     HASH JOIN RIGHT OUTER |                              |
|                      PX RECEIVE           |                              |
|                       PX SEND HASH        |:TQ10002                      |
|                        VIEW               |                              |
|                         HASH UNIQUE       |                              |
|                          WINDOW SORT      |                              |
|                           PX RECEIVE      |                              |
|                            PX SEND HASH   |:TQ10001                      |
|                             PX BLOCK ITERA|                              |
|                              TABLE ACCESS |MB_MEM_HIST                   |
|                      PX RECEIVE           |                              |
|                       PX SEND HASH        |:TQ10003                      |
|                        PX BLOCK ITERATOR  |                              |
|                         TABLE ACCESS FULL |MB_MEM                        |
----------------------------------------------------------------------------

Posted by maceo

12 18, 2008 22:22 12 18, 2008 22:22
, ,
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/124

pga_aggregate_target은 limit 이 아님


아무리 pga_aggregate_target 을 정해놓더라도 빡센거 돌면 그거 넘어서서 PGA 할당한다.
over allocation 가능하다는 말씀. 그러면 얼마나 할당할 수 있느냐? Oracle 버전에 따라 다르다. 아래 링크 참고

http://www.pythian.com/documents/Working_with_Automatic_PGA.ppt

Five Tuning Tips For Your Data Warehouse 

기타 여러가지 좋은 팁들이 많다...

Posted by maceo

12 18, 2008 19:49 12 18, 2008 19:49
,
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/123

대량 DML 로 인한 gc 대기 잡기

갑자기 DB가 Hang이 걸리거나 WAS에서 큐가 마구 쌓일 때, 일단 대기를 살펴보자.

잽싸게

create table pnc$active_ses as
select * from v$active_session_history


를 해놓고 초단위로 IO, User, Cluster, Concurrency , Other등의 Wait Class 별로 발생빈도를 측정한다. 그러면 어떤 순서로 대기가 발생했는지 알 수 있고 DB에서 무슨 일이 벌어졌는지 실마리를 잡을 수 있다.

어제 대량 DML 로 인한 gc 대기를 그렇게 잡았다.

위의 방식으로 살펴보니 instance 레벨에서 Cluster 대기가 엄청 발생하고, 그 후에 Concurrency 가 발생했다. 주로 gc cr current block-2way 와 gc cr request 가 먼저 왕창 생기고 그 후에 latch: cache buffer chains 가 발생했는데...

http://wiki.ex-em.com/index.php/Gc_cr/current_block_2-way 참고
http://wiki.ex-em.com/index.php/Gc_cr/current_request 참고

current block 인 것으로 보아 갑자기 대량 DML이 발생한 것 같아서 여기저기 수소문해보니 그런 일이 있었다. 업무적으로 이걸 막기는 힘든 상황.. 마침 gc cr block lost 도 많이 보여서 UDP 패킷 사이즈를 체크.

* gc cr/current request - Tuning
 
비효율적인 네트워크 설정
 - Gigabit Ethernet Interconnect에서는 UDP(User Diagram Protocol) 사용
 - 확인 방법 :
 SQL> oradebug setmypid
 SQL> oradebug ipc
 SQL> oradebug tracefile_name
 
[예제]
PCSDB1:SQL>oradebug setmypid
Statement processed.
PCSDB1:SQL>oradebug ipc
Information written to trace file.
PCSDB1:SQL>oradebug tracefile_name
/cs_orahome/oracle/10.2.0/admin/PCSDB1_csdb1/udump/pcsdb1_ora_11771.trc
PCSDB1:SQL>exit
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit Production
With the Partitioning, Real Application Clusters, OLAP and Data Mining Scoring Engine options
[PCSDB1] /cs_orahome/oracle/10.2.0/rdbms/admin> vi /cs_orahome/oracle/10.2.0/admin/PCSDB1_csdb1/udump/pcsdb1_ora_11771.trc
 
* 결과
locked 1
blocked 0
timed wait receives 0
admno 0xfe8bc48 admport:
SSKGXPT 0x217880 flags SSKGXPT_READPENDING      socket no 8     IP 10.1.1.1     UDP 58379
context timestamp 0
        no ports
 
 - RAC Interconnect 성능과 가장 연관 있는 것은 UDP Buffer Size.
 - 오라클 권장 UDP buffer size = 256K
 - UDP Buffer Size가 작으면 패킷유실(Packet loss) 현상이 발생. (gc cr/current block lost 발생)
 
 * 패킷 유실 확인
 [PCSDB1] /cs_orahome/oracle> netstat -s -p udp
udp:
        57726 incomplete headers
        4795 bad checksums
        52931 socket overflows
 
 
# 아래 metalink 문서에서는 HP-UX서버에서는 UDP 튜닝이 안되는걸로 확인됨
 1.문서변경 : Reference site확인결과
 UDP Send buffer size는 64K로 Fix되어 다른 값으로 변경 할 수 없고
 UDP Receive buffer size는 ndd명령으로 변경가능함
 
 2. Reference Site size
 - 메리츠 증권 : 1M
 - 신한은행 : 2G
 - SKT : 1M

OS 커널 파라미터를 UDP 패킷 버퍼 1M 로 변경하고 나니 문제 해결~~~

오늘의 교훈

뭔 일이 생기면 일단 active_session_history 를 덤프떠놓고 세심하게 분석해보자!!

Posted by maceo

12 18, 2008 19:46 12 18, 2008 19:46
, , ,
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/122

SGA 가 춤을 출 때

SGA에서 shared pool 과 buffer cache 가 커졌다 작아졌다 난리부르스를 출 때...

확인은

select *
from (
    select INST_ID,
      COMPONENT,
      OPER_TYPE,
      OPER_MODE,
      PARAMETER,
      INITIAL_SIZE,
      TARGET_SIZE,
      FINAL_SIZE,
      (final_size-initial_size)/1024/1024 as delta_mb,
      STATUS,
      START_TIME,
      END_TIME
    from GV$SGA_RESIZE_OPS
    where inst_id=1
    order by inst_id, END_TIME desc)
where rownum <= 50

만약 buffer cache 가 GROW 하고 shared pool이 줄어들 때 shared pool 쪽에서 library cache pin 이 일어날 수 있다. 잘못하면 이거 안풀리고 DB가 Hang까지 갈 수 있다.

왜 이런 일이 일어날까? 10g 에서부터 buffer cache 가 커지면 shared pool 의 영역을 일부 뺏어와서 쓰게 된다. 이 영역을 KGH: NO ACCESS 영역이라고 한다.

Resizing the SGA « Oracle Scratchpad 참고

오라클은 KGH: NO ACCESS 영역을 찜해놓고, 그 안에 있는 LCO를 바로 clean out 하지는 않는다. 그렇게 하기도 어렵고 대단히 무리한 CPU Operation 이 될 수 있기 때문이다. 그래서 영역을 일단 찜하고 그 안에 있는 LCO들이 unpin되면 그 영역을 buffer cache로 점진적으로 가져온다. 이럴 때 위의 쿼리에서 OPER_MODE 가 DEFFERED 로 찍힌다.

그러면 왜 library cache pin이 일어날까?

이건 추측인데... 메모리를 KGH: NO ACCESS 로 표시할 때 그 안에 들어가있는 LCO 들에 대해서 어떤 플래그를 달아야 하는데, 그 때 pin 이 걸리는게 아닐까 싶다. 확인할 길은 없다. 물론 영역 크기가 크면 자주 호출되는 LCO 가 걸려들 가능성이 높을거고 그때 pin 이 걸리겠지.


또 하나 관찰한 흥미로운 증상은, SGA Max > SGA Target 일 때 SGA resize가 더욱 빈번하게 일어난다는 거다. 거의 1~2분에 한번씩 일어나서 오라클 버그로 의심했으나

Simple Is Beautiful | SHARED POOL中KGH: NOACCESS占用大量内存的问题分析  참고

우리가 쓰는 10.2.0.3 에서는 패치가 되었다고 Oracle SR 결과 확인이 되었다. 그래서 궁여지책으로 SGA Max = SGA Target 으로 맞추고 나니 증상이 훨씬 덜해졌다. 이건 또 왜 이런걸까??

그리고.. SGA Max > SGA Target 으로 설정해놓고 몇G의 여유분을 놔둔다 하더라도 쎈 배치가 돌거나 어떤 일이 생기면 SGA Target을 넘어서서까지 메모리를 할당을 하는 것 같다. PGA도 pga_aggregate_target을 넘어서서 할당을 하는데 (v$pga_target_advice뷰의 over allocation참조) SGA Target도 마찬가지인듯. 그리고 Target을 넘어서서 메모리를 사용하고 나면 자동적으로 Target까지 shrink 를 시도하는게 아닌가 한다.

살펴보니 추측투성이네~

결론은...

ASSM쓸거면 SGA Max = SGA Target으로 해놓자.

이다.

Posted by maceo

12 18, 2008 19:30 12 18, 2008 19:30
, ,
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/121

중급 개발자들이 보아야 할 오라클 책

오늘 중급개발자로 부터 오라클을 잘사용할수 있도록 3종류의 책을 추천 해달라는 요청을 받았다.
"오라클을 7~8년 정도 사용하였지만 3~4년 전부터 SQL 실력이 늘지않는다." 가 추천을 요청한 사유이다.
3종류의 책은 다음과 같다.
1. SQL 을 자유자재로 구사할수 있는 능력을 기르는 책
   참고로 위의 책은 튜닝책을 이야기 하는것이 아니다.
   원하는 답을 내기위한 효율적인 SQL 활용법을 가르쳐주는 책을 이야기 하는것이다.  
2. SQL 튜닝책
3. PL/SQL 튜닝책

물론 단한권으로 1,2,3 번을 어느정도 기본적인 사항들을 커버하는 책이 있다.
바로 Tomas KyteEffective Oracle by Design 이다.
하지만 위의 책을 정복 한다고 해도 1,2,3 번중 어느것도 Master 가 될수는 없다.
왜냐하면 한권의 책으로는 깊이의 한계와 페이지수의 한계를 넘지못하는 것이다.
마찬가지로 국내서적중에서 깊이있는 책이 존재하지만 1,2,3번을 모두다 다루려고 하다보니 대부분 깊이
들어가지 못하고 소개정도에 그치고 있다.  

해당 개발자는 다행스럽게도 영문서적도 상관없다고 하였다.
또한 각권을 독파하면 바로 효과를 볼수 있는 책을 원했다.
다시 말하면 투자시간 대비 효율이 좋은 책을 원하는 것이다.
어떤책이 투자시간 대비 효율이 좋은 책인지 이해를 돕기위해 아래의 그림을 보자.

사용자 삽입 이미지












위의 곡선은 필자가 생각하는 실력 상승곡선이다.
검은 화살표 3개를 보면 조금만 노력을 하면 실력이 급격히 향상되는것을 알수있다.
이것은 초급 중급 단계에서는 조금만 노력해도 실력향상의 폭이 크다는 것을 나타낸다.
하지만 상대적으로 빨강화살표 부분부터는 노력을 많이해도 실력이 별로 늘지 않음을 알수 있다.
다시말하면 고급(고수의 세계)단계에서는 책 1~2 권 읽는다고 해서 실력이 그다지 늘지않는다.    
누구도 실력 상승곡선의 예외일수 없다.
오늘 추천하는 책 3권은 오라클 개발및 튜닝 관점에서 빨강화살표 부분까지 가장 빨리 도달할수있게
도와주는(효율이 좋은) 책이라 할수 있다.  
개발자들이 읽어야할 책과 DBA, 컨설턴트들이 보아야 할 책은 엄연히 다르고 생각한다.
개발자 입장에서 일단 후보가 될수있는 책을 생각하니 7~8권 정도 생각이 났지만 몇시간의 장고 끝에
아래의 3권을 추천 하였다.

1.SQL 을 자유자재로 구사할수 있는 책 :
   Mastering Oracle SQL 2nd Edition (저자:Sanjay Mishra & Alan Beauieu)

2.SQL 튜닝책 :
   SQL Tuning (저자:Dan Tow)

3.PL/SQL 튜닝책 :
   Mastering Oracle PL/SQL (저자:Cornor McDonald)


각각의 장점을 설명하면 아래와 같다.

1.Mastering Oracle SQL 2nd Edition (저자:Sanjay Mishra & Alan Beauieu)
  말이 필요없는 SQL 활용의 대가인 Alan Beauieu 의 작품이다.
  중급개발자라면 1,2장은 넘기면서 볼수 있지만 3장부터는 신경을 써야한다.
  모든 스크립트는 온라인으로 Down Load가 가능하다.
  자세한 내용은 필자의 서평을 참조하기바란다.

2.SQL Tuning (저자:Dan Tow)
  Oracle 뿐아니라 DB2, SQL Server 의 SQL 튜닝을 모조리 커버하는 놀라운 책 이다.
  여러분이 만약 업무를 모르는 상태에서 SQL 튜닝 요청을 받았다고 가정하고 해당 SQL 의 FROM 절에
  테이블이 8~10 개정도 있다고 할때 조인순서및 조인방법을 쉽고 빠르게 확정할수 있겠는가?
  국내외를 막론하고 조인순서및 조인방법에 대하여 이책만큼 명확한 방법론을 제시하는 책은 없었다.
  Dan Tow 의 Diagram-Based 방법론을 익힌다면 SQL 튜닝에 대해서는 더이상 걱정이 없을것이다.
  Method-R 방법론을 집대성한 Cary Milsap 이 적극 추천한 책이기도 하다.

3.Mastering Oracle PL/SQL (저자:Cornor McDonald)
  PL/SQL 문법이나 활용서적이 아니라 튜닝 책이다.
  마지막 순간까지 이책과 Steven Feuerstein 의 Oracle PL/SQL Best Practices를 두고 고민 하였다.
  하지만  Steven Feuerstein 의 책은 100% PL/SQL 튜닝 책이 아니고 PL/SQL 의 효율적인 활용에 대해서
   50% 정도 언급을 하고 있기 때문에 제외 시켰다.
  Cornor McDonald의 책은 100% 튜닝관점에서 집필된 책이다.
  모든 소스 코드가 온라인에 공개되어 있으므로 튜닝과정을 따라가기가 매우쉽다.  
  예를 하나만 들면
 "같은 답을 내는 2가지의 PL/SQL 이 있고 구현방법이 다를때 redo 양이 적게 발생하는 것이 무엇인지?"
  등의 상당히 재미있는 주제가 많다.  
  기본(1,2번 책)을 익히고 이책을 정복한다면 이책의 제목처럼 PL/SQL 튜닝에 대해서는 Master 가 될것이다.

모든 중급개발자및 DBA들에게 위의 3가지 책을 자신있게 추천한다.
만약 컨설턴트들이 위의 책들을 보지 못했다면 실수라고 말하고 싶다.
이런 종류의 책이 국내에는 없다는점이 아쉬울 뿐이다.
최근에 환율이 장난이 아니고 난위도가 어느정도 있는책이므로 중간에 포기할 생각이라면 원서를
구입하지말고 E-Book 등을 활용하기 바란다.
참고로 3번책을 제외하면 E-Book 을 구할수 있다.(방법은 각자 알아서...)

편집후기 :
혹시 여러분들이 1,2,3 번에 대해여 다른책을 추천한다면?
물론 효율(실력 상승곡선)을 염두에 두어야 한다.
여러분들의 의견을 듣고 싶다.  


-----

일단 위의 3권을 보시는데만 6개월은 족히 걸릴거 같습니다.
제가 서평을 3~4 개월 마다 올리므로 그때 참조하시는 것도하나의 방법이 되겟습니다.
참고로 제가 고민 했던 7~8 권은 아래와 같습니다.
1.SQL 을 자유자재로 구사할수 있는 책
SQL COOK BOOK
The Art of SQL
대용량 데이터베이스 솔루션 2권
2.SQL 튜닝책:
Oracle SQL High-Performance Tuning (2/E)
대용량 데이터 베이스 솔루션1 OLD 버젼
3.PL/SQL 튜닝책
Oracle PL/SQL Best Practices
Expert Oracle PL/SQL

Posted by maceo

11 12, 2008 13:16 11 12, 2008 13:16
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/119

first_rows_n

first_rows_n

Filed under: CBO, Execution plans, Hints, Performance, Tuning — Jonathan Lewis @ 1:05 pm UTC Nov 11,2008

When it comes to setting the optimizer_mode parameter you often hear people say that first_rows_N (for one of the legal values of N) should be used for OLTP systems and all_rows should be used for decision support and data warehouse systems.

There is an element of truth in the statement - but it’s really a hangover from the early days of CBO, and remembrance of  the old first_rows optimizer mode (** See footnote).

Prior to the introduction of parameters like optimizer_index_cost_adj (Oracle 8), and system statistics (Oracle 9 - but optional until 10g), the cost based optimizer often seemed too keen to use execution plans that involved tablescans and hash joins - which could be most unsuitable in an OLTP system.

This problem appeared because the optimizer did not attempt to distinguish between the potential performance of a “db file sequential read” (single block read) compared to a “db file scattered read” (multiblock read).  Setting the optimizer_mode to first_rows introduced some simple rules that (to a large extent) stopped the optimizer from using tablescans unless there were no alternatives.

In 9i, however, first_rows_N optimisation is geared towards using arithmetic to make decisions about avoiding tablescans. You can see the results of this in some of the odd numbers that appear in execution plans as the optimizer works out whether, for example, it is better to use an index to pick up 10 rows from a table, or whether running 2.3% of a tablescan (which would probably get the first 10 rows) is the cheaper option.

Think about what this means - first_rows_N is trying to work out the cheapest way of collecting the first N rows of the result set, whereas all_rows is trying to work out the cheapest way of collecting all the rows of the result set.

But when you are running an OLTP system a huge fraction of typical end-user queries will be returning just a handful of rows - and if you have a query that’s only supposed to return 5 or 6 rows (say), then first_rows_10 actually means “all the rows I expect”, i.e. all_rows. If the optimizer works correctly, then both options should produce the same execution plan.

Of course, some end-user queries (even in an OLTP system) are reports, and for reports you don’t want to generate a plan that’s optimised to return the first few lines so, again, you’re really interested in all_rows optimisation.

Your conclusion should therefore be: for OLTP systems, first_rows_N ought to be irrelevant. You should be using all_rows - unless you can demonstrate that this introduces a large number of execution plans that have to be fixed individually because of some unexpected side effects (Again, though, see footnote).

So why would we ever need first_rows_N ?

Think Google, or Amazon, or any of the “forum” software suppliers.  There are systems which are effectively ad hoc query systems where users can supply query predicates that could return a lot of data - but the code limits the amount of data sent back to the user to “page at a time”. Think “web-based reporting system”, and you’ve identified the basic rationale for first_rows_N.

Even for the web-base reporting system, though, you may still be able to run under all_rows from from 10g onwards. In 10g when the optimizer sees predicates like “rownum <= 35″ it will behave as if you had included the hint /*+ first_rows(35) */ in the query.

As a closing thought: even if you think that first_rows_N may be the correct logical and strategic choice for your system, remember that it hasn’t been “field-tested” to the extent that all_rows has been tested.

There are bugs (or side effects) in the optimizer that make their first appearance only in the strange circumstances of “real-world” applications - and it’s a good bet that such oddities are found (and probably fixed) faster in the all_rows environment than in the first_rows_N environment simply because far more systems use all_rows.

Even when first_rows_N seems to be the right choice, you could decide to stick with all_rows and adjust critical statements with a /*+ first_rows(N) */ hint.

Footnote: If you still have any systems running 9i or later and using first_rows, you should be planning to change the optimizer_mode when you next go through a full test cycle. As the manuals point out (9.2 Performance Tuning Guide and Reference p1-12): first_rows is available for backward compatibility and plan stability”.

Backward compatibility is important, and until you enable system statistics, clean up various other optimizer related parameters, sort out your statistics collection strategy, and clean out a load of redundant hints and SQL hacks, you may find that changing the optimizer_mode introduces as many problems as it solves - and that’s why this is a change that needs a lot of testing

Posted by maceo

11 11, 2008 23:56 11 11, 2008 23:56
Response
No Trackback , No Comment
RSS :
http://merritt.co.kr/tt/rss/response/118


블로그 이미지

가늘어도 긴놈이 장땡

- maceo

Archives

Authors

  1. maceo

Calendar

«   3 2010   »
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      

Site Stats

Total hits:
170288
Today:
32
Yesterday:
47