이 문서는 지원되지 않는 버전의 PostgreSQL을위한 것입니다.
당신은에 대해 같은 페이지를 보려고 할 수 있습니다현재버전 또는 위에 나열된 다른 지원 버전 중 하나입니다.

제 37 장. 인터페이스 확장 지표

지금까지 설명한 절차로 새로운 유형을 정의 할 수 있습니다. 기능 및 신규 운영자. 그러나 우리는 아직 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 비용 함수
비용 함수는 쿼리 최적화에 의해 사용됩니다. 스캔에서 주어진 인덱스를 사용할지 여부. 다행히도, 이것들 이미 존재합니다. 우리가 사용할 두 가지 기능은입니다.btreesel,의 선택성을 추정합니다B-Treebtreenpage, 페이지 수를 추정합니다 검색은 나무에 닿을 것입니다.

그래서 우리는가 필요합니다.젠 토토우리는 방금 정의했습니다. 우리는 모든 운영자의 이름을 찾아 볼 것입니다. 두 번 가져 가라복잡한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';