롤 토토 : 문서 : 9.5 : 롤 토토 | |||
---|---|---|---|
PostgreSQL : 문서 : 9.5 : 토토 결과 운영자 클래스 | PostgreSQL : 문서 : 9.5 : 사설 토토 Indexes | 60 장. SP-Gist Indexes | PostgreSQL : 문서 : 9.5 : 사설 토토 사이트 |
SP-Gist높은 수준의 추상화와 인터페이스를 제공하므로 액세스 방법 개발자는 주어진 데이터 유형에 특정한 메소드 만 구현해야합니다. 그만큼SP-GistCore는 효율적인 디스크 매핑 및 트리 구조 검색을 담당합니다. 또한 동시성 및 로깅 고려 사항을 처리합니다.
leaf tuples ofSP-Gist트리에는 인덱스 열과 동일한 데이터 유형의 값이 포함되어 있습니다. 루트 레벨의 잎 튜플은 항상 원래 인덱스 데이터 값을 포함하지만, 낮은 레벨의 잎 튜플은 접미사와 같은 압축 된 표현 만 포함 할 수 있습니다. 이 경우 운영자 클래스 지원 기능은 잎 수준에 도달하기 위해 통과 된 내부 튜플에서 축적 된 정보를 사용하여 원래 값을 재구성 할 수 있어야합니다..
내부 와이즈 토토은 검색 트리의 분기 지점이기 때문에 더 복잡합니다. 각 내부 와이즈 토토에는 하나 이상의 세트가 포함됩니다노드, 유사한 잎 값의 그룹을 나타냅니다. 노드에는 다운 링크가 포함되어있어 다른, 하단 수준 내부 튜플 또는 동일한 인덱스 페이지에있는 짧은 잎 튜플 목록이 포함되어 있습니다. 각 노드에는에레이블예를 들어, Radix 트리에서 노드 레이블은 문자열 값의 다음 문자 일 수 있습니다. 선택적으로, 내부 튜플은 a를 가질 수 있습니다.prefix모든 회원을 설명하는 값. radix 트리에서 이것은 표현 된 문자열의 일반적인 접두사 일 수 있습니다. 접두사 값은 반드시 접두사 일 필요는 없지만 운영자 클래스가 필요한 데이터 일 수 있습니다. 예를 들어, 쿼드 트리에서는 4 개의 사분면이 측정되는 중심점을 저장할 수 있습니다. 그런 다음 쿼드 트리 내부 튜플에는이 중심점 주변의 사분면에 해당하는 4 개의 노드가 포함됩니다.
일부 트리 알고리즘은 현재 튜플의 레벨 (또는 깊이)에 대한 지식이 필요하므로SP-GistCore는 운영자 클래스가 트리를 내려 가면서 레벨 카운팅을 관리 할 가능성을 제공합니다. 필요할 때 대표 값을 점진적으로 재구성하는데도 도움이됩니다.
참고 :thesp-gist핵심 코드는 NULL 항목을 관리합니다. 하지만sp-gist인덱스 인덱스 열에 nulls에 대한 저장 항목이 있습니다. 이는 인덱스 운영자 클래스 코드에서 숨겨져 있습니다. 널 인덱스 항목 또는 검색 조건은 운영자 클래스 메소드에 전달되지 않습니다. (SP-Gist운영자는 엄격하고 널 값에 대해 성공할 수 없습니다.) 널 값은 여기에서 더 이상 논의되지 않습니다.
인덱스 운영자가 클래스하는 5 가지 사용자 정의 메소드SP-Gist제공해야합니다. 5 명 모두 2 개를 수락하는 협약을 따릅니다내부인수, 첫 번째는 지지대에 대한 입력 값을 포함하는 C 구조물에 대한 포인터이며, 두 번째 인수는 출력 값을 배치 해야하는 C 구조물에 대한 포인터입니다. 4 가지 방법은 방금 retlyvoid, 모든 결과가 출력 구조물에 나타나기 때문에; 하지만Leaf_consistent
추가로 a를 반환합니다.부울결과. 방법은 입력 스트러크의 필드를 수정해서는 안됩니다. 모든 경우에, 출력 구조는 사용자 정의 메소드를 호출하기 전에 0으로 초기화됩니다.
5 가지 사용자 정의 방법은 다음과 같습니다.
config
접두사 및 노드 레이블 데이터 유형의 데이터 유형 OID를 포함하여 인덱스 구현에 대한 정적 정보를 반환합니다.
theSQL함수 선언은 다음과 같아야합니다.
함수 생성 my_config (내부, 내부) 반환 void ...
첫 번째 인수는 a에 대한 포인터입니다.SPGCONFIGINC 구조, 함수에 대한 입력 데이터를 포함합니다. 두 번째 인수는 A에 대한 포인터입니다.SPGCONFIGOUTC 구조물, 함수가 결과 데이터로 채워야합니다.
typedef struct spgconfigin Oid Atttype; / * 색인화 할 데이터 유형 */ spgconfigin; typedef struct spgconfigout OID PREFIXTYPE; / * 내부 튜플 접두사의 데이터 유형 */ OID LABELTYPE; / * 내부 튜플 노드 레이블의 데이터 유형 */ BOOL CANRETURNDATA; / * opclass는 원본 데이터를 재구성 할 수 있습니다 */ BOOL LONGVALUESOK; / * opclass는 값에 대처할 수 있습니다 1 페이지 */ spgconfigout;
atttype12677_12850
접두사를 사용하지 않는 운영자 클래스의 경우PrefixType로 설정할 수 있습니다voidoid. 마찬가지로 노드 레이블을 사용하지 않는 운영자 클래스의 경우labelType로 설정할 수 있습니다voidoid. CanreturnData운영자 클래스가 원래 보관 된 인덱스 값을 재구성 할 수있는 경우 true를 설정해야합니다.LongValuesok만 맞아야합니다.atttype가변 길이이며 연산자 클래스는 반복 된 접미사를 통해 긴 값을 분할 할 수 있습니다 (참조섹션 60.4.1).
선택
새 값을 내부 튜플에 삽입하는 방법을 선택합니다.
theSQL함수 선언은 다음과 같아야합니다.
함수 생성 my_choose (내부, 내부) 반환 void ...
첫 번째 인수는 a에 대한 포인터입니다.SpgchooseinC struct, 함수에 대한 입력 데이터를 포함합니다. 두 번째 인수는 A에 대한 포인터입니다.spgchooseoutC 구조물, 함수가 결과 데이터로 채워야합니다.
typedef struct spgchoosein 데이텀 데이텀; / * 색인화 될 원본 데이텀 */ 데이텀 리프 듀다; / * 잎에 저장 될 전류 데이텀 */ int 레벨; / * 현재 레벨 (0에서 계산) */ / * 현재 내부 튜플의 데이터 */ BOOL ALLTHESAME; /* 튜플은 모든 것이 표시되어 있습니까? */ BOOL HASPREFIX; /* 튜플에는 접두사가 있습니까? */ Datum Prefixdatum; / * 그렇다면 접두사 값 */ int nnodes; / * 내부 튜플의 노드 수 */ Datum *Nodelabels; / * 노드 레이블 값 (null이 없음) */ spgchoosein; typedef enum spgchooseresulttype spgmatchnode = 1, / * 기존 노드로 내려갑니다 * / spgaddnode, / * 내부 튜플에 노드를 추가하십시오 * / spgsplittuple / * 분할 내부 튜플 (접두사 변경) * / spgchooseresulttype; typedef struct spgchooseout spgchooseresulttype resulttype; / * 액션 코드, 위 참조 */ 노동 조합 spgmatchnode * /struct / * 결과 * / int noden; / *이 노드로 내려갑니다 (0에서 index) */ int levelAdd; / *이 정도의 증분 레벨 */ 데이텀리스트 덤; / * 새로운 잎 기준 */ matchNode; spgaddnode * /struct / * 결과 * / 데이텀 노 델라벨; / * 새 노드 레이블 */ int noden; / * 삽입 할 위치 (0에서 색인) */ addnode; spgsplittuple에 대한 struct / * 결과 * / / * 하나의 노드로 새로운 내부 튜플을 형성하는 정보 */ 부울 접두사 hasprefix; /* 튜플은 접두사가 있어야합니까? */ Datum PrefixprefixDatum; / * 그렇다면 그 가치 */ 데이텀 노 델라벨; / * 노드 레이블 */ / * 모든 오래된 노드와 함께 새로운 하위 수준 내부 튜플을 형성하는 정보 */ bool postfixhasprefix; /* 튜플은 접두사가 있어야합니까? */ Datum postfixprefixdatum; / * 그렇다면 그 가치 */ splittuple; 결과; spgchooseout;
Datum지수에 삽입 될 원래 데이텀입니다.Leafdatum처음에는와 동일합니다.Datum, 그러나이면 트리의 낮은 레벨에서 변경 될 수 있습니다.선택
또는picksplit
메소드 변경. 삽입 검색이 리프 페이지에 도달하면 현재 값Leafdatum새로 생성 된 잎 와이즈 토토에 저장 될 것입니다.레벨는 루트 레벨에서 0에서 시작하는 현재 튜플 레벨입니다.Allthesame전류 내부 튜플이 여러 동등한 노드를 포함하는 것으로 표시된 경우 참조 (참조섹션 60.4.3).hasprefix전류 내부 튜플에 접두사가 포함되어 있으면 참입니다. 그렇다면,PrefixDatum값입니다.nnodes내부 튜플에 포함 된 자식 노드의 수는Nodelabels라벨이없는 경우 레이블 값의 배열이거나 널
the선택
함수는 새 값이 기존 하위 노드 중 하나와 일치하거나 새 하위 노드가 추가되어야한다는 것을 결정할 수 있거나 새 값이 튜플 접두사와 일치하지 않으므로 내부 튜플을 분할하여 덜 제한적인 접두사를 생성해야합니다..
새 값이 기존 자식 노드 중 하나와 일치하는 경우resultTypetoSPGMATCHNODE. 세트Noden노드 어레이의 해당 노드의 인덱스 (0에서)까지. 세트levelAdd증분으로레벨해당 노드를 통해 내림차순으로 인해 발생하거나 연산자 클래스가 레벨을 사용하지 않으면 0으로 남겨 둡니다. 세트RestDatum동등한Datum운영자 클래스가 한 레벨에서 다음 레벨로 데이텀을 수정하지 않거나 다른 방법으로 사용될 수정 된 값으로 설정Leafdatum다음 단계에서.
새 하위 노드를 추가 해야하는 경우resultTypetoSpgaddnode. 세트Nodelabel새 노드에 사용될 레이블에Noden노드 어레이에 노드를 삽입 할 인덱스 (0에서)까지. 노드가 추가 된 후선택
함수는 수정 된 내부 튜플로 다시 호출됩니다. 그 전화는를 초래해야합니다.SPGMATCHNODE결과.
새 값이 와이즈 토토 접두사와 일치하지 않는 경우resultTypetospgsplittuple. 이 동작은 기존의 모든 노드를 새로운 하위 레벨 내부 튜플로 이동시키고 기존 내부 튜플을 새로운 하단 내부 튜플에 연결하는 단일 노드를 갖는 튜플로 대체합니다. 세트prefixhasprefix새 와이즈 토토에 접두사가 있어야하는지 여부를 나타내려면prefixprefixDatum접두사 값으로. 이 새로운 접두사 값은 색인화 할 새 값을 수락하기 위해 원본보다 충분히 덜 제한적이어야하며, 원래 접두사보다 더 이상 안됩니다. 세트Nodelabel새로운 하위 레벨 내부 튜플을 가리킬 노드에 사용되는 레이블로. 세트postfixhasprefix새로운 하위 수준의 내부 튜플에 접두사가 있어야하는지 여부를 나타내려면PostFixPrefixDatum접두사 값으로. 이 두 접두사와 추가 레이블의 조합은 원래 접두사와 동일한 의미를 가져야합니다. 새로운 하위 레벨 튜플로 이동 한 노드 레이블을 변경하거나 하위 인덱스 항목을 변경할 수있는 기회가 없기 때문입니다. 노드가 분할 된 후선택
함수는 교체 내부 튜플로 다시 호출됩니다. 그 전화는 일반적으로를 초래할 것입니다.SPGADDNODE결과, 아마도 분할 단계에 추가 된 노드 레이블은 새 값과 일치하지 않기 때문에; 그 후, 마지막으로 돌아 오는 세 번째 전화가있을 것입니다SPGMATCHNODE삽입이 잎 수준으로 내려 오도록 허용합니다.
picksplit
잎 튜플 세트에 새로운 내부 튜플을 만드는 방법을 결정합니다.
theSQL함수 선언은 다음과 같아야합니다.
함수 생성 my_picksplit (내부, 내부) 반환 void ...
첫 번째 인수는 a에 대한 포인터입니다.SPGPICKSPLITINC struct, 함수에 대한 입력 데이터를 포함합니다. 두 번째 인수는 A에 대한 포인터입니다.SPGPICKSPLITOUTC 구조물, 함수가 결과 데이터로 채워야합니다.
typedef struct spgpicksplitin int ntuples; / * 잎 튜플 수 */ 데이텀 *데이텀; / * 그들의 데이텀 (길이의 배열 ntuples) */ int 레벨; / * 현재 레벨 (0에서 계산) */ spgpicksplitin; typedef struct spgpicksplitout BOOL HASPREFIX; /* 새로운 내부 튜플이 접두사가 있어야합니까? */ Datum Prefixdatum; / * 그렇다면 그 가치 */ int nnodes; / * 새 내부 튜플에 대한 노드 수 */ Datum *Nodelabels; / * 레이블 (또는 레이블 없음) */ int *maptuplestonodes; / * 각 잎에 대한 노드 인덱스 */ 데이텀 *리프트 수스 룸; / * 각각의 새로운 잎 튜플에 보관할 데이 텀 */ spgpicksplitout;
ntuples제공된 잎 와이즈 토토의 수입니다.Datums는 데이텀 값의 배열입니다.레벨| 모든 잎 튜플이 공유하는 현재 레벨이며, 새로운 내부 튜플의 수준이 될 것입니다.
SEThasprefix새 내부 튜플에 접두사가 있어야하는지 여부를 나타내려면prefixdatum접두사 값으로. 세트nnodes새로운 내부 튜플이 포함 할 노드 수를 나타내고 설정Nodelabels레이블 값의 배열로. (노드에 레이블이 필요하지 않은 경우Nodelabels보다섹션 60.4.2자세한 내용.) SETMaptuplestonodes각 리프 튜플을 할당 해야하는 노드의 인덱스 (0에서)를 제공하는 배열로. 세트Leaftupledatums새로운 잎 와이즈 토토에 저장 될 값의 배열로 (입력과 동일합니다Datums운영자 클래스가 한 레벨에서 다음 레벨에서 다음 레벨로 데이 텀을 수정하지 않는 경우).picksplit
함수는 palloc'ing the에 책임이 있습니다.Nodelabels, MaptuplestonodesandLeaftupledatums배열.
둘 이상의 잎 와이즈 토토이 제공되면picksplit
함수는 둘 이상의 노드로 분류됩니다. 그렇지 않으면 잎 튜플을 여러 페이지에 걸쳐 분할 할 수 없습니다. 이는이 작업의 궁극적 인 목적입니다. 따라서이면picksplit
함수는 모든 잎 튜플을 동일한 노드에 배치하게됩니다. 코어 SP-Gist 코드는 해당 결정을 무시하고 내부 튜플이 무작위로 여러 동일하게 표지 된 노드에 지정되는 내부 튜플을 생성합니다. 그러한 튜플은 표시되어 있습니다Allthesame이것이 일어났다는 것을 나타냅니다. 그만큼선택
andInner_consistent
기능은 그러한 내부 튜플에 적합한주의를 기울여야합니다. 보다섹션 60.4.3자세한 내용은
picksplit
단일 잎 와이즈 토토에만 적용 할 수 있습니다.config
함수 세트LongValuesoktrue로, PAT보다 큰 입력 값이 제공되었습니다. 이 경우 작업의 점은 접두사를 벗기고 새롭고 짧은 잎 기준 값을 생성하는 것입니다. 페이지에 맞을 정도로 짧은 잎 기준이 생성 될 때까지 호출이 반복됩니다. 보다섹션 60.4.1자세한 내용은
Inner_consistent
트리 검색 중에 따라야 할 노드 세트 (브랜치) 세트를 반환합니다.
theSQL함수 선언은 다음과 같아야합니다 :
함수 생성 my_inner_consistent (내부, 내부) 반환 void ...
첫 번째 인수는 A에 대한 포인터입니다.SpginnerConsistentinC struct, 함수에 대한 입력 데이터를 포함합니다. 두 번째 인수는 A에 대한 포인터입니다.SpginnerConsistentOutC 구조물, 함수가 결과 데이터로 채워야합니다.
typedef struct spginnerconsistentin 스캔 키 스캔 키; / * 운영자 배열 및 비교 값 */ int nkeys; / * 배열 길이 */ Datum ReconstructedValue; / * 부모에게 재구성 된 값 */ int 레벨; / * 현재 레벨 (0에서 계산) */ bool returndata; /* 원본 데이터를 반환해야합니까? */ / * 현재 내부 튜플의 데이터 */ BOOL ALLTHESAME; /* 튜플은 모든 것이 표시되어 있습니까? */ BOOL HASPREFIX; /* 튜플에는 접두사가 있습니까? */ Datum Prefixdatum; / * 그렇다면 접두사 값 */ int nnodes; / * 내부 튜플의 노드 수 */ Datum *Nodelabels; / * 노드 레이블 값 (null이 없음) */ SpginnerConsistentin; typedef struct spginnerconsistentout int nnodes; / * 방문 할 어린이 노드 수 */ int *nodenumbers; / * 노드 어레이의 인덱스 */ int *levelAdds; / * 각 */에 대한 이거 화수율 Datum *재구성 Values; / * 관련 재구성 값 */ spginnerConsistEntOut;
배열Scankeys, 길이nkeys, 인덱스 검색 조건을 설명합니다. 이러한 조건은 결합되며 - 모든 것을 만족시키는 인덱스 항목 만 흥미 롭습니다. (nkeys= 0은 모든 인덱스 항목이 쿼리를 만족 시킨다는 것을 의미합니다.) 일반적으로 일관된 함수는에만 관심이 있습니다.sk_strategy및sk_argument각 배열 항목의 필드는 각각 색인 가능한 연산자와 비교 값을 제공합니다. 특히 확인할 필요가 없습니다sk_flagsSP-Gist 핵심 코드가 그러한 조건을 필터링하기 때문에 비교 값이 null인지 확인하려면재구성 value부모 튜플에 대해 재구성 된 값입니다. 그것은(Datum) 0루트 레벨에서 또는Inner_consistent
함수는 부모 수준에서 값을 제공하지 않았습니다.레벨는 루트 레벨의 경우 0에서 시작하는 현재 튜플 레벨입니다.returnDataistrue이 쿼리에 재구성 된 데이터가 필요한 경우; 이것은만큼 그렇게 될 것입니다config
기능 주장CanreturnData. Allthesame현재 내부 튜플이 표시되면 참입니다"All-the-Same"; 이 경우 모든 노드는 동일한 레이블 (있는 경우)을 가지므로 쿼리와 일치하거나 전혀 일치합니다 (참조섹션 60.4.3).hasprefix전류 내부 튜플에 접두사가 포함되어 있으면 참입니다. 그렇다면,prefixdatum그 가치입니다.nnodes내부 튜플에 포함 된 자식 노드의 수는Nodelabels노드에 레이블이없는 경우 레이블 값의 배열이거나 NULL입니다.
nnodes검색에서 방문 해야하는 자식 노드 수로 설정해야합니다.Nodenumbers인덱스 배열로 설정해야합니다. 운영자 클래스가 레벨을 추적하는 경우levelAdds방문 할 각 노드로 내려갈 때 필요한 레벨 증분 배열로. (종종 이러한 증분은 모든 노드에서 동일하지만 반드시 그렇지는 않기 때문에 배열이 사용됩니다.) 값 재구성이 필요한 경우재구성방문 할 각 어린이 노드에 대해 재구성 된 값의 배열; 그렇지 않으면 떠나재구성null로.Inner_consistent
함수는 palloc'ing the에 책임이 있습니다.Nodenumbers, levelAdds및재구성배열.
Leaf_consistent
리프 튜플이 쿼리를 만족시키는 경우 true를 반환합니다.
theSQL함수 선언은 다음과 같아야합니다 :
함수 만들기 my_leaf_consistent (내부, 내부) 반환 bool ...
첫 번째 인수는 a에 대한 포인터입니다.SPLEAMCONSISTENTINc 함수에 대한 입력 데이터를 포함하는 구조. 두 번째 인수는 A에 대한 포인터입니다.spleafconsistentoutC 구조물, 결과 데이터가 결과 데이터로 채워야합니다.
typedef struct spleafconsistentin 스캔 키 스캔 키; / * 운영자 배열 및 비교 값 */ int nkeys; / * 배열 길이 */ Datum ReconstructedValue; / * 부모에게 재구성 된 값 */ int 레벨; / * 현재 레벨 (0에서 계산) */ bool returndata; /* 원본 데이터를 반환해야합니까? */ 데이텀 리프 듀다; / * 잎 튜플의 데이텀 */ spgleafconsistentin; typedef struct spgleafconsistentout 데이텀 리프 값; / * 재구성 된 원본 데이터 */ 부울 재건; / * 운영자를 다시 확인 해야하는 경우 true 설정 */ spleafconsistentout;
배열Scankeys, 길이nkeys, 인덱스 검색 조건을 설명합니다. 이러한 조건은 결합되며 - 모두를 만족시키는 인덱스 항목 만 쿼리를 만족시킵니다. (nkeys= 0은 모든 인덱스 항목이 쿼리를 만족 시킨다는 것을 의미합니다.) 일반적으로 일관된 함수는에만 관심이 있습니다.sk_strategyandsk_argument각 배열 항목의 필드는 각각 색인 가능한 연산자와 비교 값을 제공합니다. 특히 확인할 필요가 없습니다sk_flagsSP-Gist 핵심 코드가 그러한 조건을 필터링하기 때문에 비교 값이 null인지 확인하려면재구성 value부모 튜플에 대해 재구성 된 값입니다. 그것은(Datum) 0루트 레벨에서 또는Inner_consistent
함수는 부모 수준에서 값을 제공하지 않았습니다.레벨는 루트 레벨에서 0에서 시작하는 현재 잎 튜플 레벨입니다.returnDataistrue이 쿼리에 재구성 된 데이터가 필요한 경우; 이것은만큼 그렇게 될 것입니다config
기능 주장CanreturnData. Leafdatum현재 잎 튜플에 저장된 키 값입니다.
함수가 반환해야합니다true리프 와이즈 토토이 쿼리와 일치하는 경우거짓그렇지 않은 경우. 에서truecase, ifreturnDataistruetheLeafValue이 잎 와이즈 토토에 대해 인덱싱 된 원래 값으로 설정해야합니다. 또한,다시 확인로 설정 될 수 있습니다true일치가 불확실하고 연산자가 실제 힙 와이즈 토토에 다시 적용되어 일치를 확인해야합니다..
모든 SP-Gist 지원 방법은 일반적으로 단기간 메모리 컨텍스트에서 호출됩니다. 즉,CurrentMemoryContext각 와이즈 토토을 처리 한 후 재설정됩니다. 그러므로 당신이 palloc의 모든 것을 pfree에 대해 걱정하는 것은 그리 중요하지 않습니다. (그만큼config
메소드는 예외입니다. 메모리 누출을 피해야합니다. 그러나 보통config
메소드는 전달 된 매개 변수 구조에 상수를 할당하는 것 외에는 아무것도 할 필요가 없습니다.)
인덱스 된 열이 Collatable 데이터 유형 인 경우 표준을 사용하여 모든 지원 메소드로 인덱스 콜레이션이 전달됩니다.pg_get_collation ()
메커니즘.