MongoDB 및 CouchDB와 같은 문서 지향적 데이터베이스는 데이터를 테이블에 저장하지 않고 문서 형식으로
저장한다는 점에서 관계형 데이터베이스와 큰 차이가 있다. 개발자의 관점에서 문서 지향적(또는 스키마리스)
데이터는 관계형 데이터에 비해 단순해서 관리 유연성이 훨씬 높다. 관계를 통해 결합된 테이블, 행 및 열로
구성된 엄격한 스키마에 데이터를 저장하기 보다는 필요한 데이터가 포함된 문서를 개별적으로 작성한다.
개발사에서 소개하는 MongoDB
10gen의 CTO인 Eliot Horowitz가 시기 적절한 기술 팟캐스트를 통해 이 오픈 소스 문서 데이터베이스에 대해
자세히 설명한다. 지금 들어보자.
오픈 소스 문서 지향적 데이터베이스 중에서 MongoDB는 RDBMS 기능을 갖춘 NoSQL 데이터베이스라고
언급되기도 한다. 예를 들어, MongoDB에서는 미리 정의된 MapReduce 함수가 없어도 동적 쿼리가 지원된다. 또한
MongoDB에는 손쉽게 데이터 저장소에 액세스하는 기능을 제공하는 대화식 쉘이 있으며 기본적으로 지원되는 샤드(shard)
기능을 사용하면 여러 노드로 확장할 수 있다.
MongoDB의 API는 JSON 오브젝트와 JavaScript 함수의 혼합체이다. 개발자는 명령행 인수를 사용할 수 있는 쉘
프로그램이나 언어 드라이버를 통해 MongoDB와 상호 작용하여 데이터 저장소 인스턴스에 액세스할 수 있다. 그렇지만
JDBC와 같은 드라이버는 없다. 이는 ResultSet 또는 PreparedStatement를
다루지 않아도 된다는 의미이다.
MongoDB는 빠르다는 장점도 가지고 있다. 이는 주로 데이터를 쓰는 방법 즉, 데이터를 메모리에 저장한 후 나중에
백그라운드 스레드를 통해 디스크에 기록하는 방법이 속도 향상 효과를 제공하기 때문이다.
이 시리즈의 정보
처음 Java 기술이 발표된 이후로 Java를 개발하는 과정은 급속도로 변화되었다. 오픈 소스 프레임워크와 신뢰할 수 있는 임대용 전개 인프라 덕택에
Java 애플리케이션을 신속하고 저렴하게 어셈블하고 테스트하고 유지할 수 있게 되었다. 이 시리즈에서 Andrew Glover는 이러한 새로운 Java 개발 패러다임을
가능하게 하는 다양한 기술과 도구를 탐구한다.
MongoDB에 대해 설명하는 이 기사는 CouchDB에 대해 소개하는 필자의 기사(참고자료
참조)를 바탕으로 하며 다시 한번 주차 티켓 예제를 사용하여 스키마리스 데이터 저장소의 유연성을 보여 준다. MongoDB의
API 및 동적 쿼리 지원이 MongoDB의 두 가지 주요 차별 요소이므로 이러한 차별 요소에 중점을 두고 MongoDB의 쉘 및 Java
언어 드라이버의 사용법을 보여 주는 예제를 살펴본다. 기사 후반부에서는 MongoDB의 MapReduce 구현에서 제공하는 일부 정보를
사용하는 Groovy 랩퍼인 GMongo에 대해서도 소개한다. 이 기능도 이 특별한 NoSQL 옵션의 주요 특징 중 하나이다.
스키마리스 저장소가 모든 분야에 적합한 것은 아니기 때문에 문서 지향적 방법과 관계형 방법의 선택 기준을
이해해야 한다. 데이터를 다양한 양식으로 참조할 수 있지만 기본 모델이 동일한 분야에서는 문서의 유연성이
중요하다. 명함이 전형적인 예이다. 수많은 명함을 보면 다양한 데이터가 있다는 것을 알 수 있다. 일부 명함에는
팩스 번호나 회사 URL이 적혀 있기도 하지만 우편 주소, 두 개의 전화번호 또는 Twitter 핸들이 적혀 있는 명함도
있다. 데이터는 다양하지만 모델이나 기능은 동일하다. 즉, 명함에는 연락처 정보가 있다.
명함을 관계형 용어로 모델링할 수는 있지만 꽤 복잡하다. 관계형 데이터베이스를 보면 예를 들어, 팩스 번호를
사용하는 하나 또는 두 개의 레코드마다 팩스 열의 값이 널값인 레코드를 많이 볼 수 있다. 또한 관계형 시스템에서는
열 유형을 지정해야 하기 때문에 주소 필드 길이 등으로 인한 제약이 발생할 수 있다. (아마도 Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch에
사는 사람의 주소를 저장해야 하는 경우를 생각해 본 적이 없을 것이다. 하지만 이 마을이 실제로 존재한다.)
문서 지향적 데이터 저장소로 명함을 모델링하는 작업은 매우 쉽다. 스키마를 사용하지 않는다는 것은 길이에
상관 없이 필요한 모든 데이터를 문서에 담을 수 있다는 것을 의미한다. 명함의 특성을 고려하면 다양한 특성을
지닌 문서로 모델링하는 것이 적합하다.
스키마리스 데이터 저장소는 대부분 ACID(Atomicity, Consistency, Isolation, and Durability)를 완벽하게
지원하지는 않기 때문에 안정성 및 일관성이 중요한 분야에서는 문제가 발생할 수 있다. NoSQL 방법의 지지자는
확장하기 위해 다중 노드를 도입하는 순간부터 불가피하게 발생하는 중단 시간을 고려하지 않는 경우에만 ACID가
작동한다고 주장한다. 핵심은 스키마리스 데이터 저장소가 관계형 데이터 저장소보다 쉽게 확장할 수 있으므로 문서
지향적 저장소가 웹 기반 애플리케이션에 적합하다는 것이다.
SQL> SELECT empno, sal, deptno FROM emp WHERE sal IN ( SELECT sal FROM emp WHERE deptno = 30 AND comm is NOT NULL ) AND deptno IN ( SELECT deptno FROM emp WHERE deptno = 30 AND comm is NOT NULL );
오라클 형변환 - 숫자형을 문자로 출력할때 소수점을 살려두고 싶다면. select to_char(96.08,'990.0') from dual union all select to_char(96.5,'990.0') from dual union all select to_char(96.33,'990.0') from dual
모바일 환경을 지원하는 디바이스는 휴대성을 고려하기 위해 한정된 자원을 사용해야 하는 많은 제약사항을 가지고 있다. 그러나 똑똑하고 다양한 기능을 지원하기 위해서는 큰 메모리를 사용하고, 다루고자 하는 데이터가 많아지는 경우에는 안정성과 활용성을 고려한 데이터베이스 시스템이 사용되어야 한다. 모바일 디바이스에서 현재 큰 인기를 끌고 있는 SQLite에서 어떻게 하면 성능을 향상시켜 최적의 기능을 이끌어낼 수 있을지 지금부터 살펴보도록 한다.
모바일 디바이스에서 사용되는 데이터베이스 관리 시스템에는 많은 솔루션이 있지만, 그 중에서 대표적인 것이 SQLite이다. SQLite는 구글의 안드로이드나 애플의 아이폰 등에서 사용되는 솔루션으로 사용자 측면과 관리자 측면에서 모두 뛰어난 접근성을 가지고 있다. SQLite는 다음과 같은 임베디드 시스템을 위한 요구사항을 만족하는 데이터베이스 솔루션이다.
- 사용자가 사용하기 쉬움 - 관리가 간편 - 갑작스런 외부 오류에 둔감 - 다양한 플랫폼에 모두 적용 가능 - 풋-프린트가 작음
SQLite 가 가지는 가장 큰 특성 세 가지는 다음과 같다. 서버를 필요로 하지 않기 때문에 시스템 내에서 별도의 자원을 사용할 필요가 없으며, 다른 솔루션과 달리 설정이 필요 없으므로 사용하기에 편리하다. 또한 트랜잭션 처리가 이뤄지므로, 데이터의 무결성을 보장해 줄 수 있다. 따라서 SQLite는 데스크톱 컴퓨터로부터 PDA, 셀룰러 폰, MP3 플레이어에 이르기까지 많은 디바이스에 적용될 수 있다. SQLite의 주요 특성은 다음과 같다(<표 1> 참조).
이와 같은 특성들을 가지고 있는 SQLite의 내부 구조는 <그림 2>와 같다. 코어, SQL 컴파일러, 백앤드가 주요 핵심요소이고, 이외에 액세서리 역할을 하는 유틸리티와 테스트 코드로 이뤄져 있다. 그럼 지금부터는 SQLite의 성능을 다른 데이터베이스 솔루션과 비교해 보도록 하자. 일단 오픈소스 데이터베이스로서 유명한 MySQL과 비교해 보면 <화면 1>과 같다.
InnoDB를 사용하는 MySQL에 비해서는 SQLite가 빠르지만, MyISAM을 사용하는 MySQL에 비해서는 느린 특성을 가진다. <표 2>에서는 PostgreSQL과 MySQL의 성능을 SQLite와 비교해 보도록 하자. 비교하는 동작은 INSERT, UPDATE, SELECT, DELETE, DROP이다. 그럼 SQLite의 성능을 최대한 향상시키기 위해서는 어떻게 해야 할까? 우선 다음과 같은 방법을 고려해 볼 수 있다. SQLite 에서 성능을 향상시키고자 할 때 우선적으로 트랜잭션과 캐시를 고려한다. 만약에 트랜잭션이 명시적으로 선언되어 수행되지 않으면, 각 SQL 문은 자신들의 동작을 보장하기 위해 동작 시마다 새로운 트랜잭션을 가지게 된다. 이는 매번 저널 파일에 대한 열기, 쓰기, 닫기를 수행하도록 함으로써 속도 저하를 유발하므로, 일련의 SQL 문들이 있으면 이 전체를 모두 하나의 트랜잭션으로 묶어 속도를 향상시킬 수 있다.
SQLite 는 저널 파일을 사용함으로써 만약의 동작 실패 시에 트랜잭션을 롤백할 수 있다. 이를 위해 트랜잭션 동작 중에 데이터베이스에서 발생하는 모든 변화들을 기록해야 한다. 따라서 이는 디스크 액세스에 있어서 오버헤드 동작이 된다. 따라서 만약 데이터베이스를 변경할 필요가 없을 경우에는 저널 동작을 수행하지 않도록 한다. 만약에 게임과 같은 애플리케이션이 동작하면서 데이터베이스를 사용하는 경우에는 데이터의 무결성보다는 성능을 더욱 더 중요시하기 때문에 이러한 경우에는 저널링을 중단해도 될 것이다. 물론 사용자가 원한다면 저널링을 수행하도록 한다. 쿼리는 캐시돼 있을수록 디스크에 대한 접근 횟수가 줄어들기 때문에 속도향상에 도움이 된다. 또한 이러한 방법 이외에 추가적으로 SQL 문을 재정렬하거나 인덱스를 생성 및 이용하면 속도를 향상시킬 수 있다. 인덱스를 사용하는 쿼리는 인덱스를 사용하지 않는 쿼리보다 속도의 향상을 기대할 수 있다. 인덱스들 중에 불필요한 것이 있는지는 확인해서 불필요한 것은 제거하도록 해야 한다. 인덱스를 사용하게 되면, 디스크에서 전체 테이블을 스캔하지 않고서도 값의 범위를 선택할 수 있다. 인덱스는 질의가 전체 테이블에 대해 스캔할 필요가 없을 때 속도 측면에서 큰 차이를 가져온다. 인덱스를 사용하기 위해서는 별도의 인덱스 테이블을 생성해야 하기 때문에 부수적인 크기의 오버헤드를 가져온다. 인덱스를 생성하는 방법은 <리스트 1>과 같다.
<리스트 1> 인덱스 생성 방법
CREATE TABLE mytable (
a TEXT PRIMARY KEY, -- index created
b INTEGER,
c TEXT UNIQUE -- index created
);
이러한 방법과 더불어 다음과 같은 방법들도 고려할 수 있다.
첫 번째로 데이터베이스 스키마를 가능한 간단하게 만들도록 한다. 즉, 잘못된 데이터나 논리구조를 가지면 안 된다는 의미다. 두 번째로 데이터베이스 스키마를 무조건적으로 정규화하지 않도록 한다. 이는 개발자에게는 편리할 수 있겠지만, 정규화는 성능을 감소시킬 수 있다. 세 번째로는 SELECT 문에서 테이블의 순서를 조정함으로써 성능을 향상시킬 수 있다. 네 번째로는 불필요한 인덱스들을 사용하는 대신 해시 키를 사용할 수도 있다. 이는 성능문제 때문에 인덱스를 생성하기 어려울 경우에 매우 유용할 수 있다.
또 한, 컴파일러 설정을 확인해서 C 컴파일러에서 최적화 옵션을 사용해 빌드해야 한다. 불필요한 심볼이 들어가서 이를 처리하기 위한 불필요한 동작이 수행되면 성능을 저하시킬 수 있기 때문이다. 만약에 사용하지 않은 특성이 있다면 이는 비활성화시켜서 바이너리 크기를 줄이고, 이를 통해 속도를 향상시키도록 한다. SQLite의 사용 시간 중에 많은 부분을 차지하는 것은 디스크 액세스 시간이다. 따라서 성능을 최적화시키기 위해서는 디스크 액세스 양을 최소화해야만 한다. 이러한 점을 고려해 다음과 같은 방법을 사용하도록 한다.
- In-memory 데이터베이스 사용 - PRAGMA cache_size 사용 - PRAGMA synchronous=OFF 사용 - PRAGMA count_changes=OFF 사용
이외에도 SQLite의 실제 동작은 파일시스템 위에서 이뤄질 것이기 때문에 하위 근간을 이루는 파일시스템의 성능도 중요한 요소가 된다(<화면 2> 참조).
SQLite 데이터베이스는 기본 값으로 1KB 크기를 가지는 btree 페이지들로 나눌 수 있으며, 데이터베이스를 가지고 동작할 때 이러한 페이지들을 메모리로 로드해 데이터들을 관리한다. 캐시의 페이지 최대값으로 2,000이 기본적으로 설정돼 있지만, 이를 증가시킴으로써 성능 도모를 꾀할 수 있다. PRAGMA synchronous=OFF를 사용함으로써 디스크에 쓰기 위해 기다리는 시간을 줄일 수 있어 속도를 향상시킬 수 있게 된다. PRAGMA count_changes가 ON으로 설정돼 있으면, 콜백 함수는 각 DELETE, INSERT, UPDATE 동작이 수행될 때마다 수행된다. 따라서 이를 OFF로 해 놓으면 속도를 향상시킬 수 있다. SQLite에서 GLOB과 LIKE 연산자는 인덱스를 사용하지 않기 때문에 가급적이면 피하도록 한다. 그리고 매우 긴 문자열을 사용할 때 length()를 사용하지 않도록 한다. 따라서 <리스트 2>와 같이 사용하도록 한다.
<리스트 2> Length()의 대체방법
Example : Replace (WHERE length(str)=0) with (WHERE str='').
SQLite 데이터베이스의 파일 크기를 줄이기 위해서는 실제로 내용이 없어서 비어 있지만 메모리 페이지를 차지하는 페이지를 제거하는 방법을 우선적으로 사용할 수 있다. 이를 위한 가장 간단한 방법은 VACUUM이라는 명령어를 사용하는 것이다. 이는 <리스트 3>과 같이 수행할 수 있다.
데이터의 크기를 최소한으로 만들기 위해서 압축하는 방법을 사용할 수 있다. 바이너리 데이터를 압축 및 해지하기 위해서 sqlite_ encode_binary()와 sqlite_decode_binary() 함수를 사용할 수 있다. 이를 통해 저장하기에 적합한 바이너리로 인코딩할 수 있다. 만약에 특수 문자를 포함하지 않는다면, 모든 0을 제거하기 위해 XOR 인코딩을 사용할 수 있다. 이러한 인코딩 방식과 별도로 7-비트 데이터 인코딩 방식이 존재한다. 이는 상위 비트를 토글링함으로써 SQL 문을 인코딩하는 데 유용하게 사용될 수 있다.
<리스트 4> 7-비트 데이터 인코딩 방식
int ascii7enc(char *out, const char *in, int len)
{
int ct = len;
if (!in || !out || len < 0) return -1;
while (ct-- > 0)
{
char ch = (*in == 0 || *in == '\'' || *in == 0x80 || *in == '\''^0x80)?
(*in++ ^ 0x80): *in++;
*out++ = ch;
}
return len;
}
지금까지 SQLite 성능을 향상시키기 위한 여러 가지 방법을 살펴봤다. 다양한 방법을 통해 성능을 향상시킬 수 있지만, 어느 하나만을 사용한다고 해서 혁신적으로 속도가 향상되는 것은 아니다. 따라서 해결법을 혼합 사용해 원하는 속도의 향상을 이뤄내도록 노력해야 할 것이다.
필자소개
김형훈 asinayo73@hotmail.com|모바일 디바이스의 설계부터 테스팅까지 모든 부분에 관심이 많으며, 현재 gmobileTech사에서 모바일 디바이스 구조검증 및 설계 컨설팅 업무를 맡고 있다. 다양한 형태의 모바일 디바이스가 어떻게 하면 각각 최적의 성능을 낼 수 있는지에 대해 연구하고 있다.
/*+ ALL_ROWS */
explicitly chooses the cost-based approach to optimize a statement
block with a goal of best throughput (that is, minimum
total resource consumption)
가장 좋은 단위 처리량의 목표로 문 블록을 최적화하기 위해 cost-based
접근 방법을 선택합니다. (즉, 전체적인 최소의 자원 소비)
/*+ CHOOSE */
causes the optimizer to choose between the rule-based
approach and the cost-based approach for a SQL statement
based on the presence of statistics for the tables accessed by
the statement
최적자(optimizer)가 그 문에 의해 접근된 테이블을 위해 통계의 존재에
근거를 두는 SQL 문을 위해 rule-based 접근 방법과 cot-based 접근 방법
사이에 선택하게 합니다.
/*+ FIRST_ROWS */
explicitly chooses the cost-based approach to optimize a statement
block with a goal of best response time (minimum
resource usage to return first row)
가장 좋은 응답 시간의 목표로 문 블록을 최적화하기 위해 cost-based 접근
방법을 선택합니다. (첫번째 행을 되돌려 주는 최소의 자원 사용)
/*+ RULE */
explicitly chooses rule-based optimization for a statement
block
문 블록을 위하여, rule-based 최적화를 고르는
/*+ AND_EQUAL(table index) */
explicitly chooses an execution plan that uses an access path
that merges the scans on several single-column indexes
그만큼 실행 계획을 선택합니다. 그리고 여럿의 single-column 색인에
그 scan을 합병하는 접근 경로를 사용합니다.
/*+ CLUSTER(table) */
explicitly chooses a cluster scan to access the specified table
선택합니다. 그리고, 클러스터는 그 명시된 테이블을 접근하기 위해 살핍니다.
/*+ FULL(table) */
explicitly chooses a full table scan for the specified table
그 명시된 테이블을 위하여, 전체 테이블 scan을 고르는
/*+ HASH(table) */
explicitly chooses a hash scan to access the specified table
선택합니다. 그리고, 해쉬는 그 명시된 테이블을 접근하기 위해 운율을 살핍니다.
/*+ HASH_AJ(table) */
transforms a NOT IN subquery into a hash antijoin to access
the specified table
변환, 그 명시된 테이블을 접근하는 해쉬 antijoin으로의 NOT IN 부속 조회
/*+ HASH_SJ (table) */
transforms a NOT IN subquery into a hash anti-join to access
the specified table
변환, 그 명시된 테이블을 접근하는 해쉬 anti-join으로의 NOT IN 부속 조회
/*+ INDEX(table index) */
explicitly chooses an index scan for the specified table
그 명시된 테이블을 위하여, 색인 scan을 고르는
/*+ INDEX_ASC(table index) */
explicitly chooses an ascending-range index scan for the specified
table
그 명시된 테이블을 위하여, ascending-range 색인 scan을 고르는
/*+ INDEX_COMBINE(table index) */
If no indexes are given as arguments for the INDEX_COMBINE
hint, the optimizer uses whatever Boolean combination
of bitmap indexes has the best cost estimate. If particular
indexes are given as arguments, the optimizer tries to use
some Boolean combination of those particular bitmap indexes.
어떤 색인도 INDEX_COMBINE 암시를 위해 인수로서 주어지지 않는다면,
bitmap 색인의 결합이 어떤 부울의를 가장 좋은 수행 난이도 평가를 가지고
있든지 최적자는 이용합니다.
특별한 색인이 인수로서 주어진다면, 최적자는 그 특별한 bitmap 색인의
몇몇의 부울의 결합을 사용하려고 노력합니다.
/*+ INDEX_DESC(table index) */
explicitly chooses a descending-range index scan for the specified
table
그 명시된 테이블을 위하여, descending-range 색인 scan을 고르는
/*+ INDEX_FFS(table index) */
causes a fast full index scan to be performed rather than a full
table scan
빠른 전체 색인 scan이 전체 테이블 scan이라기보다는 수행되게 합니다.
/*+ MERGE_AJ (table) */
transforms a NOT IN subquery into a merge anti-join to access
the specified table
변환, NOT IN 부속 조회, 그 명시된 테이블을 접근하기 위해 anti-join을
합병합니다.
/*+ MERGE_SJ (table) */
transforms a correlated EXISTS subquery into a merge semi-join
to access the specified table
변환, 관련된 EXISTS 부속 조회, 접근으로 semi-join을 합병합니다,
그 명시된 테이블
/*+ ROWID(table) */
explicitly chooses a table scan by ROWID for the specified
table
그 명시된 테이블을 위하여, ROWID에 의해 테이블 scan을 고르는
/*+ USE_CONCAT */
forces combined OR conditions in the WHERE clause of a
query to be transformed into a compound query using the
UNION ALL set operator
힘은 질의의 WHERE 문절에 있는 UNION ALL 집합 연산자를 사용하는 합성의
질의로 변형되는 OR 조건을 합쳤습니다.
/*+ ORDERED */
causes Oracle to join tables in the order in which they appear
in the FROM clause
오라클이 어느 것에 순서로 테이블을 결합시키게 합니다.
/*+ STAR */
forces the large table to be joined last using a nested-loops join
on the index
큰 있는 테이블이 최종 사용/회전율에 nested-loops를 결합시킨 힘은
그 색인에 결합합니다.
/*+ DRIVING_SITE (table) */
forces query execution to be done at a different site from that
selected by Oracle
힘은 그것과 다른 오라클에 의해 선택된 사이트에 되는 실행을 질의합니다.
/*+ USE_HASH (table) */
causes Oracle to join each specified table with another row
source with a hash join
오라클이 테이블이 다른 행 자원으로 해쉬 접합으로 명시되면서 각자와
합치게 합니다.
/*+ USE_MERGE (table) */
causes Oracle to join each specified table with another row
source with a sort-merge join
오라클이 테이블이 다른 행 자원으로 sort-merge 접합으로 명시되면서 각자와
합치게 합니다.
/*+ USE_NL (table) */
causes Oracle to join each specified table to another row
source with a nested-loops join using the specified table as the
inner table
오라클이 그 명시된 테이블을 그 안의 테이블로 사용하는 nested-loops 접합과
각자와 다른 행 자원에 대한 명시된 테이블을 합치게 합니다.
/*+ APPEND */ , /*+ NOAPPEND */
specifies that data is simply appended (or not) to a table; existing
free space is not used. Use these hints only following the
INSERT keyword.
데이타가 테이블로 단순히 덧붙여진다는 (or not)것 명시합니다; 무료인
현존하는 영역은 사용되지 않습니다.
단지 그 삽입 키 핵심어를 따르는 이 암시를 사용하시오.
/*+ NOPARALLEL(table) */
disables parallel scanning of a table, even if the table was created
with a PARALLEL clause
그 테이블이 PARALLEL 문절로 새로 만들어졌다면 테이블의 평행의 순차 검색을
무능하게 만듭니다.
/*+ PARALLEL(table, instances) */
allows you to specify the desired number of concurrent slave
processes that can be used for the operation.
DELETE, INSERT, and UPDATE operations are considered for
parallelization only if the session is in a PARALLEL DML
enabled mode. (Use ALTER SESSION PARALLEL DML to
enter this mode.)
당신이 그 연산을 위해 사용될 수 있는 동시의 슬레이브(slave) 프로세스의
요구된 수를 명시하는 것을 허락합니다.
그 세션이 가능하게 된 PARALLEL DML에 모드를 있다면, DELETE, INSERT, UPDATE
연산은 단지 parallelization에 대해 고려됩니다. (사용은 이 모드에 들어가기
위해 평행의 세션 DML을 변경합니다.)
/*+ PARALLEL_INDEX
allows you to parallelize fast full index scan for partitioned
and nonpartitioned indexes that have the PARALLEL attribute
parallelize에 당신에게 빠른 가득한 색인 scan을 허락합니다. 그런데,
그것은 PARALLEL 속성을 가지고 있는 색인을 분할했고 nonpartitioned했습니다.
/*+ NOPARALLEL_INDEX */
overrides a PARALLEL attribute setting on an index
병렬이 색인을 나아가는 것을 속하게 하는 대체
/*+ CACHE */
specifies that the blocks retrieved for the table in the hint are
placed at the most recently used end of the LRU list in the
buffer cache when a full table scan is performed
그 블록이 찾아서 가져왔다는 것을 명시합니다. 그리고 그 테이블을 위해
그 암시에 놓여집니다. 그런데, 그것은 가장 요즈음 사용된 언제 그 버퍼 캐쉬,
가득한 테이블 scan에 있는 LRU 리스트의 끝입니다. 수행됩니다.
/*+ NOCACHE */
specifies that the blocks retrieved for this table are placed at
the least recently used end of the LRU list in the buffer cache
when a full table scan is performed
그 명시합니다. 그리고, 그 블록은 이 테이블을 위해 검색되면서 요즈음 사용된
언제 그 버퍼 캐쉬, 가득한 테이블 scan에 있는 LRU 리스트의 가장 작은 끝에
놓여집니다. 수행됩니다.
/*+ MERGE (table) */
causes Oracle to evaluate complex views or subqueries before
the surrounding query
오라클이 그 둘러싸는 질의 전에 복잡한 뷰나 부속 조회를 평가하게 합니다.
/*+ NO_MERGE (table) */
causes Oracle not to merge mergeable views
오라클이 mergeable 뷰를 합병하지 않게 하지 않습니다
/*+ PUSH_JOIN_PRED (table) */
causes the optimizer to evaluate, on a cost basis, whether or
not to push individual join predicates into the view
개개 접합을 미는 것이 그 뷰 안으로 단정 하든 간에 비용 방식으로 최적자가
평가하게 합니다.
/*+ NO_PUSH_JOIN_PRED (table) */
Prevents pushing of a join predicate into the view
접합 술부 중에서 그 뷰로 밀면서, 막는
/*+ PUSH_SUBQ */
causes nonmerged subqueries to be evaluated at the earliest
possible place in the execution plan
원인은 그 실행 계획에서의 가장 이른 가능한 장소에 평가되는 부속 조회를
nonmerged했습니다.
/*+ STAR_TRANSFORMATION */
makes the optimizer use the best plan in which the transformation
has been used.
최적자가 그 변형이 사용된 가장 좋은 계획을 사용하는 제작