2010년 3월 20일 토요일

간단한 proc 프로그램 예제

4절. 간단한 proc 프로그램 예제

다음은 zipcode 테이블에 총몇개의 자료가 들어있는지 알아오는 아주 간단한 프로그램이다.

예제 : zipcode.pc

 
#include <stdio.h>
#include <unistd.h>

/* SQLCA 를 선언한다 */
EXEC SQL INCLUDE SQLCA;

int main(int argc, char **argv)
{
    /* 선언부 */
    EXEC SQL BEGIN DECLARE SECTION;
            int count = 0;
            char userid[40]= "system/manager@ORACLE";
    EXEC SQL END DECLARE SECTION;

    /* DB 연결 */
    EXEC SQL CONNECT :userid;

    /* 에러 처리 */
    if (sqlca.sqlcode < 0)
    {
            printf("%s\n", sqlca.sqlerrm.sqlerrmc);
            EXEC SQL ROLLBACK WORK RELEASE;
            exit(0);
    }

    /* 쿼리 */ 
    EXEC SQL SELECT count(*) 
            INTO: count  
            FROM zipcode;

    /* 쿼리 결과에 대한 에러처리 */
    if (sqlca.sqlcode != 0) 
    {
            EXEC SQL COMMIT WORK RELEASE;
            return 0;
    }

    printf("우편주소 데이타 : %d 개\n", count);

    /* DB 연결 종료 */
    EXEC SQL COMMIT WORK RELEASE;
}
		
코드를 보면 알겠지만 뭐 복잡하게 이것 저것 인클루드 시켜줄 필요도 없고, SQL 문이 거의 그대로 쓰여서 이해하기도 매우 쉽다는 것을 알수 있을 것이다. 참고로 오라클 proc 쏘쓰파일에서의 주석은 /* */ 만 사용가능하다. // 을 썼다가는 오류가 발생한다.

이번 문서는 단지 이런식으로 프로그래밍이 가능하다라는 정도만 보여줄 것임으로 위의 코드의 설명은 생략하도록 하겠다. 나중에 자세히 다루도록 하겠다.


4.1절. 컴파일 하기

우선 zipcode.pc 파일을 proc 선행 컴파일러를 이용해서 zipcode.c 파일을 얻어낸다음 gcc를 이용해서 object 파일을 만들고 링크과정을 거쳐서 실행파일을 만들어야 한다. 다음은 이러한 일련의 과정이다.

[oracle@localhost proc]$ proc zipcode INCLUDE=include/ \ 
> include=/usr/u01/product/8.1.7/precomp/public/ \
> include=/usr/u01/product/8.1.7/rdbms/demo/ \
> include=/usr/u01/product/8.1.7/rdbms/public/ \
> include=/usr/u01/product/8.1.7/network/public/ \
> PARSE=NONE RELEASE_CURSOR=YES MODE=ANSI

Pro*C/C++: Release 8.1.7.0.0 - Production on Thu Oct 31 00:29:15 2002

(c) Copyright 2000 Oracle Corporation.  All rights reserved.

System default option values taken from: /usr/u01/product/8.1.7/precomp/admin/pcscfg.cfg

[oracle@localhost proc]$ gcc -c -o zipcode.o zipcode.c -I$ORACLE_HOME/precomp/public \ 
> -I$ORACLE_HOME/rdbms/demo -I$ORACLE_HOME/rdbms/public \
> -I$ORACLE_HOME/network/public

[oracle@localhost proc]$ gcc -o zipcode zipcode.o -L$ORACLE_HOME/lib -lclntsh
			
이 프로그램을 실행시키면 다음과 같은 결과값을 보여줄 것이다.
[oracle@localhost proc]$ ./zipcode 
우편주소 데이타 : 43476 개
			

4.2절. 컴파일 과정을 Makefile 로 관리하기

하지만 위의 방법대로 수동으로 코드를 컴파일 하는건 비 생산적인 방법이다. 그러므로 Makefile 을 만들어서 관리하도록 하자.

Makefile

TARGET          = zipcode

CC              = gcc
PROC            = proc
LIB             = -L$(ORACLE_HOME)/lib -lclntsh
MYINC           = include/
PROCINC         = include=$(ORACLE_HOME)/precomp/public/ include=$(ORACLE_HOME)/rdbms/demo/ \
	include=$(ORACLE_HOME)/rdbms/public/ \
	include=$(ORACLE_HOME)/network/public/ 
CINC            = -I$(ORACLE_HOME)/precomp/public/ -I$(ORACLE_HOME)/rdbms/demo/ \
	-I$(ORACLE_HOME)/rdbms/public/ -I$(ORACLE_HOME)/network/public/ 

ORA_OPT         = PARSE=NONE RELEASE_CURSOR=YES MODE=ANSI
CC_OPT          =

OBJECT          = zipcode.o
ORA_GARBAGE     = *.dcl *.cod *.cud *.lis

######## implicit rules
.SUFFIXES: .pc .c

.pc.c:
	$(PROC) $* INCLUDE=$(MYINC) $(PROCINC) $(ORA_OPT)
.c.o:
	$(CC) -c -o $*.o $*.c -I $(MYINC) $(CINC)

####### build rules

all:            $(TARGET)

$(TARGET):      $(OBJECT)
	$(CC) -o $(TARGET) $(OBJECT) $(LIB)

zipcode.c: zipcode.pc
zipcode.o: zipcode.c

clean:
	rm -f $(TARGET) $(OBJECT) $(ORA_GARBAGE)
			
이해하는데 특별히 어려움은 없을것이라고 생각된다. Makefile 에 대한 내용은 make 를 이용한 프로젝트 관리 (1)를 참고하도록 한다.

출처 :

spfile 생성

create spfile from pfile ='/opt/oracle10/oracle10/10g/dbs/initorcl10.ora';

Proc 설정하기

1. Prepare

 * Oracle 10g ( or 11g)

 * precomp demo

 * ProC 를 컴파일하기 위해서는 오라클 과, precomp demo 파일( 필수 사항은 아님) 이 있어야한다.

 * 10g 이상부터 오라클 일반설치를 하면 자동으로 proc 가 install 되기 때문에 추가적으로 깔아 주어야

    할것은 없다. ( Client 를 깔아야 된다는 예기도 있던데 없어도 컴파일 가능하다. )

 

2. Setting

$ORACLE_HOME/precomp/admin/pcscfg.cfg

 * 위의 파일은 *.pc 파일을 *.c 파일로 변환해 주는데 필요한 환경변수들이 있는곳이다.

 * 기본으로 설치하면 자신의 리눅스 환경과는 맞지 않는 설정으로 되어 있으므로,

   아래와 같이 다시 세팅해 주어야한다.

 

PARSE=NONE
sys_include=($ORACLE_HOME/precomp/public,/usr/include,/usr/lib/gcc/i586-redhat-linux/4.4.1/include,$ORACLE_HOME/lib)
include=($ORACLE_HOME/precomp/lib)
include=($ORACLE_HOME/precomp/public)
include=($ORACLE_HOME/rdbms/lib)
include=($ORACLE_HOME/rdbms/public)
include=($ORACLE_HOME/rdbms/demo)
include=($ORACLE_HOME/network/lib)
include=($ORACLE_HOME/network/public)
include=($ORACLE_HOME/plsq/public)
ltype=short

 

3. Compile

 

*.pc 파일을 c/c++ 로 변환후 컴파일을 수행한다.

기본적으로 proc 를 사용하여 c 로 변환시킨다.

proc sample1.pc

pcscfg.cfg 의 환경변수를 이용하여, sample1.c 파일이 생성된다.

c 파일을 gcc / cc 컴파일러를 이용하여 컴파일하여 실행파일로 만든다.

 

gcc -o run sample1.c -I$ORACLE_HOME/precomp/public -L$ORACLE_HOME/lib -lclntsh

 

* 위의 설정으로는 demo 의 sample.pc 파일들을 컴파일 할때 대부분 오류가 발생한다.

따라서 코드를 수정해 줘야한다. ( 해결사항은 추후 기재 ..;;)


[에러 조치사항]

 추후 기재 ...

 

 

 

2010년 3월 16일 화요일

Input Prompt

static void cliInput(char const* prompt, char* buf, size_t buf_size)
{
        char* p;

        do {
                printf("%s",prompt);
                *buf = '\0';
                fgets(buf, buf_size, stdin);
                p = buf + strlen(buf);


        } while (p <= buf+1);

        if (*(p-1) == '\n') {
                *--p = '\0';
        }
}

2010년 3월 15일 월요일

no_parallel, no_parallel_index

 

1. no_parallel_index

Index를 사용할때 병렬 처리를 하지 않도록한다.

기본적으로 Index 는 single access 이다. 하지만 INDEX FAST FULL SCAN 의 경우 Index 의 물리적인 Block을 순차적으로 읽기 때문에 병렬 ACCESS 가 가능하다. 따라서 해당 힌트를 사용하면 실행계획 생성시 INDEX FAST FULL SCAN 을 사용하지 않는 방법을 택한다. ( INDEX FULL SCAN ..)

 

2. no_parallel

Table Scan 시에 병렬 처리를 하지 않도록한다.

일반적으로 CREATE AS SELECT 질의시 옵티마이져가 일반적으로 병렬처리를 하게된다.

해당 힌트로 사용하여, 옵티마이져가 병렬처리하는것을 배제하도록한다.

해당 테이블을 어떠한 특정 정렬로 복사 하고자 할때 no_parallel 힌트를 사용하지 않으면,

병렬처리로 인하여 원본 테이블과는 다른 Block 개수를 가지게 될수 있다.

 

아마 FreeList 의 할당 방법 때문인것으로 보이는데 병렬처리시에 FreeList Contention 을 줄이기 위해 각기 다른 Data Block을 할당하게 된다.

따라서 동시에 여러 Data Block 에 대해서 Insert 작업이 일어나기 때문에, 각각의 데이터 사용률 또한 원본 테이블의 분포도와는 차이를 보이게 되며,

사용하는 Data Block 또한 일반적으로 원본 테이블이 사용한 Block 수 보다 조금더 사용하게 된다.

또한 Index 생성시 Clustering Factor 또한 변화가 있을것이다.

 

 

 

사용예제

insert into v52.DSS_REGION nologging select
/*+ no_parallel(DSS_REGION)  no_parallel_index(DSS_REGION) */ * from v40.DSS_REGION;

 

 

2010년 3월 14일 일요일

Truth table for three-valued logic & NULL

 x

y

x AND y

x OR y

NOT x 

 TRUE

 TRUE

 TRUE

 TRUE

FALSE

 TRUE

 UNKNOWN

 UNKNOWN

 TRUE

FALSE

 TRUE

FALSE 

FALSE

 TRUE

FALSE

 UNKNOWN

 TRUE

 UNKNOWN

 TRUE

 UNKNOWN

 UNKNOWN

 UNKNOWN

 UNKNOWN

 UNKNOWN

 UNKNOWN

 UNKNOWN

FALSE

FALSE

 UNKNOWN

 UNKNOWN 

FALSE

 TRUE

FALSE

 TRUE

 TRUE

FALSE

 UNKNOWN

FALSE

 UNKNOWN

 TRUE

FALSE

FALSE

FALSE

FALSE

 TRUE

 

1. NULL 의 일반적인 정의

 1. Value unknown

   - 해당 값이 존재하지만 어떤 값인지 모르는 상태 말 그대로 "I don't Know" 예) 생일을 모른다.

 2. Value inapplicable

   - 해당 값에 적용 할수 없는 상태. 즉 해당 값에 해당하지 않는 상태를 말한다.

     예) 배우자 attribute 존재할때 결혼하지 않는 사람은 NULL 로 표시된다.

 3. Value withheld

   -  아직 적용하지 않은 상태, 1번과 비슷한 상태이지만, 모르는 상태가 아닌 아직 등록하지 않은 상태임

      예) 아직 등록되지 않은 전화번호 attrubute

 

아래와 같은 쿼리를 사용하여, NOT NULL 인 튜플들만 Projection 할수있다.

( NOT NULL 같은 제약조건을 걸지 않고..)

SELECT *

FROM Movies

WHERE length <= 120 OR length > 120;

 

length attribute 가 NULL 을 가지고 있다면,

어떤 튜플이 NULL 일 경우 NULL OR NULL 인 결과는 UNKNOWN 이게 된다.

논리 연산에서 결과가 UNKNOWN 인 경우는 결과집합에 포함이 안되므로,

결론적으로 위의 쿼리는 NULL 을 가지지 않는 length 의 모든 튜플을 Projection 하게 된다.

 

위의 쿼리를 가지고 NULL 도 결과 집합에 포함 하려면?

SELECT *

FROM Movies

WHERE length <= 120 OR length > 120 OR length IS NULL;

 

IS NULL 조건이 포함되면, 튜플이 NULL 일 경우의 결과는 TRUE 이다.

TRUE 과 NULL 의 OR 연산은 TRUE 이므로 NULL 도 결과집합에 포함된다.

 

Grouping, Aggregation

 

NULL 은 어떤 aggregation function 에도 무시된다.

하지만 count(*) 의 경우는 relation 의 총 튜플수를 리턴한다.

 

   A    |    B

-------------

NULL |  NULL

 

attribute 의 집합이 NULL 뿐일경우, aggregation 의 결과는 NULL 이다.

 

 

Reference :

DATABASE SYSTEMS : The Complete Book (Jeffrey D. Ullman)

2010년 3월 13일 토요일

SORT_AREA_RETAINED_SIZE

SORT_AREA_RETAINED_SIZE

Property Description
Parameter type Integer
Default value Derived from SORT_AREA_SIZE
Modifiable ALTER SESSION, ALTER SYSTEM ... DEFERRED
Range of values From the value equivalent of two database blocks to the value of SORT_AREA_SIZE

Note:

Oracle does not recommend using the SORT_AREA_RETAINED_SIZE parameter unless the instance is configured with the shared server option. Oracle recommends that you enable automatic sizing of SQL working areas by setting PGA_AGGREGATE_TARGET instead. SORT_AREA_RETAINED_SIZE is retained for backward compatibility.

SORT_AREA_RETAINED_SIZE specifies (in bytes) the maximum amount of the user global area (UGA) memory retained after a sort run completes. The retained size controls the size of the read buffer, which Oracle uses to maintain a portion of the sort in memory. This memory is released back to the UGA, not to the operating system, after the last row is fetched from the sort space.

Oracle may allocate multiple sort spaces of this size for each query. Usually, only one or two sorts occur at one time, even for complex queries. In some cases, however, additional concurrent sorts are required, and each sort keeps its own memory area. If the shared server is used, allocation is to the SGA until the value in SORT_AREA_RETAINED_SIZE is reached. The difference between SORT_AREA_RETAINED_SIZE and SORT_AREA_SIZE is allocated to the PGA.

Note:

The default value as reflected in the V$PARAMETER dynamic performance view is 0. However, if you do not explicitly set this parameter, Oracle actually uses the value of the SORT_AREA_SIZE parameter.

See Also: