색인 연산자 클래스에는 7가지 메소드가 있습니다.GiST제공해야 합니다. 정확성
인덱스의 올바른 토토 결과을 통해 보장됩니다.같은, 일관적인그리고연합방법, 효율성(크기 및
속도) 인덱스의 속도는 다음에 따라 달라집니다.페널티그리고picksplit메소드. 나머지 두 가지 방법
이다압축그리고압축해제, 이는 토토 결과가
색인화하는 데이터와 다른 유형의 내부 트리 데이터입니다.
리프는 토토 결과 데이터 유형이어야 하고, 다른 리프는 토토 결과 데이터 유형이어야 합니다.
트리 노드는 어떤 C 구조체라도 될 수 있습니다. (하지만 여전히 따라야 합니다.포스트그레SQL여기서 데이터 유형 규칙은,
자세히 알아보기발레나가변 크기의 경우
데이터). 트리의 내부 데이터 유형이 SQL 수준에 존재하는 경우저장옵션연산자 클래스 생성명령을 사용할 수 있습니다.
일관됨색인 항목 제공p그리고 쿼리 값q, 이 함수 색인 항목이 다음과 같은지 여부를 결정합니다."일관적"쿼리로; 즉, 할 수 있다 술어"indexed_column indexable_operator q"다음으로 표시되는 모든 행에 대해 true입니다. 색인 항목? 리프 인덱스 항목의 경우 이는 동일합니다. 인덱싱 가능한 조건을 테스트하는 동안 내부 트리 노드는 스캔이 필요한지 여부를 결정합니다. 트리 노드가 나타내는 인덱스의 하위 트리입니다. 언제 결과는참, 아다시 확인플래그도 반환되어야 합니다. 이 술어가 확실히 참인지 아니면 단지 참인지를 나타냅니다. 아마도 사실일 것이다. 만일재확인 = 거짓그러면 색인이 테스트되었습니다. 술어 조건을 정확하게, 반면에 if다시 확인 = 참행은 후보 일치일 뿐입니다. 이 경우 시스템은 자동으로 평가합니다.indexable_operator실제와 반대 행 값을 사용하여 실제로 일치하는지 확인합니다. 이 컨벤션 허용합니다지스트지원하다 무손실 및 손실 인덱스 구조 모두.
그SQL선언 함수는 다음과 같아야 합니다:
함수 생성 또는 교체 my_contant(internal, data_type, smallint, oid, Internal) 반환 부울 AS 'MODULE_PATHNAME' 언어 C 엄격;
그러면 C 모듈의 일치 코드가 뒤따를 수 있습니다. 이 뼈대:
데이텀 my_contant(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(내_일관성);
데이텀
내_일관성(PG_FUNCTION_ARGS)
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
data_type *query = PG_GETARG_DATA_TYPE_P(1);
StrategyNumber 전략 = (StrategyNumber) PG_GETARG_UINT16(2);
/* Oid 하위 유형 = PG_GETARG_OID(3); */
bool *재확인 = (bool *) PG_GETARG_POINTER(4);
data_type *key = DatumGetDataType(entry-key);
부울 복구;
/*
* 전략, 키 및 쿼리의 함수로 반환 값을 결정합니다.
*
* 인덱스 트리에서 호출된 위치를 확인하려면 GIST_LEAF(entry)를 사용하세요.
* 예를 들어 = 연산자를 지원할 때 유용합니다(예:
* 리프 노드가 아닌 노드에서 비어 있지 않은 Union()과 리프에서 동일성을 확인합니다.
* 노드).
*/
*재확인 = 사실; /* 또는 검사가 정확하면 false */
PG_RETURN_BOOL(복귀);
여기,키은 다음의 요소입니다. 색인 및질의값은 지수에서 찾아봤다.전략번호매개변수는 다음을 나타냅니다. 연산자 클래스의 연산자가 적용되고 있습니다. 의 연산자 번호 중 하나와 일치합니다.연산자 클래스 생성명령. 에 따라 클래스에 포함시킨 연산자, 데이터 유형질의다음에 따라 달라질 수 있습니다. 연산자이지만 위의 뼈대에서는 그렇지 않다고 가정합니다.
연합이 방법은 트리의 정보를 통합합니다. 주어진 항목 세트, 이 함수는 새로운 색인 항목을 생성합니다. 이는 주어진 모든 항목을 나타냅니다.
그SQL선언 함수는 다음과 같아야 합니다:
함수 생성 또는 교체 my_union(내부, 내부) 내부 반환 AS 'MODULE_PATHNAME' 언어 C 엄격;
그러면 C 모듈의 일치 코드가 뒤따를 수 있습니다. 이 뼈대:
데이텀 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-벡터;
데이터 유형 *아웃,
*tmp,
*오래된;
정수 숫자 범위,
나는 = 0;
숫자 범위 = 항목vec-n;
tmp = DatumGetDataType(ent[0].key);
아웃 = tmp;
if (숫자 범위 == 1)
출력 = data_type_deep_copy(tmp);
PG_RETURN_DATA_TYPE_P(아웃);
for (i = 1; i < 숫자 범위; i++)
낡은 = 아웃;
tmp = DatumGetDataType(ent[i].key);
out = my_union_implementation(out, tmp);
PG_RETURN_DATA_TYPE_P(아웃);
보시다시피, 이 뼈대에서 우리는 데이터 유형 여기서결합(X, Y, Z) = Union(합집합(X, Y), Z). 지원하기에는 충분히 쉽습니다. 그렇지 않은 경우 데이터 유형을 구현하여 이것의 적절한 결합 알고리즘GiST지원 방법.
그연합토토 결과
함수는 새로 포인터를 반환해야 합니다.팔록()ed 메모리입니다. 그냥 돌아오면 안 돼
입력이 무엇이든.
압축데이터 항목을 다음에 적합한 형식으로 변환합니다. 인덱스 페이지의 물리적 저장 공간입니다.
그SQL선언 함수는 다음과 같아야 합니다:
함수 생성 또는 교체 my_compress(내부) 내부 반환 AS 'MODULE_PATHNAME' 언어 C 엄격;
그러면 C 모듈의 일치 코드가 뒤따를 수 있습니다. 이 뼈대:
데이텀 my_compress(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(my_compress);
데이텀
my_compress(PG_FUNCTION_ARGS)
GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
GISTENTRY *재발;
if (엔트리-리프키)
/* 항목-키를 압축된 버전으로 교체 */
pressed_data_type *compressed_data = palloc(sizeof(compressed_data_type));
/* 항목-키의 *compressed_data 채우기 ... */
retval = palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(compressed_data),
항목-상대, 항목-페이지, 항목-오프셋, FALSE);
그렇지 않으면
/* 일반적으로 리프가 아닌 항목에는 아무 것도 할 필요가 없습니다 */
retval = 항목;
PG_RETURN_POINTER(복귀);
당신은 적응해야 합니다압축_데이터_유형특정한 것에 리프를 압축하기 위해 변환하려는 유형 물론 노드입니다.
귀하의 필요에 따라 관심을 기울여야 할 수도 있습니다. 압축에 대해NULL값 예를 들어 저장 중입니다.(데이텀) 0좋아요gist_circle_compress그렇습니다.
압축해제의 반대압축방법. 인덱스를 변환합니다
데이터 항목을 다음과 같은 형식으로 표현합니다.
데이터베이스에 의해 조작되었습니다.
그SQL선언 함수는 다음과 같아야 합니다:
함수 생성 또는 교체 my_decompress(내부) 내부 반환 AS 'MODULE_PATHNAME' 언어 C 엄격;
그리고 C 모듈의 일치 코드는 다음과 같습니다. 이 뼈대:
데이텀 my_decompress(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(my_decompress);
데이텀
my_decompress(PG_FUNCTION_ARGS)
PG_RETURN_POINTER(PG_GETARG_POINTER(0));
위의 뼈대는 다음과 같은 경우에 적합합니다. 감압이 필요합니다.
페널티다음을 나타내는 값을 반환합니다."비용"새 항목을
나무의 특정 가지. 항목이 아래로 삽입됩니다.
최소의 경로벌칙에
나무. 반환된 값벌칙음수가 아니어야 합니다. 만약
음수 값이 반환되면 0으로 처리됩니다.
그SQL선언 함수는 다음과 같아야 합니다:
함수 생성 또는 교체 my_penalty(내부, 내부, 내부) 내부 반환 AS 'MODULE_PATHNAME' 언어 C 엄격; -- 어떤 경우에는 페널티 함수가 엄격할 필요가 없습니다.
그러면 C 모듈의 일치 코드가 뒤따를 수 있습니다. 이 뼈대:
데이텀 my_penalty(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(my_penalty);
데이텀
my_penalty(PG_FUNCTION_ARGS)
GISTENTRY *오리젠트리 = (GISTENTRY *) PG_GETARG_POINTER(0);
GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
float *페널티 = (float *) PG_GETARG_POINTER(2);
data_type *orig = DatumGetDataType(origentry-key);
data_type *new = DatumGetDataType(newentry-key);
*penalty = my_penalty_implementation(orig, new);
PG_RETURN_POINTER(페널티);
그벌칙함수는
토토 결과의 좋은 성능에 중요합니다. 익숙해질 거야
언제 따라갈 분기를 결정하기 위한 삽입 시간
트리에서 새 항목을 추가할 위치를 선택합니다. 쿼리 시
시간이 지남에 따라 지수가 균형을 이룰수록 속도가 빨라집니다.
조회합니다.
picksplit인덱스 페이지 분할이 필요할 때 이 기능은 페이지의 어떤 항목을 이전 페이지에 유지할지 결정합니다. 페이지가 새 페이지로 이동됩니다.
그SQL선언 함수는 다음과 같아야 합니다:
함수 생성 또는 교체 my_picksplit(내부, 내부) 내부 반환 AS 'MODULE_PATHNAME' 언어 C 엄격;
그리고 C 모듈의 일치 코드는 다음과 같습니다. 이 뼈대:
데이텀 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);
나는,
n바이트;
오프셋 번호 *왼쪽,
*맞아요;
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;
유니온L = NULL;
유니온R = 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, 컬, 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);
좋아요페널티, 그picksplit기능이 중요합니다
토토 결과의 좋은 성능을 위해. 적합한 디자인페널티그리고picksplit토토 결과은
좋은 성과를 토토 결과하는 데 도전GiST거짓말을 색인화합니다.
같은두 개의 색인 항목이 동일하면 true를 반환하고 false를 반환합니다. 그렇지 않으면.
그SQL선언 함수는 다음과 같아야 합니다:
함수 생성 또는 교체 my_same(내부, 내부, 내부) 내부 반환 AS 'MODULE_PATHNAME' 언어 C 엄격;
그리고 C 모듈의 일치 코드는 다음과 같습니다. 이 뼈대:
데이텀 my_same(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(my_same);
데이텀
내_동일(PG_FUNCTION_ARGS)
접두사_범위 *v1 = PG_GETARG_PREFIX_RANGE_P(0);
prefix_range *v2 = PG_GETARG_PREFIX_RANGE_P(1);
bool *result = (bool *) PG_GETARG_POINTER(2);
*결과 = my_eq(v1, v2);
PG_RETURN_POINTER(결과);
역사적인 이유로,같은함수는 단지 다음을 반환하지 않습니다.
부울 결과; 대신에 플래그를 저장해야 합니다.
세 번째 인수로 표시된 위치입니다.