이 문서는 지원되지 않는 PostgreSQL 버전에 대한 것입니다.
다음에 대한 동일한 페이지를 보고 싶을 수도 있습니다.PostgreSQL : 문서 : 17 : 36.16. 토토 핫에 대한 확장 인터페이스버전 또는 위에 나열된 다른 지원 버전 중 하나를 사용하세요.

37장. 인터페이스 확장 지수로

지금까지 설명한 절차를 통해 새로운 유형, new 함수와 새로운 연산자. 그러나 아직은 정의할 수 없습니다. 보조 인덱스(예:B-트리, R-트리또는 해시 액세스 방법)을 통해 새로운 유형 또는 해당 연산자.

뒤를 돌아보세요주요 Postgres 시스템 카탈로그. 오른쪽 절반에는 수정해야 하는 카탈로그가 표시됩니다. 말해주기 위해포스트그레스방법 사용자 정의 유형 및/또는 사용자 정의 연산자를 인덱스와 함께 사용 (즉,pg_am, pg_amop, pg_amproc, pg_operator그리고pg_opclass). 불행히도 이를 수행하는 간단한 명령은 없습니다. 우리는 실행 예제를 통해 이러한 카탈로그를 수정하는 방법을 보여줍니다. 에 대한 새로운 연산자 클래스B-트리복소수를 오름차순으로 저장하고 정렬하는 액세스 방법 절대값 순서입니다.

pg_am클래스에는 하나의 인스턴스가 포함되어 있습니다. 모든 사용자 정의 액세스 방법에 대해. 힙 액세스 지원 메소드가 내장되어 있습니다.포스트그레스하지만 다른 모든 액세스 방법은 여기에 설명되어 있습니다. 스키마는

표 37-1. 인덱스 스키마

속성 설명
amname 액세스 방법 이름
아소유자 소유자의 개체 ID pg_user의 인스턴스
암킨드 현재는 사용되지 않지만 다음으로 설정됨 자리 표시자로 'o'
좋은 전략 이를 위한 전략 수 액세스 방법(아래 참조)
암지원 에 대한 지원 루틴 수 이 액세스 방법(아래 참조)
amgettuple
아민서트
... 프로시저 식별자 액세스 방법에 대한 인터페이스 루틴입니다. 예를 들어, regproc 인스턴스를 열고 닫고 가져오기 위한 ID 액세스 방법이 여기에 표시됩니다.

객체 ID인스턴스의pg_am은 많은 경우 외래 키로 사용됩니다. 다른 수업. 이 클래스에 새 인스턴스를 추가할 필요는 없습니다. 당신이 관심을 갖고 있는 것은 바로 그 것입니다.객체 아이디확장하려는 액세스 방법 인스턴스의:

pg_am에서 젠 토토 선택 amname = 'btree';

         +----+
         |로이드 |
         +----+
         |403 |
         +----+
우리는 그것을 사용하겠습니다선택어디다음 절.

좋은 전략속성이 다음에 존재합니다. 데이터 유형 전반에 걸쳐 비교를 표준화합니다. 예를 들어,B-트리s는 엄격한 명령을 내립니다. 키가 작을수록 커집니다. 이후포스트그레스사용자가 연산자를 정의할 수 있습니다.포스트그레이름을 볼 수 없습니다 연산자(예: "" 또는 "<")를 선택하고 어떤 종류인지 알려주세요. 비교는 그렇죠. 실제로 일부 액세스 방법은 어떠한 요구사항도 부과하지 않습니다. 전혀 주문합니다. 예를 들어,R-트리s 직사각형-포함 관계를 표현하는 반면, 해시된 데이터는 구조는 a의 값을 기반으로 비트별 유사성만 표현합니다. 해시 함수.포스트그레일부 필요 귀하의 쿼리에서 자격을 취득하는 일관된 방법을 살펴보고 연산자를 사용하고 사용 가능한 인덱스가 있는지 결정합니다. 이 다음을 의미합니다.포스트그레필요 예를 들어, "<=" 및 "" 연산자가 분할된다는 것을 알고 있습니다. 에B-트리. 포스트그레전략을 사용하여 이를 표현합니다. 연산자 간의 관계와 연산자를 사용하는 방법 인덱스를 스캔합니다.

새로운 전략 세트를 정의하는 것은 이 범위를 벗어납니다. 논의하고 있지만 방법을 설명하겠습니다.B-트리전략은 효과가 있습니다. 왜냐하면 당신이 알아야 하기 때문입니다 새로운 연산자 클래스를 추가하는 것입니다. 에서pg_am클래스, amstrategies 속성은 이 액세스 방법에 대해 정의된 전략 수입니다. 에 대한B-트리s, 이 숫자는 5입니다. 전략은 다음과 같습니다

표 37-2. B-트리 전략

작동 색인
미만 1
작거나 같음 2
같음 3
크거나 같음 4
보다 큼 5

아이디어는 다음과 같은 절차를 추가해야 한다는 것입니다. 위의 비교는pg_amop관계(아래 참조). 액세스 방법 코드는 이러한 전략을 사용할 수 있습니다 데이터 유형에 관계없이 숫자를 사용하여 분할 방법을 알아보세요.B-트리, 선택성 계산 및 등등. 프로시저 추가에 대한 세부 사항은 아직 걱정하지 마세요. 그냥 다음과 같은 일련의 절차가 있어야 함을 이해합니다.int2, int4, 젠 토토,및 기타 모든 데이터 어떤 것을 입력하세요.B-트리할 수 있다 작동합니다.

때때로 전략은 시스템에 대한 정보가 충분하지 않습니다. 인덱스를 어떻게 사용하는지 알아보세요. 일부 액세스 방법에는 다음이 필요합니다. 작동하기 위한 다른 지원 루틴. 예를 들어,B-트리액세스 방법은 다음을 수행할 수 있어야 합니다. 두 개의 키를 비교하고 하나가 더 큰지, 같은지 확인합니다. 다른 것보다 적거나 적습니다. 마찬가지로,R-트리액세스 방법은 다음을 계산할 수 있어야 합니다. 교차점, 합집합 및 직사각형의 크기. 이러한 작업은 SQL 쿼리의 사용자 자격과 일치하지 않습니다. 그들은 내부적으로 액세스 방법에 사용되는 관리 루틴입니다.

다양한 지원 루틴을 일관되게 관리하기 위해 모두포스트그레액세스 방법,pg_am이라는 속성을 포함합니다암지원. 이 속성은 다음을 기록합니다. 액세스 방법에서 사용되는 지원 루틴의 수입니다. 에 대한B-트리s, 이 숫자는 1입니다. 두 개의 키를 가져와서 다음에 따라 -1, 0 또는 +1을 반환하는 루틴입니다. 첫 번째 키가 키보다 작거나 같거나 큰지 여부 두 번째.

참고:엄밀히 말하면 이 루틴은 다음을 반환할 수 있습니다. 음수(< 0), 0 또는 0이 아닌 양수( 0).

좋은 전략pg_am의 항목은 다음과 같습니다. 액세스 방법에 대해 정의된 전략의 수 질문. 작음, 덜 같음 등에 대한 절차는 그렇지 않습니다. 에 나타남pg_am. 마찬가지로,암지원은 단지 지원 루틴의 수입니다 액세스 방법에 따라 필요합니다. 실제 루틴이 나열됩니다. 다른 곳.

다음 관심 클래스는 pg_opclass입니다. 이 클래스만 존재합니다. 이름과 기본 유형을 젠 토토와 연결합니다. pg_amop에서는 매B-트리연산자 클래스에는 다음 세트가 있습니다. 위의 1번부터 5번까지의 절차를 참조하세요. 일부 기존 opclass는 다음과 같습니다.int2_ops, int4_ops 및 젠 토토_ops. 당신은 필요 opclass 이름으로 인스턴스를 추가하려면(예:complex_abs_ops) ~pg_opclass.젠 토토의 이 인스턴스는 다른 클래스의 외래 키입니다.

pg_opclass에 삽입(opcname, opcdeftype)
    SELECT 'complex_abs_ops', 젠 토토 FROM pg_type WHERE typname = 'complex_abs';

SELECT 젠 토토, opcname, opcdeftype
    pg_opclass에서
    opcname = 'complex_abs_ops';

         +------+------+------------+
         |로이드 | opc이름 | opcdef유형 |
         +------+------+------------+
         |17314 | complex_abs_ops |      29058 |
         +------+------+------------+
귀하의 젠 토토에 유의하십시오.pg_opclass인스턴스는 다를 것입니다! 걱정하지 마세요 그래도 이것에 대해서는. 나중에 시스템에서 이 번호를 받게 됩니다. 여기서 유형의 젠 토토를 얻은 것처럼요.

이제 접근 방법과 연산자 클래스가 생겼습니다. 우리는 아직도 일련의 연산자가 필요합니다. 연산자를 정의하는 절차는 다음과 같습니다. 이 설명서의 앞부분에서 논의했습니다. complex_abs_ops 연산자의 경우 Btrees의 클래스에서 필요한 연산자는 다음과 같습니다.

절대값보다 작음
        절대값이 작거나 같음
        절대값이 같음
        절대값 크거나 같음
        절대값보다 큼

정의된 함수를 구현하는 코드가 저장되어 있다고 가정합니다. 파일에서PGROOT/src/tutorial/complex.c

코드의 일부는 다음과 같습니다: (우리는 단지 나머지 예제에서는 항등 연산자입니다. 나머지 4개 연산자는 매우 유사합니다. 참조복잡한.c또는복합체.소스자세한 내용은.)

#define Mag(c) ((c)-x*(c)-x + (c)-y*(c)-y)

         부울
         complex_abs_eq(복소수 *a, 복소수 *b)

             이중 amag = Mag(a), bmag = Mag(b);
             return (amag==bmag);

몇 가지 중요한 일이 일어나고 있습니다. 아래.

먼저, 작음, 작거나 같음에 대한 연산자에 유의하세요. 같음, 크거나 같음 및 보다 큼int4정의 중입니다. 이들 연산자는 모두 이미 정의됨int4이름 아래 <, <=, =, = 및 . 새로운 운영자는 행동합니다 물론 다르게요. 이를 보장하기 위해포스트그레스이러한 새로운 연산자를 사용하는 대신 이전 것들은 이전 것과 다르게 이름을 지정해야 합니다. 이것이 핵심 사항입니다. 연산자를 오버로드할 수 있습니다.포스트그레, 그러나 연산자가 그렇지 않은 경우에만 해당 인수 유형에 대해 이미 정의되어 있습니다. 즉, < (int4, int4)에 대해 정의되었으므로 다시 정의할 수 없습니다.포스트그레정의할 때 이를 확인하지 않습니다. 교환원이니까 조심하세요. 이 문제를 피하기 위해 이상한 이름은 운영자에게 사용됩니다. 이것을 잘못 이해하면 액세스가 스캔을 시도할 때 메소드가 충돌할 가능성이 있습니다.

또 다른 중요한 점은 모든 연산자 기능이 부울 값을 반환합니다. 액세스 방법은 이 사실에 의존합니다. (켜짐 반면에 지원 함수는 무엇이든 반환합니다. 특정 액세스 방법이 필요합니다. 이 경우에는 서명된 정수.) 파일의 마지막 루틴은 "지원 루틴"입니다. 우리가 amsupport 속성을 논의할 때 언급한 바와 같습니다.pg_am클래스. 우리는 이것을 나중에 사용할 것입니다. 지금은 무시하세요.

함수 생성 complex_abs_eq(complex_abs, complex_abs)
              반환 부울
              AS 'PGROOT/tutorial/obj/complex.so'
              언어 'c';

이제 이를 사용하는 연산자를 정의하십시오. 언급한 바와 같이, 운영자는 이름은 두 개를 사용하는 모든 연산자 중에서 고유해야 합니다.int4피연산자. 운영자인지 확인하기 위해 아래에 나열된 이름이 사용되었으므로 쿼리를 수행할 수 있습니다.pg_operator:

/*
     * 이 쿼리는 정규식 연산자(~)를 사용합니다.
     *로 끝나는 세 문자 연산자 이름을 찾으려면
     * 캐릭터 &
     */
    선택 *
     pg_operator에서
     WHERE oprname ~ '^..&$'::text;

당신이 원하는 유형에 당신의 이름이 사용되는지 확인하세요. 는 여기서 중요한 것은 절차입니다(C위에 정의된 함수) 및 제한사항 선택성 함수에 참여하세요. 그냥 사용했던 것을 사용해야합니다 아래--각각의 기능이 있다는 점에 유의하십시오. 보다 작음, 같음, 보다 큼의 경우입니다. 이것들은 반드시 공급되어야 하며, 그렇지 않으면 연산자를 사용하려고 할 때 액세스 방법이 중단됩니다. 제한 및 가입 이름을 복사해야 하지만 마지막 단계에서 정의한 프로시저 이름입니다.

연산자 생성 = (
     leftarg = complex_abs, rightarg = complex_abs,
     절차 = complex_abs_eq,
     제한 = eqsel, 조인 = eqjoinsel
         )

5개의 연산자가 작음, 덜 같음, 같음, 더 크거나 더 큰 같음이 정의됩니다.

이제 막 끝났어요. 우리가 마지막으로 해야 할 일은 업데이트하세요pg_amop관계. 이렇게 하려면 다음 속성이 필요합니다.

표 37-3.pg_amproc스키마

속성 설명
아모피드 the젠 토토pg_amB-트리의 인스턴스(== 403, 위 참조)
amopclaid the젠 토토pg_opclass인스턴스 forcomplex_abs_ops(== 대신 무엇을 얻었든 의17314, 위 참조)
amopopr the젠 토토20566_20643
amopselect, amopnpages 비용 함수
비용 함수는 쿼리 최적화 프로그램에서 다음을 결정하는 데 사용됩니다. 스캔에서 특정 인덱스를 사용할지 여부. 다행히도 이러한 이미 존재합니다. 우리가 사용할 두 가지 함수는 다음과 같습니다.btreesel, 이는의 선택성을 추정합니다.B-트리브트리엔페이지, 페이지 수를 추정합니다. 검색은 트리에서 터치됩니다.

그래서 우리는 다음이 필요합니다젠 토토운영자의 방금 정의했습니다. 우리는 모든 운영자의 이름을 검색할 것입니다 두 개 가져가세요복잡한es, 그리고 우리 것을 선택하세요 밖으로:

o.젠 토토 AS op젠 토토 선택, o.oprname
     INTO 테이블 complex_ops_tmp
     pg_operator o, pg_type t에서
     여기서 o.oprleft = t.젠 토토 및 o.oprright = t.젠 토토
      t.typname = 'complex_abs';

         +------+---------+
         |로이드 | 이름 |
         +------+---------+
         |17321 | < |
         +------+---------+
         |17322 | <= |
         +------+---------+
         |17323 |  = |
         +------+---------+
         |17324 | = |
         +------+---------+
         |17325 |  |
         +------+---------+
(다시 말하지만, 당신 중 일부는젠 토토숫자 거의 확실히 다를 것입니다.) 우리가 운영하는 운영자는 관심 있는 사람은 다음과 같습니다.젠 토토s 17321 17325를 통해 얻을 수 있는 값은 아마도 다를 수 있으며, 아래 값으로 대체해야 합니다. 우리는 이것을 할 것이다 선택 문으로.

이제 업데이트할 준비가 되었습니다.pg_amop와 함께 우리의 새로운 오퍼레이터 클래스. 이 전체에서 가장 중요한 것은 토론은 연산자가 덜 평등한 것부터 순서가 지정된다는 것입니다. 더 큰 평등을 통해, inpg_amop. 우리는 추가한다 필요한 인스턴스:

pg_amop에 삽입(amopid, amopclaid, amopopr, amopstrategy,
                amopselect, amopnpages) 
        SELECT am.젠 토토, opcl.젠 토토, c.op젠 토토, 1,
                'btreesel'::regproc, 'btreenpage'::regproc
        pg_am am, pg_opclass opcl, complex_abs_ops_tmp c에서
        여기서 amname = 'btree' AND
            opcname = 'complex_abs_ops' AND
            c.oprname = '<';
이제 "1"을 대체하는 다른 연산자에 대해 이 작업을 수행하십시오. 위의 세 번째 줄에, 마지막 줄에 "<"가 있습니다. 참고하세요 순서: "보다 작음"은 1, "작거나 같음"은 2, "같음"은 3, "크거나 같음"은 4이고 "보다 큼"은 5입니다.

다음 단계는 "지원 루틴" 등록입니다 이전에 우리의 논의에서 설명한 바와 같습니다.pg_am.젠 토토이것의 지원 루틴은에 저장됩니다.pg_amproc액세스 방법으로 키가 지정된 클래스젠 토토그리고 연산자 클래스젠 토토. 먼저, 함수를 등록해야 합니다.포스트그레(우리가 넣은 것을 기억하세요C이 루틴을 구현하는 코드는 연산자를 구현한 파일의 맨 아래 루틴):

CREATE FUNCTION complex_abs_cmp(복합,복잡)
     반환 int4
     AS 'PGROOT/tutorial/obj/complex.so'
     언어 'ㄷ';

    SELECT 젠 토토, proname FROM pg_proc
     WHERE proname = 'complex_abs_cmp';

         +------+------+
         |로이드 | 성씨 |
         +------+------+
         |17328 | complex_abs_cmp |
         +------+------+
(다시 말하지만, 당신의젠 토토번호는 아마도 다를 수 있으며 표시되는 값을 대체해야 합니다. 아래 값에 대해 설명합니다.) 다음과 같이 새 인스턴스를 추가할 수 있습니다.
pg_amproc에 삽입(amid, amopclaid, amproc, amprocnum)
        a.젠 토토, b.젠 토토, c.젠 토토, 1 선택
            pg_am a, pg_opclass b, pg_proc c에서
            여기서 a.amname = 'btree' AND
                b.opcname = 'complex_abs_ops' AND
                c.proname = 'complex_abs_cmp';

이제 우리는 유형이 가능하도록 해싱 전략을 추가해야 합니다. 색인이 생성되었습니다. pg_am에서 다른 유형을 사용하여 이를 수행하지만 같은 작전입니다.

pg_amop에 삽입(amopid, amopclaid, amopopr, amopstrategy,
                amopselect, amopnpages)
        SELECT am.젠 토토, opcl.젠 토토, c.op젠 토토, 1,
                'hashsel'::regproc, 'hashnpage'::regproc
        pg_am am, pg_opclass opcl, complex_abs_ops_tmp c에서
        amname = '해시' AND
            opcname = 'complex_abs_ops' AND
            c.oprname = '=';

Where 절에서 이 색인을 사용하려면 다음을 수정해야 합니다.pg_operator클래스는 다음과 같습니다.

pg_operator 업데이트
        SET oprrest = 'eqsel'::regproc, oprjoin = 'eqjoinsel'
        oprname = '=' AND
            oprleft = oprright AND
            oprleft = (pg_type WHERE typname = 'complex_abs'에서 젠 토토 선택);

    업데이트 pg_operator
        SET oprrest = 'neqsel'::regproc, oprjoin = 'neqjoinsel'
        어디 oprname = '' 그리고
            oprleft = oprright AND
            oprleft = (pg_type WHERE typname = 'complex_abs'에서 젠 토토 선택);

    업데이트 pg_operator
        SET oprrest = 'neqsel'::regproc, oprjoin = 'neqjoinsel'
        어디 oprname = '' 그리고
            oprleft = oprright AND
            oprleft = (pg_type WHERE typname = 'complex_abs'에서 젠 토토 선택);

    업데이트 pg_operator
        SET oprrest = 'intltsel'::regproc, oprjoin = 'intltjoinsel'
        oprname = '<' AND 
            oprleft = oprright AND
            oprleft = (pg_type WHERE typname = 'complex_abs'에서 젠 토토 선택);

    업데이트 pg_operator
        SET oprrest = 'intltsel'::regproc, oprjoin = 'intltjoinsel'
        WHERE oprname = '<=' AND
            oprleft = oprright AND
            oprleft = (pg_type WHERE typname = 'complex_abs'에서 젠 토토 선택);

    업데이트 pg_operator
        SET oprrest = 'intgtsel'::regproc, oprjoin = 'intgtjoinsel'
        oprname = '' AND
            oprleft = oprright AND
            oprleft = (pg_type WHERE typname = 'complex_abs'에서 젠 토토 선택);

    업데이트 pg_operator
        SET oprrest = 'intgtsel'::regproc, oprjoin = 'intgtjoinsel'
        oprname = '=' AND
            oprleft = oprright AND
            oprleft = (pg_type WHERE typname = 'complex_abs'에서 젠 토토 선택);

그리고 마지막으로 (드디어!) 이 유형에 대한 설명을 등록합니다.

INSERT INTO pg_description(obj젠 토토, 설명) 
    SELECT 젠 토토, '두 부분으로 구성된 G/L 계정'
            pg_type WHERE typname = 'complex_abs';