Oracle/기타2009. 11. 15. 00:51

성능 문제에 대한 정확한 이해는 용어에 대한 정확한 이해에서부터 온다

인간의 생각하는 능력이 언어라는 것을 만들었지만, 거꾸로 언어가 인간의 사고 능력을 지배하게 되죠.

오라클 성능 세계에서도 마찬가지입니다. 용어에 대한 정확한 이해가 없으면 문제를 100% 이해할 수도 없을뿐더러 잘못된 지식을 믿게 됩니다. 예를 들어 볼까요?

  • Explain Plan과 Execution Plan의 차이를 설명할 수 있습니까?
  • Scan과 Lookup의 차이는 무엇입니까?
  • Histogram의 의미는 무엇입니까?
  • Lock과 Enqueue의 의미를 구분할 수 있습니까?
  • SQL문과 Cursor의 차이를 설명할 수 있습니까?
  • Event라는 용어가 언제 쓰이는지 설명할 수 있습니까?
용어을 100% 정확하게 설명할 수 있다면 그 자체로도 성능 문제에 대한 상당한 통찰력을 가지고 있다고 볼 수 있습니다.





출처 : http://ukja.tistory.com/282

'Oracle > 기타' 카테고리의 다른 글

ROWNUM  (2) 2009.11.17
Query의 성능 측정의 기준  (0) 2009.11.16
DBA와 개발자가 알고 있어야 하는 오라클의 새로운 기능(oracle database 11g)  (0) 2009.11.15
Binding 변수 확인하기  (0) 2009.11.13
metadata  (0) 2009.11.11
Posted by 자수성가한 부자
Oracle/기타2009. 11. 15. 00:10

'Oracle > 기타' 카테고리의 다른 글

Query의 성능 측정의 기준  (0) 2009.11.16
[펌]오라클 성능에 대한 짧은 생각 #12  (0) 2009.11.15
Binding 변수 확인하기  (0) 2009.11.13
metadata  (0) 2009.11.11
난수 발생(dbms_random package)  (0) 2009.11.09
Posted by 자수성가한 부자
Oracle/SQL2009. 11. 14. 23:22
connect by
start with

자료의 구조가 계층적으로 이루어진 경우
상위자료에서부터 하위자료로의 자료 전개 및
하위자료에서 상위자료로의 역 전개를 위하여 사용되는 SELECT 형식이다.


예)
오라클에서 제공하는 샘플테이블이 있는 경우 사용 가능한 예제


-- Top-down 방식

select level, lpad(empno, level*4, '_') as empno1, e.*
from emp e
start with empno = 7839
connect by PRIOR empno = mgr;


LEVEL EMPNO1 EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
1 7839 7839 KING PRESIDENT   81/11/17 5000   10
2 ____7566 7566 JONES MANAGER 7839 81/04/02 2975   20
3 ________7788 7788 SCOTT ANALYST 7566 82/12/09 3000   20
4 ____________7876 7876 ADAMS CLERK 7788 83/01/12 1100   20
3 ________7902 7902 FORD ANALYST 7566 81/12/03 3000   20
4 ____________7369 7369 SMITH CLERK 7902 80/12/17 800   20
2 ____7698 7698 BLAKE MANAGER 7839 81/05/01 2850   30
3 ________7499 7499 ALLEN SALESMAN 7698 81/02/20 1600 300 30
3 ________7521 7521 WARD SALESMAN 7698 81/02/22 1250 500 30
3 ________7654 7654 MARTIN SALESMAN 7698 81/09/28 1250 1400 30
3 ________7844 7844 TURNER SALESMAN 7698 81/09/08 1500 0 30
3 ________7900 7900 JAMES CLERK 7698 81/12/03 950   30
2 ____7782 7782 CLARK MANAGER 7839 81/06/09 2450   10
3 ________7934 7934 MILLER CLERK 7782 82/01/23 1300   10


-- Bottom-up방식

select level, lpad(empno, level*4, '_') as empno1, e.*
from emp e
start with empno = 7369
connect by empno = PRIOR mgr;

LEVEL EMPNO1 EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
1 7369 7369 SMITH CLERK 7902 80/12/17 800   20
2 ____7902 7902 FORD ANALYST 7566 81/12/03 3000   20
3 ________7566 7566 JONES MANAGER 7839 81/04/02 2975   20
4 ____________7839 7839 KING PRESIDENT   81/11/17 5000   10


-- SIBLING 키워드(계층형 구조의 order by,  같은 층 끼리만 비교함)

select level, lpad(empno, level*4, '_') as empno1, ename, sal, job, sys_connect_by_path(ename, '/')
from emp e
start with empno = 7839
connect by PRIOR empno = mgr
order SIBLINGS by sal desc;

LEVEL EMPNO1 ENAME SAL JOB SYS_CONNECT_BY_PATH(ENAME,'/')
1 7839 KING 5000 PRESIDENT /KING
2 ____7566 JONES 2975 MANAGER /KING/JONES
3 ________7788 SCOTT 3000 ANALYST /KING/JONES/SCOTT
4 ____________7876 ADAMS 1100 CLERK /KING/JONES/SCOTT/ADAMS
3 ________7902 FORD 3000 ANALYST /KING/JONES/FORD
4 ____________7369 SMITH 800 CLERK /KING/JONES/FORD/SMITH
2 ____7698 BLAKE 2850 MANAGER /KING/BLAKE
3 ________7499 ALLEN 1600 SALESMAN /KING/BLAKE/ALLEN
3 ________7844 TURNER 1500 SALESMAN /KING/BLAKE/TURNER
3 ________7521 WARD 1250 SALESMAN /KING/BLAKE/WARD
3 ________7654 MARTIN 1250 SALESMAN /KING/BLAKE/MARTIN
3 ________7900 JAMES 950 CLERK /KING/BLAKE/JAMES
2 ____7782 CLARK 2450 MANAGER /KING/CLARK
3 ________7934 MILLER 1300 CLERK /KING/CLARK/MILLER



계층형 쿼리 관련 함수

-- sys_connect_by_path() 
    : 계층형 구조의 전체 경로를 나타냄, 
     두번째 인수인 구분자는 열값의 일부의 문자로는 사용불가.
     아래의 쿼리를 예로 들면 ename중에 /가 들어가는 이름이 있으면 /는 사용 불가


select level, lpad(empno, level*4, '_') as empno1, ename, sal, job, sys_connect_by_path(ename, '/')
from emp e
start with empno = 7839
connect by PRIOR empno = mgr;
LEVEL EMPNO1 ENAME SAL JOB SYS_CONNECT_BY_PATH(ENAME,'/')
1 7839 KING 5000 PRESIDENT /KING
2 ____7566 JONES 2975 MANAGER /KING/JONES
3 ________7788 SCOTT 3000 ANALYST /KING/JONES/SCOTT
4 ____________7876 ADAMS 1100 CLERK /KING/JONES/SCOTT/ADAMS
3 ________7902 FORD 3000 ANALYST /KING/JONES/FORD
4 ____________7369 SMITH 800 CLERK /KING/JONES/FORD/SMITH
2 ____7698 BLAKE 2850 MANAGER /KING/BLAKE
3 ________7499 ALLEN 1600 SALESMAN /KING/BLAKE/ALLEN
3 ________7521 WARD 1250 SALESMAN /KING/BLAKE/WARD
3 ________7654 MARTIN 1250 SALESMAN /KING/BLAKE/MARTIN
3 ________7844 TURNER 1500 SALESMAN /KING/BLAKE/TURNER
3 ________7900 JAMES 950 CLERK /KING/BLAKE/JAMES
2 ____7782 CLARK 2450 MANAGER /KING/CLARK
3 ________7934 MILLER 1300 CLERK /KING/CLARK/MILLER


-- connect_by_root() : 상관관계 쿼리에서 level이 0인 최상위 로우의 정보를 얻어올 수 있다.

SELECT LPAD('   ', 4*(LEVEL-1)) || ename ename, empno, 
CONNECT_BY_ROOT  empno "Root empno", level
FROM emp
START WITH job='PRESIDENT'
CONNECT BY PRIOR empno=mgr;

ENAME EMPNO Root empno LEVEL
KING 7839 7839 1
JONES 7566 7839 2
SCOTT 7788 7839 3
ADAMS 7876 7839 4
FORD 7902 7839 3
SMITH 7369 7839 4
BLAKE 7698 7839 2
ALLEN 7499 7839 3
WARD 7521 7839 3
MARTIN 7654 7839 3
TURNER 7844 7839 3
JAMES 7900 7839 3
CLARK 7782 7839 2
MILLER 7934 7839 3



-- connect_by_isleaf() : 계층형 구조에서 로우의 최하위 레벨 여부를 반환한다.

SELECT LPAD('', 4*(LEVEL-1)) || ename ename, empno, 
CONNECT_BY_ISLEAF "leaf", level
FROM emp
START WITH job='PRESIDENT'
CONNECT BY NOCYCLE  PRIOR empno=mgr;


ENAME EMPNO leaf LEVEL
KING 7839 0 1
JONES 7566 0 2
SCOTT 7788 0 3
ADAMS 7876 1 4
FORD 7902 0 3
SMITH 7369 1 4
BLAKE 7698 0 2
ALLEN 7499 1 3
WARD 7521 1 3
MARTIN 7654 1 3
TURNER 7844 1 3
JAMES 7900 1 3
CLARK 7782 0 2
MILLER 7934 1 3


참조 : http://www.oracleclub.com/lecture/1903

'Oracle > SQL' 카테고리의 다른 글

index를 사용하여 쿼리를 튜닝해보자  (0) 2009.11.16
WITH .. AS  (0) 2009.11.15
입력 소요시간 비교(insert 여러건 vs connect by 이용)  (0) 2009.11.11
Merge  (0) 2009.11.09
분석함수(Anaylitic Function)  (0) 2009.11.09
Posted by 자수성가한 부자
Oracle/Admin2009. 11. 14. 20:27

'Oracle > Admin' 카테고리의 다른 글

Query 실행순서(select)  (0) 2009.11.19
Oracle Architecture  (0) 2009.11.18
isql*plus에서 dba유저 로그인 설정  (0) 2009.11.16
SGA  (0) 2009.11.10
리스너에 여러 포트를 사용하고 싶을 때 추가 방법  (0) 2009.10.21
Posted by 자수성가한 부자
Oracle/기타2009. 11. 13. 17:25

시스템 유저로 접속

conn / as sysdba

V$SQL_BIND_DATA뷰를 확인(데이터가 많으므로 isqlplus에서 확인할 것)

참고 : http://download.oracle.com/docs/cd/B19306_01/server.102/b14237/dynviews_2115.htm#i1417482

Posted by 자수성가한 부자
Oracle/PL_SQL2009. 11. 13. 14:52

오라클에서의 에러는 다음과 같이 두 종류가 있다.
- Syntax Error
- Runtime Error (Exception) 

Every Oracle error has a number, but exceptions must be handled by name
모든 오라클 에러는 번호가 있지만, Exception은 반드시 이름을 가지고 처리한다.


   ○ Oracle defined error : Predefined exception                   1.When name then
                                      Non-predefined exception            2.When others then
                                                                                       3.After naming exception
   ○ User defined error                                                       4.create user defined exception
                                                                                       5.DBMS_STANDARD.RAISE_APPLICATION_ERROR


1번(Predefined exception)과 2번(Non-predefined exception) 예제

오라클의 대표적인 predefined exception 들이다.

NO_DATA_FOUND       리턴되는 행이 없을 때
TOO_MANY_ROWS     많은 행을 리턴할 때
INVALID_CURSOR       유효하지 않은 커서
ZERO_DIVIDE             0으로 나눌때
DUP_VAL_ON_INDEX  중복된 값을 입력시

drop table t1 purge;
create table t1 (col1 number constraint t1_no_nn not null);

create or replace procedure p1
          (p_no number,
           p_no2 number)
is
    v_no number;
begin
    v_no := 100/p_no;
    dbms_output.put_line(v_no);

    insert into t1 values (p_no2);
       exception
           when ZERO_DIVIDE then          -- predefined exception
                dbms_output.put_line('Your program attempts to divide a number by zero.');
           when others then                     -- non predefined exception
                dbms_output.put_line('Your program attempts to insert to null value');
end;
/

exec p1 (10, 1);
exec p1(10, 0);                --> ZERO_DIVIDE exception발생
exec p1 (10, NULL);        --> ORA-01400 상황




3번,Non-predefined exception(Atfer naming exception)

PRAGMA : 컴파일러에 대한 슈도명령어,
패키지에 선언해 두면 모든 plsql에서 exception으로 처리할 수 있다.

프로시져 내에서 Exception 정의

테이블 삭제후 생성

drop table t1 purge;
create table t1 (col1 number constraint t1_no_nn not null);



create or replace procedure p1
 (p_no number)
is
 e_null_insert exception;
 pragma exception_init(e_null_insert, -1400);

 v_no number;
begin
 insert into t1 values (p_no);
exception
 when e_null_insert then
  dbms_output.put_line('Your program attempts to insert a null into t1.col1');
end;
/

exec p1(null)     --> ORA-01400



Excetion을 package로 만듬

create or replace package exception_package
is
  e_null_insert exception;
  pragma exception_init(e_null_insert, -1400);
end;
/


 

create or replace procedure p1
  (p_no  number)
is
  v_no number;
begin
  insert into t1 values (p_no);
exception
  when exception_package.e_null_insert then
    dbms_output.put_line('Your program attempts to insert a null into hr30.t1.col1');
end;
/

exec p1 (NULL)




4번 사용자 정의 예외(User defined error)예제

먼저 아래의 SQL로 테이블의 상황을 보여주면

select sum(salary), department_id
     from employees
     group by department_id
     order by department_id

SUM(SALARY) DEPARTMENT_ID
4400 10
19000 20
17500 50
19200 60
30100 80
58000 90
20300 110
7000


create or replace procedure p2
 (p_dept_id number)
is
 v_sum_salary number;
 e1       exception;
begin
 select sum(salary) into v_sum_salary
 from employees
 where department_id = p_dept_id;

 if v_sum_salary < 20000 then
  raise e1;                         -- 예외(exception)를 발생시킨다.
 end if;

dbms_output.put_line(v_sum_salary);

exception
 when e1 then
  dbms_output.put_line('The total salary is too low!');

end;
/

exec p2(90);     --> 정상처리됨.
exec p2(10);     --> department_id 10의 sum(salary)가 4400으로 20000보다 적으므로 예외 발생




5.DBMS_STANDARD.RAISE_APPLICATION_ERROR예제

마치 oracle의 non-predicated exception이 발생한 것처럼 처리

declare
 v_sum_salary number;
 e1 exception;
begin
 select sum(salary) into v_sum_salary
 from employees
 where department_id = 20;

 if v_sum_salary < 20000 then
  dbms_standard.raise_application_error(-20001, 'too low');
 end if;
end;
/

 

declare
 v_sum_salary number;
 e1 exception;
 pragma exception_init(e1, -20001);
begin
 select sum(salary) into v_sum_salary
 from employees
 where department_id = 20;


 if v_sum_salary < 20000 then
  dbms_standard.raise_application_error(-20001, 'too low');   /* raise e1; */
 end if;

 dbms_output.put_line(v_sum_salary);
exception
 when e1 then
  dbms_output.put_line('exception arised!');
end;
/



오라클home\RDBMS\ADMIN의 아래에
stdspec.sql
predefined exception로 검색하면 exception이 선언되어 있음

참조 : http://download.oracle.com/docs/cd/B10501_01/appdev.920/a96624/07_errs.htm#784
관련 질문 : http://kin.naver.com/detail/detail.php?d1id=1&dir_id=10110&docid=1105489&qb=7ZaJ7Jq07J20IOyeiOq4sOulvCBleGNlcHRpb24=&enc=utf8&section=kin&rank=10&sort=0&spq=0

'Oracle > PL_SQL' 카테고리의 다른 글

테이블 변경시 관련 procedure, function, package 확인  (0) 2009.11.16
wrap pld  (0) 2009.11.16
Cursor  (0) 2009.11.12
PLS_INTEGER  (1) 2009.11.12
Bind Variables(Host Variable)  (0) 2009.11.12
Posted by 자수성가한 부자
Oracle/PL_SQL2009. 11. 12. 22:36

커서(cursor)란?

커서는 DML(Select Update) 구문을 위한 메모리에 대한 핸들(이름 또는 포인터) 이다.
A cursor is a handle (pointer) in memory for a DML operation (Select Update).

기본적으로 sql구문을 실행하는 오라클에 의해 할당된 지역이다. 오라클은 Single row query는 암시적 커서(Implicit)를 사용하고, Multiple row query는 명시적커서(explicit)를 사용한다.


그리고 각 커서는 속성을 갖는데, 4가지가 있다.

%FOUND : 가장 최근의 FETCH가 행을 리턴하는지 판단. Boolean 타입

%ISOPEN : 커서가 열렸는지 판단함. Boolean 타입

%NOTFOUND : 가장 최근의 FETCH가 행을 리턴하지 않는지 판단. Boolean 타입

%ROWCOUNT : 리턴되는 행의 갯수가 얼마인지 판단. Number타입

 

암시적 커서

SQL> VARIABLE rows_deleted VARCHAR2(30)
SQL>

DECLARE
    empno employees.employee_id%TYPE := 176;
BEGIN
    DELETE FROM employees
    WHERE employee_id = empno;
    :rows_deleted := (SQL%ROWCOUNT ||' row deleted.');
END;
/
SQL> PRINT rows_deleted

 

명시적 커서

DECLARE
    CURSOR emp_cursor is
        select * from emp
        order by sal desc;
 
        emp_rec emp_cursor%rowtype;
BEGIN
    if emp_cursor%isopen = false then
        OPEN emp_cursor;
    end if;

    LOOP
        FETCH emp_cursor INTO emp_rec;

        exit when emp_cursor%notfound or emp_cursor%rowcount > 3;

        dbms_output.put_line(emp_rec.ename||' '||emp_rec.sal);   
    END LOOP;

    CLOSE emp_cursor;
END;
/


DECLARE
    CURSOR emp_cursor IS
        select * from emp
        order by sal desc;
BEGIN
    for emp_rec in emp_cursor loop
        exit when emp_cursor%notfound or emp_cursor%rowcount > 3;
    dbms_output.put_line(emp_rec.ename||' '||emp_rec.sal); 
    end loop;
END;
/

 

 

 

'Oracle > PL_SQL' 카테고리의 다른 글

테이블 변경시 관련 procedure, function, package 확인  (0) 2009.11.16
wrap pld  (0) 2009.11.16
Exception handling  (0) 2009.11.13
PLS_INTEGER  (1) 2009.11.12
Bind Variables(Host Variable)  (0) 2009.11.12
Posted by 자수성가한 부자
Oracle/PL_SQL2009. 11. 12. 09:22

PLS_INTEGER은 PL/SQL에서 사용가능한 데이터 타입입니다.
 
그런데 왜 이러한 데이터 타입이 나오게 되었을까요??

그건 바로 처리속도 때문입니다. 빠르게 된 이유로는 BINARY_INTEGER와 NUMBER 타입이 "라이브러리를 이용" 하여 수치 연산을 하는 반면, PLS_INTEGER는 실제 기계적인 연산(Machine arithmetic)을 수행하기 때문이라고 하네요.

-2147483647과 2147483647 사이의 signed 정수에 대한 기본형으로 정의 할 수 있습니다.


원문)
You use the PLS_INTEGER datatype to store signed integers. Its magnitude range is -2147483648 to 2147483647, represented in 32 bits. PLS_INTEGER values require less storage than NUMBER values and NUMBER subtypes. Also, PLS_INTEGER operations use hardware arithmetic, so they are faster than NUMBER operations, which use library arithmetic. For efficiency, use PLS_INTEGER for all calculations that fall within its magnitude range. For calculations outside the range of PLS_INTEGER, you can use the INTEGER datatype.

출처 : http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14261/datatypes.htm#i10726


그럼, 실제로 PLS_INTEGER이 BINARY_INTEGER나 NUMBER보다 연산을 빨리 수행하는지 테스트 해볼까요??

실제 비교를 하기 전에 똑같은 환경을 만들어 줍니다.

set timing on                     - 소요시간을 화면에 출력해주기 위해 설정

drop table t1 purge;

create table t1   
(col1 number);


BINARY_INTEGER

declare
    i number:=1;
    j number:=2;
    k number:=3;
    total number:=0;
begin
    for l in 1..100000000 loop
        total := total+i+j+k;
    end loop;
    dbms_output.put_line(total);
end;
/

소요시간 : 00:00:18.65


또 같은 환경을 만들어줍니다.

drop table t1 purge;

create table t1
(col1 number);

NUMBER

declare
    i binary_integer:=1;
    j binary_integer:=2;
    k binary_integer:=3;
    total binary_integer:=0;
begin
    for l in 1..100000000 loop
        total := total+i+j+k;
    end loop;
    dbms_output.put_line(total);
end;
/

소요시간 : 00:00:06.84

같은 환경을 만들어 줍니다.

drop table t1 purge;

create table t1
(col1 number);


PLS_INTERGER

declare
    i pls_integer:=1;
    j pls_integer:=2;
    k pls_integer:=3;
    total pls_integer:=0;
begin
    for l in 1..100000000 loop
        total := total+i+j+k;
    end loop;
    dbms_output.put_line(total);
end;
/

소요시간 : 00:00:05.20

                                                                                                                                                        단위 : 초

   NUMBER BINARY_INTEGER  PLS_INTEGER 
 소요시간  18.65  06.84  05.20


이렇게 해서 PLS_INTEGER의 연산속도가 NUMBER와 BINARY_INTEGER보다 빠르다는 것을 알 수 있었습니다.

'Oracle > PL_SQL' 카테고리의 다른 글

테이블 변경시 관련 procedure, function, package 확인  (0) 2009.11.16
wrap pld  (0) 2009.11.16
Exception handling  (0) 2009.11.13
Cursor  (0) 2009.11.12
Bind Variables(Host Variable)  (0) 2009.11.12
Posted by 자수성가한 부자
Oracle/PL_SQL2009. 11. 12. 00:16


바인드 변수(호스트 변수)는 호스트 환경에서 선언한 변수로 Run Time 값을 하나 이상의 PL/SQL 프로그램과 주고 받는데 사용합니다.


변수 선언 방법
VARIABLE v_test NUMBER;

초기값 입력하기
EXEC :v_test := 5;

변수 확인 방법
PRINT v_test;


사용예)
variable g_deptno number
variable g_deptno_avg_sal number
variable g_avg_sal number
variable g_diff number

exec :g_deptno := 10;

begin
  select avg(sal), min((select avg(sal) from emp)) into :g_deptno_avg_sal, :g_avg_sal
  from emp
  where deptno = :g_deptno;

  :g_diff := :g_deptno_avg_sal - :g_avg_sal;
end;
/

print 명령어로 결과값 확인
print g_deptno g_deptno_avg_sal g_avg_sal g_diff


결과 화면)




참조 : http://www.oracle.com/technology/support/tech/sql_plus/htdocs/sub_var3.html

'Oracle > PL_SQL' 카테고리의 다른 글

테이블 변경시 관련 procedure, function, package 확인  (0) 2009.11.16
wrap pld  (0) 2009.11.16
Exception handling  (0) 2009.11.13
Cursor  (0) 2009.11.12
PLS_INTEGER  (1) 2009.11.12
Posted by 자수성가한 부자
Oracle/SQL2009. 11. 11. 23:20

create table t1
(col1 number);

set timing on                          -- 소요시간을 표시하기 위한 세팅


# insert문 백만개로 백만건 입력시 소요시간

  begin
    FOR i IN 1..1000000 LOOP
      insert into t1 values (i);
    END LOOP;
  end;
/

경과시간: 00:00:31.14

#connect by 이용 백만건 입력시 소요시간

  insert into t1
  select level
  from dual
  connect by level <= 1000000;

경과시간: 00:00:03.46 (9배나 빠름)

이렇게 데이터를 입력할 일이 있으면 꼭 connect by를 이용하도록 해야겠다.

'Oracle > SQL' 카테고리의 다른 글

WITH .. AS  (0) 2009.11.15
계층형 쿼리(Hierachical select)  (0) 2009.11.14
Merge  (0) 2009.11.09
분석함수(Anaylitic Function)  (0) 2009.11.09
단일행 함수(Single Row Function)  (0) 2009.11.09
Posted by 자수성가한 부자