지금까지 설명한 절차로 새로운 유형을 정의 할 수 있습니다. 기능 및 신규 운영자. 그러나 우리는 아직 a를 정의 할 수 없습니다 2 차 지수 (예 :B-Tree, R-Tree또는 해시 액세스 방법)를 통해 새로운 유형 또는 운영자.
되돌아 보면주요 Postgres 시스템 카탈로그. 오른쪽 절반은 우리가 수정 해야하는 카탈로그를 보여줍니다. 말하기 위해Postgres방법 인덱스와 함께 사용자 정의 유형 및/또는 사용자 정의 연산자를 사용하십시오. (즉.,PG_AM, PG_AMOP, PG_AMPROC, pg_operatorandpg_opclass). 불행히도,이를 수행하라는 간단한 명령은 없습니다. 우리는 할 것입니다 실행중인 예제를 통해 이러한 카탈로그를 수정하는 방법을 보여줍니다. 에 대한 새로운 운영자 클래스B-Tree오름차순에 복소수를 저장하고 정렬하는 액세스 방법 절대 가치 순서.
PG_AM클래스에는 하나의 인스턴스가 포함됩니다 모든 사용자 정의 액세스 방법에 대해. 힙 액세스 지원 메소드가 내장되어 있습니다Postgres그러나 다른 모든 액세스 방법은 여기에 설명되어 있습니다. 스키마는
표 37-1. 인덱스 스키마
속성 | 설명 |
---|---|
Amname | 액세스 방법의 이름 |
Amowner | 소유자의 객체 ID pg_user의 인스턴스 |
Amkind | 현재 사용되지 않지만 설정 'O'는 장소 보유자 |
AMSTROGRATIES | 이것에 대한 전략 수 액세스 방법 (아래 참조) |
amsupport | 지원 루틴 수 이 액세스 방법 (아래 참조) |
amgettuple | |
Aminsert | |
... | 절차 식별자 액세스 방법에 대한 인터페이스 루틴. 예를 들어, regproc 개방, 폐쇄 및 인스턴스를위한 ID 액세스 방법이 여기에 나타납니다. |
the객체 ID인스턴스의PG_AM는 많은 곳에서 외국 키로 사용됩니다 다른 수업. 이 클래스에 새 인스턴스를 추가 할 필요가 없습니다. 관심있는 것은입니다.개체 ID확장하려는 액세스 방법 인스턴스의 :
pg_am에서 젠 토토를 선택하여 Amname = 'btree'; +----+ | 젠 토토 | +----+ | 403 | +----+우리는 그것을 사용할 것입니다selectat여기서나중에 조항
theAMSTROGRAGES속성이 있습니다 데이터 유형에서 비교를 표준화하십시오. 예를 들어,B-Trees는 엄격한 순서를 부과합니다 키, 더 큰 키. 부터Postgres사용자가 연산자를 정의 할 수 있습니다.Postgres이름을 볼 수 없습니다 연산자 (예 : ""또는 "<")의 비교입니다. 실제로 일부 액세스 방법은 적을 수 없습니다 전혀 주문. 예를 들어,R-Trees 해시 데이터는 사각형 함유 관계를 표현합니다 구조는 해시 기능.Postgres일부가 필요합니다 쿼리에서 자격을 취하는 일관된 방법 연산자가 사용 가능한 색인이 있는지 결정합니다. 이것 암시한다Postgres필요합니다 예를 들어, "<="및 ""연산자 파티션이 있음을 알고 있습니다. 에이B-Tree. Postgres전략을 사용하여이를 표현합니다 연산자와 사용 할 수있는 방법 간의 관계 스캔 지수.
새로운 전략 세트 정의는 이것의 범위를 벗어납니다. 토론, 그러나 우리는 방법을 설명 할 것입니다b-tree전략은 알아야하기 때문에 작동합니다 새로운 운영자 클래스를 추가합니다. 에서PG_AM클래스, amstrategies 속성은입니다 이 액세스 방법에 정의 된 전략 수. 을 위한B-Trees,이 숫자는 5입니다 전략은에 해당합니다.
표 37-2. B- 트리 전략
작동 | index |
---|---|
보다 작음 | 1 |
작거나 평등 한 | 2 |
Equal | 3 |
더 크거나 평등 | 4 |
보다 큰 | 5 |
아이디어는 다음과 같은 절차를 추가해야한다는 것입니다. 위의 비교pg_amop관계 (아래 참조). 액세스 방법 코드는 이러한 전략을 사용할 수 있습니다 파티션 방법을 알아 내기 위해 데이터 유형에 관계없이 숫자 그만큼B-Tree, 컴퓨터 선택성 및 곧. 아직 절차 추가의 세부 사항에 대해 걱정하지 마십시오. 단지 에 대한 이러한 절차 세트가 있어야한다는 것을 이해하십시오.int2, int4, 젠 토토,및 다른 모든 데이터 a 유형B-Treecan 작동하다.
때로는 전략이 시스템에 대한 정보가 충분하지 않습니다 인덱스 사용 방법을 알아 내기 위해. 일부 액세스 방법에는 필요합니다 일하기위한 기타 지원 루틴. 예를 들어,B-Tree액세스 방법을 사용할 수 있어야합니다 두 개의 키를 비교하고 하나가 더 큰지를 결정하십시오. 다른 것보다 또는 그 이상. 마찬가지로R-Tree액세스 방법은 계산할 수 있어야합니다 교차로, 노조 및 사각형 크기. 이러한 작업은 그렇습니다 SQL 쿼리의 사용자 자격에 해당하지 않습니다. 그들은입니다 내부적으로 액세스 방법에 사용되는 관리 루틴.
다양한 지원 루틴을 지속적으로 관리하기 위해 모두Postgres액세스 방법,PG_AM라는 속성 포함amsupport. 이 속성은 액세스 방법에서 사용하는 지원 루틴 수. 을 위한B-Trees,이 숫자는 하나입니다 두 개의 키를 가져 와서 -1, 0 또는 +1을 반환하는 일상 첫 번째 키가 두번째.
참고 :엄격히 말하면,이 루틴은 a를 반환 할 수 있습니다 음수 (<0), 0 또는 0이 아닌 양수 ( 0).
theamstrategiesPG_AM의 입장 액세스 방법에 대해 정의 된 전략 수 질문. 적은 수준, 덜 평등 한 등의 절차는 에 나타납니다.PG_AM. 비슷하게,amsupport는 지원 루틴의 수입니다 액세스 방법에 필요합니다. 실제 루틴이 나열됩니다 다른 곳.
다음 관심 분야는 pg_opclass입니다. 이 수업은 만 존재합니다 이름과 기본 유형을 젠 토토와 연결합니다. pg_amop에서 모든B-Tree운영자 클래스에는 세트가 있습니다 위의 절차. 기존의 일부 OPClass는입니다.int2_ops, int4_ops 및 젠 토토_ops. 당신은 필요합니다 opclass 이름으로 인스턴스를 추가하려면 (예 :complex_abs_ops) topg_opclass. 그만큼젠 토토이 인스턴스는 다른 클래스의 외국 키입니다.
pg_opclass에 삽입 (opcname, opcdeftype) 'complex_abs_ops', pg_type에서 젠 토토를 선택하십시오. 여기서 typname = 'complex_abs'; 젠 토토, OpcName, OpcDeftype를 선택하십시오 pg_opclass에서 여기서 opcname = 'complex_abs_ops'; +-------+-----------------------------------+ | 젠 토토 | opcname | opcdeftype | +-------+-----------------------------------+ | 17314 | complex_abs_ops | 29058 | +------+-----------------+------------+당신의 젠 토토에 주목하십시오pg_opclass인스턴스가 다릅니다! 괜찮아요 그래도 이것에 대해. 우리는 나중에 시스템 에서이 번호를 얻을 것입니다 우리가 여기에 유형의 젠 토토를 얻은 것처럼.
이제 액세스 방법과 연산자 클래스가 있습니다. 우리는 여전히 운영자 세트가 필요합니다. 운영자를 정의하는 절차 이 매뉴얼의 앞부분에서 논의되었습니다. complex_abs_ops 연산자 용 Btrees에 대한 클래스, 우리가 필요로하는 운영자는 다음과 같습니다.
절대 값보다 낮습니다 절대 값은 적거나 평등하지 않습니다 절대 값은 동일합니다 절대 값은 평등 한 것보다 더 큰 값입니다 절대 가치보다 큰
정의 된 함수를 구현하는 코드가 저장되어 있다고 가정합니다. 파일에서pgroot/src/튜토리얼/complex.c
코드의 일부는 다음과 같습니다. 나머지 예제의 평등 연산자. 다른 4 명 연산자는 매우 유사합니다. 참조complex.c또는Complex.Source세부 사항은.)
#define mag (c) ((c)- x*(c)- x + (c)- y*(c)- y) 부 complex_abs_eq (complex *a, complex *b) Double Amag = mag (a), bmag = mag (b); return (amag == bmag);
일어나고있는 몇 가지 중요한 일이 있습니다. 아래에.
먼저, 작전은 적거나 덜 평등 한 운영자, 동등하고, 평등하거나, 평등하며,보다int4정의 중입니다. 이 모든 운영자가 있습니다 이미 정의int4이름 아래 <, <=, =, = 및. 새로운 운영자가 행동합니다 물론 다르게. 을 보장하기 위해Postgres이 새로운 연산자를 사용하지 않고 사용합니다 오래된 것들은 오래된 것과 다르게 지명되어야합니다. 이것은 핵심 요점입니다.Postgres그러나 연산자가 아닌 경우에만 인수 유형에 대해 이미 정의되었습니다. 즉, 당신이 <가 있다면 (int4, int4)에 대해 정의하면 다시 정의 할 수 없습니다.Postgres정의 할 때 이것을 확인하지 마십시오 운영자이므로 조심하십시오. 이 문제를 피하기 위해 이상한 이름이 있습니다 연산자에게 사용됩니다. 당신이 이것을 잘못 이해하면 액세스 스캔을 시도 할 때 방법이 충돌 할 가능성이 높습니다.
다른 중요한 점은 모든 운영자가 기능한다는 것입니다. 부울 값을 반환합니다. 액세스 방법은이 사실에 의존합니다. (에 다른 한편으로, 지원 함수는 무엇이든 반환합니다 특정 액세스 방법은 기대합니다 -이 경우 서명 된 정수.) 파일의 최종 루틴은 "지원 루틴"입니다. 우리가 amsupport 속성에 대해 논의했을 때 언급PG_AM클래스. 나중에 이것을 사용할 것입니다. 지금은 무시합니다.
함수 만들기 complex_abs_eq (complex_abs, complex_abs) Bool을 반환합니다 'pgroot/튜토리얼/obj/complex.so'로 언어 'C';
이제 사용하는 연산자를 정의하십시오. 언급 한 바와 같이, 운영자 이름은 2 번을 취하는 모든 연산자 중에서 독특해야합니다.int4오페라. 연산자가 있는지 확인하기 위해 아래에 나열된 이름은 찍히고 쿼리를 할 수 있습니다pg_operator:
/* *이 쿼리는 정규 표현 연산자 (~)를 사용합니다. * 끝나는 3 자 연산자 이름을 찾으려면 * 캐릭터 & */ 선택하다 * pg_operator에서 여기서 oprname ~ '^.. & $':: 텍스트;
원하는 유형에 대한 이름이 찍힌 지 확인하십시오. 그만큼 중요한 것은 절차입니다 (C위에서 정의 된 함수) 및 제한 및 선택성 함수에 가입하십시오. 사용 된 것만 사용해야합니다 아래-그러한 기능은 다른 기능이 있다는 점입니다 덜, 평등하고, 더 큰 경우. 이들은 공급해야합니다. 또는 작업자를 사용하려고 할 때 액세스 방법이 충돌합니다. 제한 및 가입을 위해 이름을 복사해야하지만 사용하십시오. 마지막 단계에서 정의한 절차 이름.
생성 연산자 = ( leftarg = complex_abs, rightarg = complex_abs, 절차 = complex_abs_eq, 제한 = eqsel, join = eqjoinsel )
5 명의 운영자가 적은, 덜 동일하며, 동일하고, 더 크고, 더 큰 평등이 정의됩니다.
우리는 거의 끝났습니다. 우리가해야 할 마지막 일은 업데이트pg_amop관계. 이를 위해 다음 속성이 필요합니다.
표 37-3.PG_AMPROC스키마
속성 | 설명 |
---|---|
amopid | the젠 토토의PG_AMb- 트리의 인스턴스 (== 403, 위 참조) |
AMOPCLAID | the젠 토토의pg_opclass인스턴스complex_abs_ops(== 대신 무엇이든지 의17314, 위 참조) |
amopop | the젠 토토opclass (who)의 연산자 우리는 단지 1 분 안에 갈거야) |
amopselect, amopnpages | 비용 함수 |
그래서 우리는가 필요합니다.젠 토토우리는 방금 정의했습니다. 우리는 모든 운영자의 이름을 찾아 볼 것입니다. 두 번 가져 가라복잡한es, 우리를 선택하십시오 밖으로:
O.Oid를 Opoid, O.Oprname으로 선택하십시오 테이블에 complex_ops_tmp pg_operator o, pg_type t에서 여기서 o.oprleft = t.oid 및 o.oprright = t.oid 및 t.typname = 'complex_abs'; +------+--------+ | 젠 토토 | oprname | +------+--------+ | 17321 | <| +------+--------+ | 17322 | <= | +------+--------+ | 17323 | = | +------+--------+ | 17324 | = | +------+--------+ | 17325 | | +------+--------+(다시, 일부젠 토토숫자 거의 확실하게 다를 것입니다.) 우리는 운영자입니다 관심이있는 사람은젠 토토S 17321 17325 년까지. 당신이 얻는 가치는 아마도 다를 것입니다. 아래 값으로 대체해야합니다. 우리는 이것을 할 것입니다 선정 된 진술과 함께.
이제 업데이트 할 준비가되었습니다pg_amop우리의 새로운 운영자 수업. 이 전체에서 가장 중요한 것 토론은 운영자가 덜 동일하게 주문된다는 것입니다. 더 큰 평등을 통해pg_amop. 우리는 추가합니다 필요한 인스턴스 :
pg_amop에 삽입 amopselect, amopnpages) am.oid, opcl.oid, c.opoid, 1, 1, 'btreesel':: regproc, 'btreenpage':: regproc PG_AM AM, PG_OPCLASS OPCL, COMPLED_ABS_OPS_TMP C. 여기서 Amname = 'btree'및 opcname = 'complex_abs_ops'및 c.oprname = '<';이제 "1"을 대체하는 다른 연산자를 위해이 작업을 수행합니다. 위의 세 번째 줄과 마지막 줄에서 "<"에서. 참고 주문 : "덜"Is 1, "jec or evel"은 2, "동일"은 3, "크거나 평등"은 4이고 "보다 큰"은 5입니다.
다음 단계는 "지원 루틴"등록입니다. 이전에 우리의 토론에서 묘사PG_AM. 그만큼젠 토토이것 지원 루틴은에 저장됩니다.PG_AMPROC클래스, 액세스 방법에 의해 키워젠 토토및 운영자 클래스젠 토토. 먼저, 우리는에 함수를 등록해야합니다.PostgresC이 루틴을 구현하는 코드 운영자를 구현 한 파일의 하단 루틴) :
함수 만들기 complex_abs_cmp (complex, complex) int4를 반환합니다 'pgroot/튜토리얼/obj/complex.so'로 언어 'c'; PG_PROC에서 젠 토토, Proname을 선택하십시오 여기서 proname = 'complex_abs_cmp'; +------+----------------+ | 젠 토토 | 프로 이름 | +------+----------------+ | 17328 | complex_abs_cmp | +------+---------------+(다시, 당신의젠 토토번호는 아마도 다르고 당신이 보는 가치를 대체해야합니다. 아래 값의 경우) 새 인스턴스를 다음과 같이 추가 할 수 있습니다.
PG_AMPROC에 삽입 A.Oid, B.Oid, C.Oid, 1을 선택하십시오 pg_am a, pg_opclass b, pg_proc c 여기서 a.amname = 'btree'및 b.opcname = 'complex_abs_ops'및 c.proname = 'complex_abs_cmp';
이제 유형이 될 수 있도록 해싱 전략을 추가해야합니다. 색인. PG_AM에서 다른 유형을 사용 하여이 작업을 수행하지만 재사용합니다. Sames Ops.
pg_amop에 삽입 amopselect, amopnpages) am.oid, opcl.oid, c.opoid, 1, 1, 'Hashsel':: regproc, 'hashnpage':: regproc PG_AM AM, PG_OPCLASS OPCL, COMPLED_ABS_OPS_TMP C. 여기서 Amname = 'Hash'및 opcname = 'complex_abs_ops'및 c.oprname = '=';
WHERE 절 에서이 색인을 사용하려면 수정해야합니다. 그만큼pg_operator다음과 같이 클래스.
PG_OPERATOR 업데이트 set oprrest = 'eqsel':: regproc, oprjoin = 'eqjoinsel' 여기서 oprname = '='및 oprleft = oprright 및 oprleft = (pg_type에서 Oid를 선택하여 typname = 'complex_abs'); pg_operator를 업데이트하십시오 set oprrest = 'neqsel':: regproc, oprjoin = 'neqjoinsel' 여기서 oprname = '' 그리고 oprleft = oprright 및 oprleft = (pg_type에서 Oid를 선택하여 typname = 'complex_abs'); pg_operator를 업데이트하십시오 set oprrest = 'neqsel':: regproc, oprjoin = 'neqjoinsel' 여기서 oprname = '' 그리고 oprleft = oprright 및 oprleft = (pg_type에서 Oid를 선택하여 typname = 'complex_abs'); pg_operator를 업데이트하십시오 set oprrest = 'intltsel':: regproc, oprjoin = 'intltjoinsel' 여기서 oprname = '<'및 oprleft = oprright 및 oprleft = (pg_type에서 Oid를 선택하여 typname = 'complex_abs'); pg_operator를 업데이트하십시오 set oprrest = 'intltsel':: regproc, oprjoin = 'intltjoinsel' 여기서 oprname = '<='및 oprleft = oprright 및 oprleft = (pg_type에서 Oid를 선택하여 typname = 'complex_abs'); pg_operator를 업데이트하십시오 set oprrest = 'intgtsel':: regproc, oprjoin = 'intgtjoinsel' 여기서 oprname = ''및 oprleft = oprright 및 oprleft = (pg_type에서 Oid를 선택하여 typname = 'complex_abs'); pg_operator를 업데이트하십시오 set oprrest = 'intgtsel':: regproc, oprjoin = 'intgtjoinsel' 여기서 oprname = ' ='및 oprleft = oprright 및 oprleft = (pg_type에서 Oid를 선택하여 typname = 'complex_abs';
그리고 마지막 (마지막으로!) 우리는이 유형에 대한 설명을 등록합니다.
pg_description에 삽입 (objoid, 설명) 젠 토토, 'Two Part G/L 계정'을 선택하십시오. pg_type에서 typname = 'complex_abs';