지금까지 설명한 절차를 통해 새로운 유형, 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 | 비용 함수 |
그래서 우리는 다음이 필요합니다젠 토토운영자의 방금 정의했습니다. 우리는 모든 운영자의 이름을 검색할 것입니다 두 개 가져가세요복잡한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';