윈 토토 : 문서 : 9.4 | |||
---|---|---|---|
PostgreSQL : 문서 : 9.4 : 내장 운영자 배트맨 토토 | 사설 토토 사이트 : 문서 : 9.4 : Gist Indexes | 56 장. Gist Indexes | 토토 꽁 머니 : 문서 : 9.4 : 구현 |
전통적으로 새로운 윈 토토 액세스 방법을 구현하면 많은 어려운 작업이 의미했습니다. Lock Manager 및 Write-Ahead Log와 같은 데이터베이스의 내부 작업을 이해해야했습니다. 그만큼gist인터페이스에는 높은 수준의 추상화가있어 액세스 방법 구현자가 액세스하는 데이터 유형의 의미를 구현해야합니다. 그만큼gist레이어 자체는 동시성, 트리 구조 로깅 및 검색을 처리합니다.
이 확장 성은 처리 할 수있는 데이터 측면에서 다른 표준 검색 트리의 확장 성과 혼동되어서는 안됩니다. 예를 들어,윈 토토확장 가능한 B- 트리 및 해시 윈 토토를 지원합니다. 그것은 당신이 사용할 수 있다는 것을 의미합니다윈 토토원하는 데이터 유형을 통해 B- 트리 또는 해시를 구축하려면. 그러나 B- 트리는 범위 만 지원합니다.<, =, ), 해시 윈 토토는 평등 쿼리 만 지원합니다.
윈 토토 인 경우 A가있는 이미지 컬렉션이 표시됩니다.윈 토토B- 트리,와 같은 쿼리 만 발행 할 수 있습니다."imagex는 imagey와 같다", "imagex는 imagey보다 작습니다"및"imagex가 imagey보다 큽니다". 당신이 정의하는 방법에 따라"Equals", ""보다 작습니다.and""보다 큰 "이 맥락에서 이것은 유용 할 수 있습니다. 그러나 A를 사용함으로써gist기반 윈 토토, 도메인 별 질문을하는 방법을 만들 수 있습니다"말의 모든 이미지 찾기"또는"과다 노출 된 모든 이미지 찾기".
a를 얻는 데 필요한 모든 것gist액세스 방법 UP 및 실행은 트리의 키의 동작을 정의하는 여러 사용자 정의 메소드를 구현하는 것입니다. 물론 이러한 방법은 멋진 쿼리를 지원하기 위해 매우 화려해야하지만 모든 표준 쿼리 (B- 트리, R- 트리 등)의 경우 비교적 간단합니다. 요컨대gist일반성, 코드 재사용 및 깨끗한 인터페이스와 함께 확장 성을 결합합니다.
윈 토토 연산자가 클래스하는 7 가지 방법이 있습니다gist선택 사항을 제공해야합니다. 윈 토토의 정확성은의 적절한 구현으로 보장됩니다.동일
, 일관성
andUnion
방법, 윈 토토의 효율 (크기 및 속도)은에 따라 다릅니다.페널티
andpicksplit
방법. 나머지 두 가지 기본 방법은입니다.압축
andDecompress
, 윈 토토가 색인이 윈 토토와 다른 유형의 내부 트리 데이터를 가질 수 있습니다. 잎은 색인화 된 데이터 유형이어야하며 다른 트리 노드는 C 구조물 일 수 있습니다 (그러나 여전히 따라야합니다윈 토토데이터 유형 규칙은 여기에 참조Varlena가변 크기의 데이터의 경우). 트리의 내부 데이터 유형이 SQL 레벨에 존재하는 경우스토리지옵션운영자 클래스 만들기명령을 사용할 수 있습니다. 선택적 8 번째 방법은입니다.거리
, 운영자 클래스가 순서 스캔을 지원하려는 경우 (가장 가까운 이웃 검색)..
일관성
윈 토토 항목 주어진P및 쿼리 값Q,이 함수는 윈 토토 항목이인지 결정합니다."일관성"쿼리와 함께; 즉, 술어가 될 수 있습니다"indexed_column indexable_operator Q"인덱스 항목으로 표시되는 행에 대해 진실해야합니까? 리프 인덱스 항목의 경우 이것은 인덱스 가능한 조건을 테스트하는 것과 동일하지만 내부 트리 노드의 경우 트리 노드로 표시된 인덱스의 하위 트리를 스캔 해야하는지 여부가 결정됩니다. 결과가true, a다시 확인플래그도 반환해야합니다. 이것은 술어가 확실히 사실인지, 아마도 사실인지를 나타냅니다. 만약에다시 확인=거짓그러면 윈 토토가 술어 조건을 정확하게 테스트 한 반면다시 확인=true행은 후보 일뿐입니다. 이 경우 시스템은 자동으로를 평가합니다.indexable_operator실제 행 값에 대해 실제로 일치하는지 확인하십시오. 이 대회는 허용gist무손실 및 손실 윈 토토 구조를 모두 지원합니다.
theSQL함수 선언은 다음과 같아야합니다 :
함수 생성 또는 교체 my_consistent (내부, data_type, smallint, oid, 내부) Bool을 반환합니다 'module_pathname'으로 언어 C 엄격한;
그리고 C 모듈의 일치하는 코드는이 골격을 따를 수 있습니다.
Datum my_consistent (pg_function_args); pg_function_info_v1 (my_consistent); 자료 my_consistent (pg_function_args) gistentry *entry = (gistentry *) pg_getarg_pointer (0); data_type *query = pg_getarg_data_type_p (1); StrategyNumber Strategy = (StrategyNumber) pg_getarg_uint16 (2); /* OID 하위 유형 = PG_GETARG_OID (3); */ bool *recheck = (bool *) pg_getarg_pointer (4); data_type *key = datumgetDatatype (enther- key); 부리 retval; /* * 전략, 키 및 쿼리의 함수로 반환 값을 결정하십시오. * * gist_leaf (Entry)를 사용하여 인덱스 트리에서 호출되는 위치를 알 수 있습니다. * 예를 들어 = 연산자를 지원할 때 편리합니다 (예 : * 비 잎 노드에서 비 빈 연합 ()을 확인하고 잎의 평등을 확인하십시오. * 노드). */ *다시 확인 = 참; / * 또는 확인이 정확한 경우 false */ pg_return_bool (retval);
여기,키index and의 요소입니다.쿼리윈 토토에서 값을 찾았습니다. 그만큼StrategyNumber매개 변수가 적용되는 운영자 클래스의 운영자가 나타납니다.운영자 클래스 만들기명령. 클래스에 포함 된 연산자에 따라 데이터 유형쿼리연산자마다 다를 수 있지만 위의 골격은 그렇지 않다고 가정합니다.
Union
이 방법은 트리의 정보를 통합합니다. 항목 세트가 주어지면이 기능은 주어진 모든 항목을 나타내는 새 윈 토토 항목을 생성합니다.
theSQL함수 선언은 다음과 같아야합니다 :
함수 생성 또는 교체 my_union (내부, 내부) 내부를 반환합니다 'module_pathname'으로 언어 C 엄격한;
그리고 C 모듈의 일치하는 코드는이 골격을 따라갈 수 있습니다.
Datum my_union (pg_function_args); pg_function_info_v1 (my_union); 자료 my_union (pg_function_args) gistentRyvector *entryVec = (gistentRyvector *) pg_getarg_pointer (0); gistentry *ent = EntryVec- 벡터; data_type *out, *TMP, *오래된; int numranges, i = 0; numranges = actorvevec- n; tmp = DatumgetDatatype (ENT [0] .key); out = tmp; if (numranges == 1) out = data_type_deep_copy (tmp); pg_return_data_type_p (out); for (i = 1; i <numranges; i ++) old = out; tmp = DatumgetDatatype (ent [i] .key); out = my_union_implementation (out, tmp); pg_return_data_type_p (out);
보시다시피,이 골격에서 우리는 데이터 유형을 다루고 있습니다Union (X, Y, Z) = Union (Union (X, Y), Z). 이 경우에는 그렇지 않은 경우 데이터 유형을 지원하기가 쉽습니다.gist지원 방법.
theUnion
구현 함수는 새로 포인터를 반환해야합니다palloc ()
ed 메모리. 입력이 무엇이든 반환 할 수는 없습니다.
compress
윈 토토 페이지의 물리적 저장에 적합한 형식으로 데이터 항목을 변환합니다.
theSQL함수 선언은 다음과 같아야합니다.
함수 생성 또는 교체 my_compress (내부) 내부를 반환합니다 'module_pathname'으로 언어 C 엄격한;
그리고 C 모듈의 일치하는 코드는이 골격을 따를 수 있습니다.
Datum my_compress (pg_function_args); pg_function_info_v1 (my_compress); 자료 my_compress (pg_function_args) gistentry *entry = (gistentry *) pg_getarg_pointer (0); gistentry *retval; if (Entry- Leafkey) / * 입력- 키를 압축 버전으로 교체하십시오 */ compressed_data_type *compressed_data = palloc (sizeof (compressed_data_type)); / *채우기 *Entry- 키 ... */ retval = palloc (sizeof (gistentry)); gistentryinit (*retval, pointergetDatum (compressed_data), Entry- Rel, Entry- Page, Entry- 오프셋, False); 또 다른 / * 일반적으로 우리는 잎이 아닌 항목으로 아무것도 할 필요가 없습니다 */ retval = 진입; pg_return_pointer (retval);
당신은 적응해야합니다compressed_data_type물론 잎 노드를 압축하기 위해 변환하는 특정 유형으로..
귀하의 요구에 따라 압축에주의를 기울여야 할 수도 있습니다null거기에있는 값, 예를 들어 저장(Datum) 0LikeGIST_CIRCLE_COMPRES
Decompress
반대compress
메소드. 데이터 항목의 윈 토토 표현을 데이터베이스에서 조작 할 수있는 형식으로 변환합니다.
theSQL함수 선언은 다음과 같아야합니다.
함수 생성 또는 교체 my_decompress (내부) 내부를 반환합니다 'module_pathname'으로 언어 C 엄격한;
그리고 C 모듈의 일치하는 코드는이 골격을 따라갈 수 있습니다.
Datum my_decompress (pg_function_args); pg_function_info_v1 (my_decompress); 자료 my_decompress (pg_function_args) pg_return_pointer (pg_getarg_pointer (0));
위의 골격은 감압이 필요하지 않은 경우에 적합합니다.
페널티
값을 나타내는 값을 반환합니다"비용"나무의 특정 분기에 새 입구를 삽입하는 것. 항목은 최소 경로에 삽입됩니다페널티
나무에서. 값페널티
는 무분별하지 않아야합니다. 음수 값이 반환되면 0으로 취급됩니다.
theSQL함수 선언은 다음과 같아야합니다.
함수 생성 또는 교체 my_penalty (내부, 내부, 내부) 내부를 반환합니다 'module_pathname'으로 언어 C 엄격한; - 경우에 따라 페널티 기능이 엄격 할 필요는 없습니다
그리고 C 모듈의 일치하는 코드는이 골격을 따라갈 수 있습니다.
Datum my_penalty (pg_function_args); pg_function_info_v1 (my_penalty); 자료 my_penalty (pg_function_args) gistentry *origentry = (gistentry *) pg_getarg_pointer (0); gistentry *newentry = (gistentry *) pg_getarg_pointer (1); float *penalty = (float *) pg_getarg_pointer (2); data_type *orig = datumgetDatatype (Origentry- 키); data_type *new = DatumgetDatatype (newentry- 키); *penalty = my_penalty_implementation (Orig, New); pg_return_pointer (페널티);
the페널티
함수는 인덱스의 우수한 성능에 중요합니다. 트리에 새 항목을 추가 할 위치를 선택할 때 따라야 할 지점을 결정하기 위해 삽입 시간에 사용됩니다. 쿼리 시점에서 인덱스의 균형이 높아질수록 조회가 빨라집니다.
picksplit
윈 토토 페이지 분할이 필요한 경우이 기능은 페이지의 항목이 이전 페이지에 유지되고 새 페이지로 이동할 것인지 결정합니다..
theSQL함수 선언은 다음과 같아야합니다.
함수 생성 또는 교체 my_picksplit (내부, 내부) 내부를 반환합니다 'module_pathname'으로 언어 C 엄격한;
그리고 C 모듈의 일치하는 코드는이 골격을 따라갈 수 있습니다.
Datum my_picksplit (pg_function_args); pg_function_info_v1 (my_picksplit); 자료 my_picksplit (pg_function_args) gistentRyvector *entryVec = (gistentRyvector *) pg_getarg_pointer (0); OffsetNumber maxoff = EntryVec- n -1; gistentry *ent = EntryVec- 벡터; gist_splitvec *v = (gist_splitvec *) pg_getarg_pointer (1); INT I, nbytes; 오프셋 너버 *왼쪽, *오른쪽; data_type *tmp_union; data_type *Unionl; data_type *Unionr; gistentry ** raw_entryvec; maxoff = EntryVec- n -1; nbytes = (maxoff + 1) * sizeof (offsetNumber); v- spl_left = (OffsetNumber *) palloc (nbytes); 왼쪽 = v- spl_left; v- spl_nleft = 0; v- spl_right = (OffsetNumber *) palloc (nbytes); 오른쪽 = v- spl_right; v- spl_nright = 0; Unionl = null; Unionr = null; /* 원시 입력 벡터를 초기화합니다. */ raw_entryvec = (gistentry **) malloc (EntryVec- n *sizeof (void *)); for (i = firstOffSetNumber; i <= maxOff; i = OffSetNumberNext (i)) raw_entryvec [i] = & (EntryVec- 벡터 [i]); for (i = firstOffSetNumber; i <= maxOff; i = OffSetNumberNext (i)) int real_index = raw_entryvec [i] - EntryVec- 벡터; TMP_UNION = DATUMGETDATATYPE (EntryVec- 벡터 [real_index] .key); assert (tmp_union! = null); /* * 인덱스 항목을 넣을 위치를 선택하고 Unionl 및 UnionR 업데이트 * 따라서. v- spl_left 또는에 대한 항목을 추가하십시오 * v- spl_right, 카운터에 관심이 있습니다. */ if (my_choice_is_left (Unionl, Curl, Unionr, Curr)) if (UnionL == null) Unionl = tmp_union; 또 다른 Unionl = my_union_implementation (Unionl, Tmp_union); *왼쪽 = real_index; ++ 왼쪽; ++ (v- spl_nleft); 또 다른 /* * 오른쪽에 동일합니다 */ v- spl_ldatum = DataTypeGetDatum (Unionl); v- spl_rdatum = DataTypeGetDatum (UnionR); pg_return_pointer (V);
좋아요페널티
, Thepicksplit
함수는 윈 토토의 우수한 성능에 중요합니다. 적절한 디자인페널티
andpicksplit
구현은 성능이 우수한 구현의 과제입니다gist인덱스 거짓말.
동일
두 인덱스 항목이 동일하면, 그렇지 않으면 false..
theSQL함수 선언은 다음과 같아야합니다.
함수 생성 또는 교체 my_same (내부, 내부, 내부) 내부를 반환합니다 'module_pathname'으로 언어 C 엄격한;
그리고 C 모듈의 일치하는 코드는이 골격을 따라갈 수 있습니다.
Datum my_same (pg_function_args); PG_FUNCTION_INFO_V1(my_same); 자료 my_same (pg_function_args) prefix_ra윈 토토e *v1 = pg_getarg_prefix_ra윈 토토e_p (0); prefix_ra윈 토토e *v2 = pg_getarg_prefix_ra윈 토토e_p (1); bool *result = (bool *) pg_getarg_pointer (2); *결과 = my_eq (v1, v2); pg_return_pointer (결과);
역사적 이유로동일
함수는 부울 결과를 반환하지 않습니다. 대신 깃발을 세 번째 인수로 표시된 위치에 저장해야합니다.
거리
윈 토토 항목이 주어진P및 쿼리 값Q,이 함수는 윈 토토 항목을 결정합니다"거리"쿼리 값에서. 운영자 클래스에 주문 연산자가 포함 된 경우이 기능을 제공해야합니다. 주문 연산자를 사용하는 쿼리는 가장 작은 인덱스 항목을 반환하여 구현됩니다."거리"값을 먼저 값이므로 결과는 운영자의 의미와 일치해야합니다. 리프 인덱스 항목의 경우 결과는 인덱스 항목까지의 거리를 나타냅니다. 내부 트리 노드의 경우 결과는 모든 어린이 입국이 가질 수있는 가장 작은 거리 여야합니다.
theSQL함수 선언은 다음과 같아야합니다 :
함수 생성 또는 교체 my_distance (내부, data_type, smallint, oid) float8을 반환합니다 'module_pathname'으로 언어 C 엄격한;
그리고 C 모듈의 일치하는 코드는이 골격을 따를 수 있습니다.
Datum my_distance (pg_function_args); pg_function_info_v1 (my_distance); 자료 my_distance (pg_function_args) gistentry *entry = (gistentry *) pg_getarg_pointer (0); data_type *query = pg_getarg_data_type_p (1); StrategyNumber Strategy = (StrategyNumber) pg_getarg_uint16 (2); /* OID 하위 유형 = PG_GETARG_OID (3); */ data_type *key = datumgetDatatype (enther- key); 이중 retval; /* * 전략, 키 및 쿼리의 함수로 반환 값을 결정하십시오. */ pg_return_float8 (retval);
거리
함수는의 인수와 동일합니다.일관성
기능 - 재확인 플래그가 사용되지 않는 경우를 제외하고. 튜플이 반환되면 튜플을 다시 주문할 수있는 방법이 없기 때문에 리프 인덱스 입구까지의 거리는 항상 정확하게 결정되어야합니다. 내부 트리 노드까지의 거리를 결정할 때는 근사치가 허용됩니다. 결과는 어린이의 실제 거리보다 크지 않습니다. 따라서, 예를 들어, 경계 박스까지의 거리는 일반적으로 기하학적 응용 분야에서 충분합니다. 결과 값은 유한 할 수 있습니다float8값. (무한대 및 마이너스 무한대는 내부적으로 널과 같은 케이스를 처리하는 데 사용되므로 권장되지 않습니다.거리
함수는이 값을 반환합니다.)
모든 GIST 지원 방법은 일반적으로 단기간 메모리 컨텍스트에서 호출됩니다. 즉,CurrentMemoryContext각 튜플이 처리되면 재설정됩니다. 그러므로 당신이 palloc의 모든 것을 pfree에 대해 걱정하는 것은 그리 중요하지 않습니다. 그러나 경우에 따라 지원 방법이 반복 된 호출에서 데이터를 캐시하는 데 유용합니다. 그렇게하려면 더 긴 수명 데이터를 할당fcinfo- flinfo- fn_mcxtfcinfo- flinfo- fn_extra. 이러한 데이터는 인덱스 작동 수명 (예 : 단일 GIST 인덱스 스캔, 인덱스 빌드 또는 인덱스 튜플 삽입)에서 살아남을 것입니다. a를 교체 할 때 이전 값을 pfree에주의하십시오.fn_extra값 또는 작동 기간 동안 누출이 축적됩니다.