출처 : https://stackoverflow.com/questions/2157282/generate-days-from-date-range
-- STR_TO_DATE 파라미터에 들어가는 날짜 역순으로 해서 최대 1000개 row를 생성하여 조회조건으로 걸러낸다.
SELECT DT.YYYYMMDD |
-- 현재 날짜 역순으로 해서 최대 1000개 row를 생성하여 조회조건으로 걸러낸다.
SELECT DT.YYYYMMDD |
출처 : https://stackoverflow.com/questions/2157282/generate-days-from-date-range
-- STR_TO_DATE 파라미터에 들어가는 날짜 역순으로 해서 최대 1000개 row를 생성하여 조회조건으로 걸러낸다.
SELECT DT.YYYYMMDD |
-- 현재 날짜 역순으로 해서 최대 1000개 row를 생성하여 조회조건으로 걸러낸다.
SELECT DT.YYYYMMDD |
Oracle 참고 : http://docs.oracle.com/cd/B28359_01/java.111/b31224/urls.htm#BEIDHCBA
https://docs.oracle.com/cd/B12037_01/network.101/b10776/tnsnames.htm
오라클 SID, Service Name 차이 | Oracle개념용어정리
--------------------------------------------------------------------
지금껏 오라클을 사용하면서도 SID와 Service Name은 거의 구분해서 사용하지 않았다.
덕분에 최근까지는 SID와 Service의 차이를 인식하지 못하고 사용해 왔다.
사실 일반적인 테스트 환경이나 소규모의 경우 한개의 DB서버에 한개의 인스턴스만 사용한다.
이런 환경에서는 SID와 Service Name을 구분할 필요가 없었던것.
단순히 구분짓자면 이렇게 말할수 있다.
SID = DB 하나의 인스턴스
Service Name = 여러개의 인스턴스를 모아 하나의 서버 혹은 시스템을 구성한것
쉽게 예를 들어보자.
서버 한대에 인스턴스를 여러개 생성하여 orcl1, orcl2 로 각각 생성했다고 하자.
각각의 인스턴스는 orcl1, orcl2 라는 SID를 갖게 된다.
해당 서버에서 두개의 인스턴스를 묶어 사용할경우, orcl 이라는 Service Name을 갖을수 있다.
이외에도 서버 두대에 설치하여 각각 미러링 처리하여 동일한 서버인것 처럼 활용할경우
각각의 서버는 서로다른 SID를 갖게 되지만 Service Name을 동일하게 하여 같은 서버 처럼 활용할수 있다
[출처] 오라클 SID와 Service Name의 차이|작성자 도토리
DBMS 서버를 기동하기 위해서는 DB서버가 기동하는 서버의 IP 그리고
DB서버가 접속을 받아들이기 위한 프로토콜에 대한 정의가 필요합니다.
오라클의 경우 인스턴스가 서버 역할을 하는 DBMS프로세스인데,
인스턴스가 기동할때 SID를 필요로 합니다.
즉 SID는 인스턴스의 이름인 셈이지요.
SID가 필요한 이유는 한 서버(H/W)에 여러개의 인스턴스가 기동될 수 있으므로
구별하는 태그가 필요하겠지요. 따라서 SID는 DB서버에서 필요한 정보입니다.
SID정보는 환경변수와, LISTENER.ORA라는 파일에서 정의 됩니다.
DB에 접속하는 클라이언트 프로그램의 경우 접속하고자 하는 오라클 인스턴스 정보를
필요로 합니다. 클라이언트 프로그램이 접속하는데 필요한 정보는 서버IP, 오라클SID, 접속프로토콜
같은 정보가 필요하지요. 이러한 정보를 묶어서 서비스명으로 대표하고,
이 서비스명으로 클라이언트 프로그램이 서버에 접속하는데 사용합니다.
이 정보는 클라이언트쪽의 TNSNAMES.ORA라는 파일에 정의 되어있습니다.
출처 : 네이버 지식 검색 : 정확히는 모름(?)
instance, instantiate ; 인스턴스, 인스턴스화
--------------------------------------------------------------------
인스턴스는 추상화 개념 또는 클래스 객체, 컴퓨터 프로세스 등과 같은 템플릿이 실제 구현된 것이다.
인스턴스화는 클래스 내의 객체에 대해 특정한 변형을 정의하고, 이름을 붙인 다음, 그것을 물리적인
어떤 장소에 위치시키는 등의 작업을 통해, 인스턴스를 만드는 것을 의미한다.
1. 몇몇 필자들은, 객체지향 프로그래밍에서 클래스를 인스턴스화 한다는 것이, 클래스의 구체적인 인스턴스,
즉 객체를 만드는 것이라고 말한다. 그 객체는 컴퓨터 내에서 실행시킬 수 있는 실행 파일이다.
2. 객체지향 프로그램 언어인 자바에서는, 클래스로부터 인스턴스화된 객체를, 객체라는 말 대신에
역시 클래스라고 부름으로써 많은 사용자들을 혼란스럽게 한다. 즉 자바에서는, 특정한 클래스를
만들기 위해 클래스를 인스턴스화하며, 그것 역시 컴퓨터 내에서 동작하는 실행 파일이다.
3. 객체지향 프로그래밍 개념이 나오기 이전의 데이터 모델링이나 프로그래밍에서는, 인스턴스화라는 것이
관계형 데이터베이스 테이블 내에 새로운 엔트리를 만듦으로써 추상화된 객체로부터 실재(데이터가 들어있는)
객체를 만드는 것도, 한 가지 용례였다.
[출처] 오라클 SID, Service Name 차이 | Oracle개념용어정리 |작성자 용쓰
======================================================================
오라클(Oracle) SID 및 DB_NAME 확인 방법
출처 : http://pangate.com/665
jdbc 에서 thin 드라이버로 오라클에 접속할 때는 SID를 알아야 한다.
최근에는 SID로 직접 기술하여 접근하는 것보다는 service name 이라는 것을 tnsname.ora 파일에 지정해 놓고 이것을 사용한다. 아무래도 SID가 공개되는 것이 문제가 될 수 있을 것이다.
<tnsname.ora 의 작성 예>
서비스명과 인스턴스명과 데이타베이스명과 SID는 서로 비슷한 듯 하면서 약간 다르다.
일반적인 경우 데이타베이스가 하나만으로 구성 되어 있다면 데이타베이스명이 SID가 된다. 하지만 RAC 로 구성하여 데이타베이스 두개가 동시 가동되는 경우라면 이 SID 가 서로 다를 수 있기 때문에 중복 확인해야 한다.
JDBC 로 접속할 때 url 정보 작성 방법 :
url=jdbc:oracle:thin:@ip주소:포트:SID (url=jdbc:oracle:thin:@192.168.20.1:1521:ORCL)
아래의 예제에서 보면 RAC로 묶여 있는 경우 DATABASE NAME 과 실제 INSTANCE NAME 은 서로 다를 수 있다. 데이타베이스명은 ORCL 이지만 인스턴스명은 ORCL1 과 ORCL2 로 이름이 다름. thin 드라이브 URL 에서는 이 인스턴스명을 사용해야 한다.
======================================================================
SID
jdbc:oracle:thin:@서버IP:서버Port:SID
jdbc:oracle:thin:@//hostname:port:sid
Service Name
jdbc:oracle:thin:@서버IP:서버Port:ServiceName
jdbc:oracle:thin:@//hostname:port/serviceName
Thin 사용
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=서버IP)(PORT=서버Port)))(CONNECT_DATA=(SERVICE_NAME=ServiceName)))
출처 : http://gent.tistory.com/39
PL/SQL(Procedure, Package)을 사용하다 보면 동적으로 쿼리(Query)를 생성하거나 텍스트(text) 쿼리를 입력 받아서 실행해야하는 경우가 있다. 다음 두가지 방법을 적절히 사용하면 좋은 결과를 얻을수 있다.
EXECUTE IMMEDIATE : Inset, Update, Delete 구문을 실행하거나 Select 구문을 실행 시 INTO를 사용하여 단일 값을 리턴 받을 때 사용
OPEN-FOR : Select 구문을 실행 시 Cursor를 리턴 받을 때 사용
주의 : 바인드 변수(:) 사용 시 쿼리 내부에서 변수명은 의미가 없고 변수 순서, 개수가 USING의 변수 순서, 개수와 일치해야 한다. 바인드 변수가 없다면 USING는 생략가능.
1. EXECUTE IMMEDIATE (INSERT, UPDATE, DELETE 등 구문 실행)
CREATE OR REPLACE PROCEDURE
PC_SET_HOLIDAY ( in_hldy_dte in date
, in_hldy_nm in varchar2
, in_use_yn in varchar2)
IS
v_query varchar(1000);
d_sysdate date;
BEGIN
BEGIN
-- 단일 값을 리턴받을때
EXECUTE IMMEDIATE 'SELECT SYSDATE FROM DUAL' INTO d_sysdate;
END;
v_query := v_query || 'INSERT INTO HOLIDAY';
v_query := v_query || ' VALUES(:1,:2,:3,:4)';
BEGIN
-- INSERT, UPDATE, DELETE 구문 실행
EXECUTE IMMEDIATE v_query
USING in_hldy_dte, in_hldy_nm, in_use_yn, d_sysdate;
END;
END;
2. OPEN-FOR (CURSOR를 리턴 받을 때)
CREATE OR REPLACE PROCEDURE
PC_GET_HOLIDAY ( in_fromdate in varchar2
, in_todate in varchar2
, out_cursor out SYS_REFCURSOR)
IS
v_query varchar(1000);
BEGIN
v_query := v_query || 'SELECT HLDY_DTE, HLDY_NM';
v_query := v_query || ' FROM HOLIDAY';
v_query := v_query || ' WHERE HLDY_DTE BETWEEN :in_fromdate';
v_query := v_query || ' AND :in_todate';
BEGIN
-- CURSOR를 리턴 받을때
OPEN out_cursor FOR v_query
USING in_fromdate, in_todate;
END;
END;
-- SELECT 1건 샘플
DECLARE |
-- SELECT CURSOR 샘플
DECLARE |
참고 : http://blog.kjslab.com/20
1. 커서의 내용을 미리 정의 해 놓고 사용하는 방법
DECLARE / |
-- ROW 단위로 변수 정의
DECLARE |
-- ROW 단위로 변수 정의 후 COLUMN 단위로 사용
DECLARE |
-- COLUMN 단위로 변수 정의
DECLARE |
-- TYPE 정의
DECLARE |
2. 커서 변수를 미리 만들어 놓고 불러서 사용하는 방법
DECLARE |
3. 동적으로 커서를 생성해서 사용하는 방법
BEGIN |
오라클 쿼리 실행 시간
출처 : http://mainia.tistory.com/769
1. SET TIMING ON 사용하기 |
간혹 Stored Procedure 실행시 쿼리의 구간 별 시간을 알고
싶을 때가 있습니다. 전체 SP 수행 시간은 Object 테이블을 뒤져서
보면 되는데 각 단계별로 out print 를 찍으면서 보고 싶을 때
SET TIMING ON 을 사용하면 됩니다.
Set timing on; 후 timing start 로 시작하고 timing stop 로
마무리를 하면 됩니다. 그럼 그 시간이 측정되어 로그에
찍히게 됩니다.
Execute as Script (F5) 로 실행
SET TIMING ON; |
Toad Menu > View > Query Viewer 를 사용해도 된다.
Execute Statement (F9) 로 실행해야 보임
2. DBMS_UTILITY.GET_TIME 사용하기 |
다른 방법은 DBMS_UTILITY.GET_TIME 을 사용하는 방법입니다.
현재시간을 리턴하게 되므로 쿼리 실행후 그 차이 값을 계산하는
방법입니다. 이것이 더 불편할거 같아요.
변수를 선언하고 그 변수에 현재 시간을 저장한 후 마지막에
값을 연산해서 초로 계산하게 되는 것이다. GET_TIME 은
100분의 1초를 리턴하게 됩니다.
DELARE |
======================================================================
ORACLE서버에서 수행시간이 긴 쿼리 찾기 쿼리
SELECT ROWNUM NO,
PARSING_SCHEMA_NAME,
to_char(ELAPSED_TIME/(1000000 * decode(executions,null,1,0,1,executions)),999999.9999 ) 평균실행시간,
executions 실행횟수,
SQL_TEXT 쿼리 ,
SQL_FULLTEXT
FROM V$SQL
WHERE LAST_ACTIVE_TIME > SYSDATE-(1/24*2)
-- AND LAST_ACTIVE_TIME BETWEEN
to_Date('20111226163000','YYYYMMDDHH24MISS') AND
to_Date('20111226170000','YYYYMMDDHH24MISS')
-- AND ELAPSED_TIME >= 1 * 1000000 * decode(executions,null,1,0,1,executions)
and PARSING_SCHEMA_NAME = 'ZIPCODE'
ORDER BY 평균실행시간 DESC, 실행횟수 DESC;
SELECT TO_CHAR (SID) sid, serial# serialNumber,
SUBSTR (TO_CHAR (last_call_et), 1, 6) executeSeconds, userName, machine,
b.sql_text sqlText
FROM v$session a, v$sqltext b
WHERE username NOT IN ('SYSTEM', 'SYS')
AND a.TYPE != 'BACKGROUND'
AND a.status = 'ACTIVE'
AND a.sql_address = b.address(+)
AND a.sql_hash_value = b.hash_value(+)
ORDER BY a.last_call_et DESC, a.SID, a.serial#, b.address, b.hash_value, b.piece
현재 실행되고 있는 쿼리 와 실행 시간
SELECT TO_CHAR (SID) sid, serial# serialNumber,
SUBSTR (TO_CHAR (last_call_et), 1, 6) executeSeconds, userName, machine,
b.sql_text sqlText
FROM v$session a, v$sqltext b
WHERE username NOT IN ('SYSTEM', 'SYS')
AND a.TYPE != 'BACKGROUND'
AND a.status = 'ACTIVE'
AND a.sql_address = b.address(+)
AND a.sql_hash_value = b.hash_value(+)
ORDER BY a.last_call_et DESC,
a.SID,
a.serial#,
b.address,
b.hash_value,
b.piece
출처 : http://ukja.tistory.com/320
갑자기 퀴즈가 하고 싶어졌습니다. 지난 번 퀴즈가 너무 쉬웠다는 비난이 쏟아져서... @_@
1. 오라클 버전은 11.1.0.6입니다.
TPACK@ukja1106> select * from v$version where rownum = 1; BANNER ----------------------------------------------------------------------- Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production2. 파티션이 아닌 테이블 T1과 해시 파티션인 테이블 T2가 있습니다.
TPACK@ukja1106> create table t1(c1 number); Table created. Elapsed: 00:00:00.03 TPACK@ukja1106> create table t2(c1 number) 2 partition by hash(c1) partitions 4; Table created. Elapsed: 00:00:00.013. 파티션이 아닌 테이블 T1에 대해 40만건을 Insert하는데는 1초가 조금 안걸립니다.
TPACK@ukja1106> insert into t1 select level from dual connect by level <= 400000; 400000 rows created. Elapsed: 00:00:00.564. 해시 파티션인 테이블 T2에 대해 40만건을 Insert하는데는 무려! 6.3초가 걸립니다.
TPACK@ukja1106> insert into t2 select level from dual connect by level <= 400000; 400000 rows created. Elapsed: 00:00:06.325. 자, 여기서 문제 나갑니다. 왜 이렇게 큰 성능 차이가 발생할까요?
======================================================================
출처 : http://ukja.tistory.com/321
티팩 (TPACK)
홈페이지 : https://sites.google.com/site/otpack/
설치 : https://sites.google.com/site/otpack/guide/install_guide
이전 포스트 [퀴즈] Partitioned Table과 Insert 성능에서 제가 생각한 답변이 나왔습니다. 이렇게 적어주셨습니다.
테이블이 파티셔닝에 되어 있어, insert 할 때 insert 대상 블럭(버퍼)가 계속 바뀌게 되고, 그로 인해 logical reads가 증가하기 때문인 것 같습니다. |
이 퀴즈에서 예를 들었던 해시 파티션의 경우 매번 Insert가 이루어질 때마다 매번 다른 블록으로 들어갈 활륙이 높습니다(하지만 항상 그런 것은 아닙니다. 해시 파티션의 경우 해시값에 따라 들어갈 파티션을 결정하게 되는데 같은 해시값이 중복해서 나올 수 있기 때문입니다). 같은 원리로 레인지 파티션이나 리스트 파티션에서도 이런 문제가 발생할 수 있습니다.
가령 100개의 로우가 한번에 하나의 블록안에 들어가게 되면 Batch Processing이 이루어집니다. (또는 Array Insert라고도 합니다) Array Insert 효과에 의해서 Logical Reads도 줄어들고 Redo 데이터도 줄어듭니다.
퀴즈에서와 같이 아래와 같이 테이블을 만듭니다.
create table t1(c1 number); create table t2(c1 number) partition by hash(c1) partitions 4;Case 1. 가장 성능이 좋은 경우입니다. 가능한 많은 수의 로우가 한번에 하나의 블록안에 들어가므로 Array Insert의 효과가 극대화됩니다.
-- 가장 성능이 좋음. insert into t1 select level from dual connect by level <= 500000;Case 2. 해시 파티션인 경우 각 로우가 매번 다른 블록으로 들어갈 확률이 높습니다. 따라서 Array Insert의 효과가 크게 감소합니다.
-- 성능이 안좋아짐 insert into t2 select level from dual connect by level <= 500000;Case 3. 가장 성능이 안좋은 경우는 다음과 같이 건건이 Insert하는 경우입니다. Array Insert가 아예 발생하지 않기 때문입니다.
-- 성능이 가장 안좋음 begin for idx in 1 .. 500000 loop insert into t1 values(idx); end loop; commit; end; /Case 4. 해시 파티션에 데이터가 추가되는 원리를 이해한다면, 아래와 같은 방법을 사용하면 Case 1과 같이 가장 성능이 좋게 만들 수 있습니다. ORA_HASH 함수를 이용해서 가능한 같은 파티션으로 정렬된 형태로 Insert하는 트릭입니다. 파티션키에 정렬된 형태로 Insert를 하는 것이 핵심입니다. 레인지 파티션이나 리스트 파티션에서도 동일한 방법을 사용할 수 있습니다.
-- 가장 성능이 좋음 insert into t2 select level from dual connect by level <= 500000 order by ora_hash(level, 3);
하지만 중요한 것은 답을 맞추고 안맞추고 아니라, 데이터를 통해서 객관적으로 검증할 수 있는가입니다. 이전에 이런 퀴즈가 있었죠.
1. 오라클에서 특정 세션(혹은 시스템)의 현재 상태를 바로 알 수 있는 가장 좋은 방법은 무엇일까요?
2. 오라클에서 특정 세션(혹은 시스템)을 하는 일을 추적할 수 있는 가장 좋은 방법은 무엇일까요?
|
첫번째 질문에 대한 제 대답은 "V$SESSTAT 뷰에 대해 Snapshot을 만들고, 각 Snapshot간의 Delta값을 비교한다"입니다. 즉 세션의 성능 문제를 분석하는데 있어서 가장 중요한 Snapshot 데이터는 V$SESSTAT 뷰이며, 이 데이터를 비교라는 방법을 이용해서 분석하는 것이 가장 기본적인 방법입니다. 이것이 티팩의 핵심적인 아이디어라는 것도 이미 말씀드렸습니다.
거창하게 말씀드렸는데, 더 간결 솔직하게 말하면 V$SESSTAT 뷰가 제공하는 데이터를 분석해보면 어느 정도 의미있는 분석을 할 수 있다. 요런 이야기입니다.
티팩의 Session Snapshot Report를 이용해서 위의 내용을 분석해보겠습니다.
create table t1(c1 number); create table t2(c1 number) partition by hash(c1) partitions 4; -- Session Snapshot 시작 exec tpack.begin_session_snapshot; -- Case 1 insert into t1 select level from dual connect by level <= 500000; exec tpack.add_session_snapshot; -- Case 2 insert into t2 select level from dual connect by level <= 500000; exec tpack.add_session_snapshot; -- Case 3 begin for idx in 1 .. 500000 loop insert into t1 values(idx); end loop; commit; end; / exec tpack.add_session_snapshot; -- Case 4 insert into t2 select level from dual connect by level <= 500000 order by ora_hash(level, 3); exec tpack.add_session_snapshot; -- Session Snapshot Report 보기 set pages 10000 set lines 200 col item format a30 col deltas format a50 select * from table(tpack.session_snapshot_report);결과는 다음과 같습니다.(내용이 길어셔 편집했음을 알려드립니다) DELTAS 값을 잘 분석해보시기 바랍니다.
TYPE ITEM START_VAL END_VAL TOTAL_DELTA DELTAS ---------- ------------------------------ ---------- ---------- ----------- -------------------------------------------------- STAT redo size 1343966008 1567241868 223275860 8486656->87223020->119117508->8448676 STAT undo change vector size 423505332 485865780 62360448 1695312->26462580->32510584->1691972 STAT session logical reads 14843144 16914592 2071448 15863->1521337->518902->15346 STAT db block changes 10655679 12453768 1798089 12623->762448->1010680->12338 STAT db block gets 11368998 13058307 1689309 13946->1144031->517777->13555 STAT db block gets from cache 11368998 13058307 1689309 13946->1144031->517777->13555 STAT redo entries 5338577 6240096 901519 7792->381384->504754->7589 STAT calls to kcmgrs 5831580 6730131 898551 6973->380346->504279->6953 STAT HSC Heap Segment Block Changes 4933463 5814688 881225 2827->375425->500125->2848 ... STAT Heap Segment Array Inserts 2682231 3063258 381027 2785->375297->113->2832 ... STAT DB time 26491 31554 5063 162->1280->3406->215 ...위의 결과에서 HSC Heap Segment Block Changes와 Heap Segment Array Inserts 두 개의 지표(불행히도 이 두 개의 유용한 지표는 11g에서 추가된 것입니다)를 잘 해석하시면 Array Insert가 미친 영향을 완벽하게 해석할 수 있습니다. 단, 티팩 자체가 발생시키는 Array Insert가 100여회 정도된다는 것을 고려해서 해석해야 합니다.
티팩이 해주는게 고작 이것이냐고 비난하지 마시기 바랍니다. 티팩이 하고자 하는 것은 성능 트러블슈팅을 위해 필요한 기본적인 데이터를 자동으로 수집하고 적절히 리포트해주는 것일 뿐, 결국 최종 해석은 사람의 몫입니다.
중요한 것은 데이터에 기반한 과학적인 분석을 하느냐 아니면 이거 아니면 저거 다 찔러보는 방식의 분석을 하느냐일 것입니다.
- TPACK 권한 부여
CREATE PUBLIC SYNONYM TPACK FOR TPACK.TPACK; |
오라클 Table/Index Analyze 통계 확인 및 실행방법
출처 : http://jangpd007.tistory.com/248
DBMS_STATS.GATHER_TABLE_STATS
참고 : http://blog.naver.com/PostView.nhn?blogId=tyboss&logNo=70153024309
http://egloos.zum.com/bosoa/v/1402860
http://m.blog.daum.net/ryaniya/277
ANALYZE는 인덱스, 테이블, 클러스터의 통계정보를 생성 한다.
ANALYZE가 생성한 통계정보들은 비용기준(Cost-based)의 옵티마이저가 가장 효율적인 실행계획을 수립하기 위해 최소비용을 계산할 때 사용 된다.
각 오브젝트의 구조를 확인하는 것과 체인(Chain) 생성 여부를 확인할 수 있으므로 시스템의 저장공간 관리를 도와준다.
object-clause : TABLE, INDEX, CLUSTER중에서 해당하는 오브젝트를 기술하고 처리할 오브젝트 명을 기술 한다.
operation : operation 옵션에는 다음 3가지중 한가지 기능을 선택할 수 있다.
주기적인 ANALYZE 작업을 수행 시켜 주어야 한다.
테이블을 재생성 하거나, 새로 클러스터링을 한 경우, 인덱스를 추가하거나 재생성한 경우, 다량의 데이터를 SQL이나 배치 애플리케이션을 통해 작업한 경우 ANALYZE를 수행 시켜 주는 것이 좋다.
사용자는 USER_TABLES, USER_COLUMNS, USER_INDEXS, USER_CLUSTER 등의 자료사전 뷰를 통해 정보를 확인할 수 있다
테이블을 ANALYZE 시킨다면 거기에 따르는 인덱스들도 같이 실시하는 것이 좋다.
오 라클에서는 20,000건 이하의 행수를 가진 데이터에 대해서는 COMPUTE STATISTICS절의 사용을 권장하며 20,000건 이상되는 경우에는 ESTIMATE STATISTICS절의 사용을 권장하고 있다. 또한, 통계정보의 분석은비 일과시간에 수행하는게 원칙이며 일과 시간에 수행해야 하는 경우라면 ESTIMATE STATISTICS절의 사용을 권장한다.
특정 column에 대한 data 분포 수집
SQL> ANALYZE TABLE emp COMPUTE STATISTICS FOR ALL INDEXED COLUMNS;
SQL> SELECT NUM_ROWS
, BLOCKS
, EMPTY_BLOCKS
, AVG_SPACE
, CHAIN_CNT
, AVG_ROW_LEN
, SAMPLE_SIZE
, LAST_ANALYZED
FROM USER_TABLES
WHERE TABLE_NAME = 'CMS_CATEGORY';
SQL> SELECT NUM_DISTINCT
, DENSITY
, LOW_VALUE
, HIGH_VALUE
, LAST_ANALYZED
, COLUMN_NAME
FROM USER_TAB_COL_STATISTICS
WHERE TABLE_NAME = 'CMS_CATEGORY';
1-1. 테이블 통계정보
SELECT TABLE_NAME
, BLOCKS -- 해당 데이터가 저장되어 있는 블록 수.
, NUM_ROWS -- 데이터 행 수.
, AVG_ROW_LEN -- 하나의 행의 평균 길이.
, TO_CHAR( LAST_ANALYZED, 'YYYYMMDD' )
FROM USER_TABLES
[WHERE TABLE_NAME = '테이블명']
1-2. 테이블 통계정보
SELECT TABLE_NAME
, COLUMN_NAME -- 컬럼명
, LOW_VALUE -- 해당 컬럼에 저장되어 있는 최소값.
, HIGH_VALUE -- 해당 컬럼에 저장되어 있는 최대값.
, NUM_DISTINCT -- 유일한 값의 수. (히스토그램 기준)
FROM USER_TAB_COLUMNS
[WHERE TABLE_NAME = '테이블명']
2. 인덱스 통계정보SELECT INDEX_NAME
, BLEVEL -- 인덱스의 깊미(Depth)
, LEAF_BLOCKS -- 리프 블록의 수.
, DISTINCT_KEYS -- 인덱스 컬럼의 유일한 값의 수.
, CLUSTERING_FACTOR -- 조건을 만족하는 데이터를 검색할 때 인덱스 키 값이 각 블록에 얼마나 잘 분산 저장되어 있는지를 나타내는 정도.
, NUM_ROWS -- 전체 행수.
, TO_CHAR( LAST_ANALYZED, 'YYYYMMDD' )
FROM USER_INDEXESex) SELECT TABLE_NAME
, NUM_ROWS
, TO_CHAR( LAST_ANALYZED, 'YYYYMMDD' )
FROM USER_TABLES;TABLE_NAME NUM_ROWS TO_CHAR(
------------------------------ ---------- --------
ABS_TYPE 38 20040101ANNIVERS 183 20040101
APPRFLDRHISTORY 570 20040101
APPRFOLDER 16885 20040101
APPRFOLDER_ERR 3670 20040101
APPRFORM 359 20040101
.
.
.
USR_INFO_ADMIN 0 20040101
VAR_DEPT_INFO 0 20040101
VIEW_TYPE 0 20040101
WASTEBOX 0 20040101
ZIP_CODE 44195 20040101252 rows selected.※ 참고 : desc user_tables 에서 보통 num_rows 로도 확인 가능[특정 Table만 Analyze 하는 방법]ANALYZE TABLE DOCUMENT COMPUTE STATISTICSex) DOCUMENT Table 만 AnalyzeANALYZE INDEX XPKDOCBOX COMPUTE STATISTICSex) XPKDOCBOX Index 만 Analyze[전체 Table Analyze 하는 간단한 방법]1. vi analyze_all.sql
SELECT 'analyze table || table_name || estimate statistics;' FROM USER_TABLES2. @analyze_all.sql3. set heading off
set echo off
set feedback off
set pagesize 300 (line 이 300 미만일 경우)
spool analyze_table.sql
/
spool off4. vi analyze_table.sql
필요없는 Line 제거 및 정리5. @analyze_table.sql
[전체 Index Analyze 하는 간단한 방법]1. vi analyze_all.sql
SELECT 'analyze index || index_name || estimate statistics;' FROM USER_INDEXES2. @analyze_all.sql3. set heading off
set echo off
set feedback off
set pagesize 300 (line 이 300 미만일 경우)
spool analyze_index.sql
/
spool off4. vi analyze_index.sql
필요없는 Line 제거 및 정리5. @analyze_index.sql
===========================================================================================================================
===========================================================================================================================
출처 : http://blog.naver.com/vxxv122?Redirect=Log&logNo=130128144052
정의
→ 비용기반 옵티마이저에서 통계정보를 모아주기 위한 튜닝 도구.
테이블과 인덱스, 클러스터, 컬럼에 대한 통계정보를 수집.
권한
→ Analyze Any 시스템 권한
통계 수집
1 . 테이블
→ Analyze Table 테이블명 Compute Statistics;
* Row수, 사용된 Block수, 사용안된 Block수, 사용가능한 평균공간, 변경된 Row수, 컬럼당 distinct 값수
컬럼당 두번째로 가장 작은 값, 컬럼당 두번째로 가장 큰 값
(질문) 왜 두번째로 가장 작은값과 큰값을 ?
2 . 인덱스
→ Analyze Index 인덱스명 Estimate Statistics;
* 인덱스 레벨, 레벨 Block수, distinct Key수, Key당 Leaf와 Data Block수 평균, Clustering Factor, 최소 Key 값
최대 Key값
3 . 클러스터
→ Analyze Cluster 클러스터명 Delete Statistics;
* Cluster Key당 길이의 평균
4 . 컬럼
→ Analyze Table 테이블명 Compute Statistics For Table;
→ Analyze Table 테이블명 Compute Statistics For Columns 컬럼명 Size 75;
→ Analyze Table 테이블명 Compute Statistics For All Indexed Columns Size 75;
* 디볼트 버켓 수는 75개
Distinct 한 값의 수, 히스토그램 정보
유효성 검사
→ Analyze Table 테이블명 Validate Structure [Cascade];
* 검사하려는 테이블과 관련된 모든 테이블을 검사하려면 Cascade 옵션 사용.
옵션
1 . Compute
→ 테이블에 저장되어 있는 모든 행을 대상으로 통계정보 수집
2 . Estimate
→ 오라클 서버의 자동화 알고리즘에 의해 데이터를 추출하여 통계정보를 수집
3 . Delete
→ 수집되어 있는 통계정보를 삭제
* 20,000건 이하의 Row는 Compute 권장, 이상은 Estimate 권장.
확인
1 . User_Tables
2 . User_Tab_Columns
3 . User_Indexes, Index_Stats, Index_histogram
4 . User_Cluster
5 . DBA_Analyze_Objects
===========================================================================================================================
===========================================================================================================================
출처 : http://www.oracleclub.com/article/23928
1. 개요
- TABLE, COLUMN, 그리고 INDEX 에 대한 통계 정보를 수집 하게 하는 PROCEDURE
2. SYNTAX
DBMS_STATS.GATHER_TABLE_STATS (OWNNAME VARCHAR2,
TABNAME VARCHAR2,
PARTNAME VARCHAR2 DEFAULT NULL,
ESTIMATE_PERCENT NUMBER DEFAULT TO_ESTIMATE_PERCENT_TYPE
(GET_PARAM('ESTIMATE_PERCENT')),
BLOCK_SAMPLE BOOLEAN DEFAULT FALSE,
METHOD_OPT VARCHAR2 DEFAULT GET_PARAM('METHOD_OPT'),
DEGREE NUMBER DEFAULT TO_DEGREE_TYPE(GET_PARAM('DEGREE')),
GRANULARITY VARCHAR2 DEFAULT GET_PARAM('GRANULARITY'),
CASCADE BOOLEAN DEFAULT TO_CASCADE_TYPE(GET_PARAM('CASCADE')),
STATTAB VARCHAR2 DEFAULT NULL,
STATID VARCHAR2 DEFAULT NULL,
STATOWN VARCHAR2 DEFAULT NULL,
NO_INVALIDATE BOOLEAN DEFAULT TO_NO_INVALIDATE_TYPE (
GET_PARAM('NO_INVALIDATE')),
FORCE BOOLEAN DEFAULT FALSE);
3. PARAMETER 설명
- DBMS_STATS.SET_PARAM 에 의해서 디폴트 파라미터 설정 변경이 가능하다.
- 수동 통계정보 생성 시에 저정을 하지 않았을 때 적용되는 DEFAULT 값에 영향을 미치는 값
=> CASCADE
=> DEGREE
=> ESTIMATE_PERCENT
=> METHOD_OPT
=> NO_INVALIDATE
=> GRANULARITY
- 자동 통계정보(GATHER_STATS_JOB) 시에만 영향을 미친다.
=> AUTOSTATS_TARGET [ AUTO : ORACLE이 자동으로 대상 OBJECT 결정,
ALL : 대상 시스템의 모든 OBJECTS
ORACLE : SYS/SYSTEM OBJECT 만 ]
1) DEFAULT 값 확인
SELECT DBMS_STATS.GET_PARAM('METHOD_OPT') FROM DUAL ;
DBMS_STATS.GET_PARAM('METHOD_OPT')
----------------------------------
FOR ALL COLUMNS SIZE AUTO
2) DEFAULT 값 변경
EXECUTE DBMS_STATS.SET_PARAM('METHOD_OPT', 'FOR ALL COLUMNS SIZE 1') ;
PL/SQL PROCEDURE SUCCESSFULLY COMPLETED.
3) 변경된 DEFAULT 값 확인
SELECT DBMS_STATS.GET_PARAM('METHOD_OPT') FROM DUAL ;
DBMS_STATS.GET_PARAM('METHOD_OPT')
----------------------------------
FOR ALL COLUMNS SIZE 1
Parameter | Description |
OWNNAME | 분석할 테이블 소유자 |
TABNAME | 테이블 이름 |
PARTNAME | 파티션 이름, 지정 하지 않으면 NULL 값 |
ESTIMATE_PERCENT | - 분석할 Row의 Percentage, NULL 이면 Compute(Row 전체) - 유효값은 1/1000000 ~ 100 - 디폴트로, DBMS_STATS.AUTO_SAMPLE_SIZE 에 의해서 최적의 값을 결정 |
BLOCK_SAMPLE | - random block sampling or random row sampling 결정 - random block sampling 이 좀더 효과적이다. - 데이터의 블록 별 분포도가 안좋을 시에는 부적절한 정보 생성 - 디폴트 값이 False로, random row sampling 을 수행한다. |
METHOD_OPT | - Histogram 생성시 사용하는 옵션 |
DEGREE | - 병렬처리 정도 - 디폴트 값은 NULL 이고, CREATE TABLE, ALTER TABLE 시 설정된 DEGREE 값에 의해 정해진다. - AUTO_DEGREE 값은 병렬처리 정도를 자동으로 결정한다. - 이것은 1 or DEFAULT_DEGREE [ Object Size 와 CPU Count 에 의해 결정 ] |
GRANULARITY | - Parition table 에 대한 분석시 사용 => ‘ALL’ : Global, Partition, Subpartition 통계정보 수집 – Parition Table 대상 => ‘AUTO’ : 디폴트 값으로 ,Partition Type 에 따라서 결정 – 일반 Table 대상 => ‘DEFAULT’ : Global, Partition 통계정보 수집, Old Version 과 호환을 위해 사용 => ‘GLOBAL’ : Global 통계정보 수집 => ‘GLOBAL AND PARTITION’ : SubPartition 에 대한 통계정보는 수집되지 않는다. => ‘PARTITION’ : Partition 통계정보 수집 => ‘SUBPARTITION’ : SubPartition 통계정보 수집 |
CASCADE | - 대상 테이블의 인덱스에 대한 통계수집 여부 - 인덱스 통계정보는 병렬처리가 불가능하다. - TRUE : 대상 테이블에 관련된 index 에 대해서 통계정보 수집 |
STATTAB | - 통계수집을 통한 기존 통계정보 Update 전에, 기존에 존재하는 통계정보를 저장할 User Stat Table 을 지정 |
STATID | - Stattab 와 연관된 구분자 값 |
STATOWN | - Stattab 에 지정한 User Stat Table 의 소유자가 다를 경우 지정 |
NO_VALIDATE | - 의존적인 Cursor를 Invalidate 할지 , 안할지 결정 => True : 관련된 Cursor 를 invalidate 하지 않는다. => False : 디폴트 값으로, 관련된 Cursor 를 Invalidate 한다. - Default 로 DBMS_STATS.AUTO_INVALIDATE 값이고, 의미는 DBMS 가 의존적 Cursor를 언제 invalidate 할지 자동으로 결정 - 이때 작용하는 Parameter는 _OPTIMIZER_INVALIDATION_PERIOD 이고, Default 롤 18000 초(5시간) 이다. - 즉, 통계 정보 수집에 의해 통계 정보가 변경된 후 약 5시간에 걸쳐 랜덤한 시점에 해당 Cursor가 실행될 때 invalidation이 발생한다. - 이것을 Auto Invalidation이라고 부른다. - 일정 시간에 걸쳐 랜덤하게 Cursor를 Invalidation함으로써 특정 시점에 Hard Parse가 한꺼번에 몰리는 현상을 피할 수 있다. |
FORCE | - Lock 걸린 Table 에 대해서도 강제로 통계정보 생성 |
4. Test
1) Mission
CASCADE => TRUE
E 인덱스에 대한 통계정보도수집하라.
CASCADE => FALSE
E 인덱스에 대한 통계정보도수집하라.
METHOD_OPT =>'FOR ALL COLUMNS SIZE 1'
E 칼럼(HIGH AND LOW COLUMN VALUE)에 대한 통계정보도 수집하라.
METHOD_OPT =>'FOR COLUMNS'
E컬럼에 대한통계정보를 수집하지 마라
2) Test
2-1) 일반 테이블
SHOW USER
USER IS"SYS"
① SCOTT의 BIG_TABLE 의 전체 테이블과 모드 인덱스를 가지고, 테이블, 칼럼(HIGHAND LOW COLUMN VALUE),
연관 인덱스의 통계정보를 생성한다.( COMPUTE STATISTICS )
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'SCOTT',
TABNAME => 'BIG_TABLE',
CASCADE => TRUE,
METHOD_OPT => 'FOR ALL COLUMNS SIZE 1');
② SCOTT의 BIG_TABLE의 15% ROW를 가지고, 테이블, 칼럼, 연관인덱스의 통계정보를 생성한다.( SAMPLE 15 PERCENT )
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'SCOTT',
TABNAME => 'BIG_TABLE',
CASCADE => TRUE,
ESTIMATE_PERCENT => 15);
③ SCOTT의 BIG_TABLE의 전체 테이블과 모드 인덱스를 가지고, 테이블의 통계정보를 수집하라.
인덱스와 칼럼에 대한 통계정보는 제외
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'SCOTT',
TABNAME => 'BIG_TABLE',
CASCADE => FALSE,
METHOD_OPT => 'FOR COLUMNS');
④ SCOTT의 BIG_TABLE의 전체 테이블과 모드 인덱스를 가지고, 테이블과인덱스에 대한 통계정보를 수집하라.
칼럼에 대한 통계정보는 제외
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'SCOTT',
TABNAME => 'BIG_TABLE',
CASCADE => TRUE,
METHOD_OPT => 'FOR COLUMNS');
⑤ SCOTT의 BIG_TABLE의 전체 테이블과 모드 인덱스를 가지고, 테이블과 컬럼(NO HISTOGRAM),
그리고 인덱스에 대한 통계정보를 수집하라.
잠시 후에 인덱스 칼럼들의 HISTOGRAM 통계정보를 수집하라.
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'SCOTT',
TABNAME => 'BIG_TABLE',
CASCADE => TRUE);
잠시 후에..
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME =>'SCOTT',
TABNAME => 'BIG_TABLE',
CASCADE => TRUE,
METHOD_OPT => 'FOR ALL INDEXED COLUMNSSIZE 1');
⑥ SCOTT 의 BIG_TABLE 의 전체 테이블과 모드 인덱스를 가지고, 테이블과 인덱스칼럼(ONLY HIGH AND LOW )에
대한 통계정보를 수집하라. 인덱스에 대한 통계정보는수집하지 마라.
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'SCOTT',
TABNAME => 'BIG_TABLE',
CASCADE => FALSE,
METHOD_OPT => 'FOR ALL INDEXED COLUMNSSIZE 1');
2-2) PARTITIONTABLE 의 경우
① 추가적으로 GRANULARITY 정보를 'ALL', 'AUTO', 'PARITION', 'GLOBAL AND PARTITION', 'GLOBAL', 'SUBPARTITION'을
통해서 통계수집 대상 TABLE SEGMENT를 선정 가능하다.
② 참고
- LOCK VS DBMS_STATS.GATHER_TABLE_STATS
: DML 이 LOCK 이 발생 하여도 GATHER_TABLE_STATS 는 정상적으로 진행된다.
BEGIN
FOR I IN 1001 .. 5000 LOOP
INSERT INTO CHECK_LOCK VALUES ( I , I , 'LOCK');
END LOOP ;
END ;
/
- @CHECK_USER_LOCK.SQL
ENTER VALUE FOR USER_NAME: SCOTT10
OLD 46: AND B.USERNAME =UPPER('&USER_NAME')
NEW 46: AND B.USERNAME =UPPER('SCOTT10')
USERNAME SID LOCK_TYPE MODE_HELD MODE_REQUE LOCK_ID1 LOCK_ID2
---------- ---- --------------- ----------- ---------- -------- --------
SCOTT10 151 DML ROW-X (SX) NONE 51782 0
SCOTT10 151 TRANSACTION EXCLUSIVE NONE 131077 307
- EXECUTE DBMS_STATS.GATHER_TABLE_STATS(OWNNAME =>'SCOTT10',TABNAME => 'CHECK_LOCK');
==> DML LOCK 과는 무관하게 진행 된다.
========================================================================
ANALYZE 와 DBMS_STATS 의 수집정보 차이
참고 : http://jedah.tistory.com/entry/ANALYZE-%EC%99%80-DBMSSTATS-%EC%9D%98-%EC%88%98%EC%A7%91%EC%A0%95%EB%B3%B4-%EC%B0%A8%EC%9D%B4
=================================================================================
index rebuild 작업
출처 : http://aozjffl.tistory.com/285
질문 :
index에 관해서 공부를 하다가 궁금한 점이 있어 이렇게 질문을 등록합니다.
테이블에 데이터가 자주 들락날락해서 delete된 데이터의 index가 그대로 남아있어, 필요이상으로 많은 공간을 차지할 때 한다는 것을 알고 있습니다.
그런데, 이렇게 필요이상으로 index가 공간을 많이 차지한다는 것을 어떻게 알 수 있을까요?
답변2 :
답변2도 답변 1과 같은 내용이지만 스크립트를 사용함으로써, 한번에 여러개의 rebuild 대상 index를 찾을 수 있다는 장점이 있다.
결과 정보를 휘발성으로 저장하는데, 그 결과를 통해서 rebuild 대상을 체크할 수 있음.
주의할 점은 아래의 쿼리 실행시 Lock이 발생하므로, 업무시간 이외에 할 것을 강추함.
참고 : http://blog.naver.com/PostView.nhn?blogId=omg92&logNo=60137609376
ERwin 재설치(Event Log Watch 서비스 또 기동 안되는 현상 -> ERwin 기동 안됨)
1. 프로그램 추가삭제에서 ERwin을 제거 한다.
2. CA_LIC 폴더까지 제거한다. (lic98_uninstaller.zip 활용)
A. C:\\Program Files\\CA\\SharedComponents\\CA_LIC 폴더에 lic98_unintaller.zip파일을 압축 해제 한다.
B. rmlicense.bat 파일을 실행한다.
C. CA_LIC 폴더가 삭제 된다.
3. Registry에서 Event Log Watch로 검색 하여 값을 삭제 한다.
4. Vista인 경우 제어판 -> 사용자계정 -> 사용자 계정 컨트롤 사용 안 함으로 체크 한다.
5. Erwin을 재설치 한다.
6. 만약 서비스에 Event Log Watch의 서비스 실행 속성이 수동으로 되어 있으면 자동으로 수정한다.
7. 시리얼 키 등록이 안된다면 Registry에서 해당 시리얼 키로 검색하여 값을 삭제 한다.
1. erwin에서 Tools -> Data Browser 선택
2. Data Browser에서 Reports -> Open Reports 클릭 후 첨부파일 (Report4FCR_Domain.erp) 선택
* 새로운 Report 만들 경우
- File -> New Report
- Name에 report 이름을 적고 Physical 선택 후 Category는 Column 선택
- 왼쪽 트리에서 Column -> Table -> Name 선택, Column -> Name, Column -> Datatype 선택
3. 왼쪽 트리에서 Table Reports -> reportTableDef2 더블 클릭 또는 마우스 우클릭 후 excute.. 클릭
4. 하위 트리 메뉴가 생성되는데 마우스 우클릭 후 Export... 클릭하면 export 메뉴가 나옴
- Export : csv로 선택
- Presentation : Tabuilar - 중복되는 결과값은 제외
Tabular with duplicates - 중복과 상관없이 모두 출력
ODBC 드라이버 다운로드 URL : http://technet.tmaxsoft.com
Tibero5 32Bit ODBC 드라이버
tbodbc_driver_installer_5_32.exe
Tibero5 64Bit ODBC 드라이버
tbodbc_driver_installer_5_64.exe
1. ODBC 드라이버 다운로드
1) tmax technet 사이트에 접속 후 다운로드 > 데이터베이스 > Tibero 메뉴에서 해당 버전 다운로드를 클릭한다.
2) 최하단의 OS를 선택하면 zip 파일로 된 파일을 다운로드 한다.
3) 다운로드 받은 파일을 압축 해제하고 binary 폴더 안에 tibero5-bin-S1410-windows32-84458-opt-tested.tar.gz 파일을 압축 해제한다.
4) ODBC 32bit 용
드라이버 Installer : binary\tibero5-bin-S1410-windows32-84458-opt-tested.tar\tibero5-bin-S1410-windows32-84458-opt-tested\tibero5\bin\tbodbc_driver_installer_5_32.exe
드라이버 DLL : binary\tibero5-bin-S1410-windows32-84458-opt-tested.tar\tibero5-bin-S1410-windows32-84458-opt-tested\tibero5\bin\libtbcli.dll
5) ODBC 64bit용
드라이버 Installer : binary\tibero5-bin-S1410-windows32-84458-opt-tested.tar\tibero5-bin-S1410-windows32-84458-opt-tested\tibero5\client\win64\bin\tbodbc_driver_installer_5_64.exe
드라이버 DLL : binary\tibero5-bin-S1410-windows32-84458-opt-tested.tar\tibero5-bin-S1410-windows32-84458-opt-tested\tibero5\client\win64\lib\libtbcli.dll
2. ODBC 드라이버 설치
1) C:\Program Files\Tibero 경로에 tbodbc_driver_installer_5_32.exe 복사
2) C:\Program Files\Tibero\bin 경로에 libtbcli.dll 복사
3) 환경변수 추가
변수이름 : TB_HOME
변수값 : C:\Program Files\Tibero
4) cmd 에서 명령어 실행
명령어 : C:\Program Files\Tibero\tbodbc_driver_installer_5_32.exe -i
3. ODBC 드라이버 확인
※ Windows가 64bit 이면서 ODBC는 32bit로 설치한 경우에는 odbc 추가 시 32bit용 odbc 관리툴을 실행해야 한다.
실행 > odbcad32 실행하면 OS 버전에 맞는 관리툴이 기본적으로 실행된다.
- 32bit ODBC 관리툴 실행 : C:\Windows\SysWOW64\odbcad32.exe
- 64bit ODBC 관리툴 실행 : C:\Windows\System32\odbcad32.exe