지금까지 설명한 절차를 통해 새로운 유형을 정의할 수 있습니다. 새로운 함수와 새로운 연산자. 그러나 아직은 정의할 수 없습니다. 보조 토토 베이(예:B-트리, R-트리또는 해시 액세스 방법)을 통해 새로운 유형 또는 해당 연산자.
뒤를 돌아보세요그림 12-1. 는 오른쪽 절반은 수정해야 하는 카탈로그를 보여줍니다. 말하다포스트그레스사용 방법 사용자 정의 유형 및/또는 토토 베이가 있는 사용자 정의 연산자 (즉,pg_am, pg_amop, pg_amproc, pg_operator그리고pg_opclass). 불행히도 이를 수행하는 간단한 명령은 없습니다. 우리는 실행을 통해 이러한 카탈로그를 수정하는 방법을 보여줍니다. 예:에 토토 베이 새로운 연산자 클래스B-트리저장하고 정렬하는 액세스 방법 절대값 오름차순의 복소수입니다.
그pg_am테이블에는 다음 행이 하나 포함되어 있습니다. 모든 사용자 정의 액세스 방법. 힙 액세스 지원 메소드가 내장되어 있습니다.포스트그레스, 하지만 다른 모든 액세스 방법은 여기에 설명되어 있습니다. 스키마 이다
표 18-1. 토토 베이 스키마
| 칼럼 | 설명 |
|---|---|
| amname | 액세스 이름 방법 |
| 아오너 | 소유자의 사용자 ID |
| 암전략 | 전략 수 이 액세스 방법(아래 참조) |
| 암지원 | 지원 루틴 수 이 액세스 방법에 대해서는(아래 참조) |
| amorderstrategy | 인덱스가 no를 제공하는 경우 0입니다. 정렬 순서, 그렇지 않으면 전략의 전략 번호 정렬 순서를 설명하는 연산자 |
| amgettuple | |
| 아민서트 | |
| ... | 프로시저 식별자 액세스 방법에 토토 베이 인터페이스 루틴입니다. 예를 들어, 행 열기, 닫기 및 가져오기를 위한 regproc ID 액세스 방법이 여기에 표시됩니다. |
그객체 ID행의pg_am외래키로 많이 사용됩니다 다른 테이블의. 이 테이블에 새 행을 추가할 필요는 없습니다. 당신이 관심을 갖고 있는 것은 바로 그 것입니다.객체 ID원하는 액세스 방법 행의 연장:
pg_am에서 oid 선택 amname = 'btree'; 이드 ----- 403 (1행)우리는 그것을 사용하겠습니다선택에어디다음 절.
그전략열이 다음에 존재합니다. 데이터 유형 전반에 걸쳐 비교를 표준화합니다. 예를 들어,B-트리s는 엄격한 명령을 내립니다. 키가 작을수록 커집니다. 이후포스트그레사용자가 정의할 수 있습니다. 연산자,포스트그레스볼 수 없음 연산자 이름(예: "" 또는 "<")에 무엇을 표시하는지 알려주세요. 일종의 비교죠. 실제로 일부 액세스 방법은 그렇지 않습니다. 전혀 명령을 내리지 마십시오. 예를 들어,R-트리s는 직사각형 포함을 표현합니다. 반면 해시된 데이터 구조는 관계만 표현합니다. 해시 함수의 값을 기반으로 한 비트 유사성.포스트그레스일관적인 작업이 필요합니다 귀하의 쿼리에서 자격을 취득하는 방법은 다음과 같습니다. 연산자를 사용하고 사용 가능한 인덱스가 있는지 결정합니다. 이는 다음을 의미합니다. 그포스트그레스알아야 할 사항이 있습니다. 예를 들어, "<=" 및 "" 연산자는 a를 분할합니다.B-트리. 포스트그레전략을 사용하여 이를 표현합니다. 연산자 간의 관계와 연산자를 사용하는 방법 인덱스를 스캔합니다.
새로운 전략 세트를 정의하는 것은 이 범위를 벗어납니다. 논의하고 있지만 방법을 설명하겠습니다.B-트리전략은 효과가 있습니다. 새로운 연산자 클래스를 추가하는 방법을 알아두세요. 에서pg_am테이블에서 amstrategies 열은 이 액세스 방법에 대해 정의된 전략 수입니다. 에 대한B-트리s, 이 숫자는 5입니다. 전략은 다음과 같습니다
아이디어는 해당하는 절차를 추가해야 한다는 것입니다. 위의 비교에 대해pg_amop관계(아래 참조). 액세스 방법 코드는 다음을 사용할 수 있습니다. 데이터 유형에 관계없이 전략 번호를 사용하여 방법을 파악합니다. 파티션을 나누다B-트리, 계산하다 선택성 등등. 추가 세부 사항에 대해 걱정하지 마십시오 아직 절차가; 단지 이러한 세트가 있어야 한다는 점을 이해하십시오. 절차int2, int4, oid,그리고 aB-트리작동할 수 있습니다.
때때로 전략은 시스템에 대한 정보가 충분하지 않습니다. 인덱스를 어떻게 사용하는지 알아보세요. 일부 액세스 방법에는 다음이 필요합니다. 작동하기 위한 다른 지원 루틴. 예를 들어,B-트리액세스 방법은 다음을 수행할 수 있어야 합니다. 두 개의 키를 비교하고 하나가 더 큰지, 같은지 확인합니다. 다른 것보다 적거나 적습니다. 마찬가지로,R-트리액세스 방법은 다음을 계산할 수 있어야 합니다. 교차점, 합집합 및 직사각형의 크기. 이러한 작업 SQL 쿼리의 사용자 자격과 일치하지 않습니다. 그들은 액세스 방법에 사용되는 관리 루틴, 내부적으로.
다양한 지원 루틴을 지속적으로 관리하기 위해 전체적으로포스트그레액세스 방법,pg_am'라는 열을 포함합니다.암지원. 이 열은 다음을 기록합니다. 액세스 방법에서 사용되는 지원 루틴의 수입니다. 에 대한B-트리s, 이 숫자는 1입니다. 두 개의 키를 가져와서 다음에 따라 -1, 0 또는 +1을 반환하는 루틴입니다. 첫 번째 키가 키보다 작거나 같거나 큰지 여부 두 번째.
참고:엄밀히 말하면 이 루틴은 다음을 반환할 수 있습니다. 음수(< 0), 0 또는 0이 아닌 양수 ( 0).
그전략입력pg_am은 정의된 전략의 수일 뿐입니다. 문제의 액세스 방법에 대해 미만에 대한 절차는, 덜 동일하며 등은 표시되지 않습니다.pg_am. 마찬가지로,암지원은 단지 지원 루틴의 수입니다 액세스 방법에 따라 필요합니다. 실제 루틴이 나열됩니다. 다른 곳.
그런데, 그amorderstrategy항목은 액세스 방법이 순서화된 스캔을 지원하는지 여부를 나타냅니다. 제로 그렇지 않다는 뜻입니다. 그렇다면,amorderstrategy은 전략의 수입니다 순서 연산자에 해당하는 루틴입니다. 예를 들어, btree는amorderstrategy= 1 즉, '미만' 전략 번호입니다.
다음 관심 테이블은pg_opclass. 이 테이블은 연결을 위해서만 존재합니다. 연산자 클래스 이름 및 아마도 연산자 클래스 oid. 일부 기존 opclass는 다음과 같습니다.int2_ops, int4_ops,그리고oid_ops. opclass를 사용하여 행을 추가해야 합니다. 이름(예:complex_abs_ops) ~pg_opclass.oid이 행의 다른 행의 외래 키가 됩니다 특히 테이블pg_amop.
pg_opclass에 삽입(opcname, opcdeftype)
SELECT 'complex_abs_ops', oid FROM pg_type WHERE typname = 'complex';
SELECT oid, opcname, opcdeftype
pg_opclass에서
opcname = 'complex_abs_ops';
이드 | opc이름 | opcdeftype
------+------+------------
277975 | complex_abs_ops | 277946
(1행)귀하의 oid에 주의하십시오.pg_opclass행이 달라집니다! 걱정하지 마세요
그래도 이건. 나중에 다음과 같이 시스템에서 이 번호를 가져옵니다.
여기서는 해당 유형의 oid를 얻었습니다.위의 예는 귀하가 이것을 새로 만들고 싶다고 가정합니다 opclass에 토토 베이 기본 인덱스 opclass입니다.복잡한데이터 유형. 그렇지 않은 경우에는 0을 삽입하세요. 안으로opcdeftype, 삽입하는 대신 데이터 유형의 oid:
pg_opclass에 삽입(opcname, opcdeftype) VALUES('complex_abs_ops', 0);
이제 접근 방법과 연산자 클래스가 생겼습니다. 우리 여전히 일련의 연산자가 필요합니다. 정의 절차 연산자는 이 설명서의 앞부분에서 논의되었습니다. 에 대한complex_abs_ops연산자 클래스 Btrees, 우리에게 필요한 연산자는 다음과 같습니다.
절대값보다 작음
절대값이 작거나 같음
절대값이 같음
절대값 크거나 같음
절대값보다 큼
정의된 함수를 구현하는 코드가 다음과 같다고 가정합니다. 파일에 저장됨PGROOT/src/tutorial/complex.c
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);
우리는 다음과 같이 Postgres에 함수를 알려줍니다:
CREATE FUNCTION complex_abs_eq(복잡함,복잡함)
반환 부울
AS 'PGROOT/tutorial/obj/complex.so'
언어 'c';
여기서 몇 가지 중요한 일이 일어나고 있습니다.
먼저, 작음, 작거나 같음, 같음, 크거나 같음 및 보다 큼복잡한정의 중입니다. 우리는 하나만 가질 수 있어요 연산자 이름은 =이고 유형을 취함복잡한두 피연산자 모두에 대해. 이 경우에는 그렇지 않습니다. 다른 연산자가 있음 = for복잡한, 하지만 실용적인 데이터 유형을 구축한다면 아마도 다음을 원할 것입니다. 복소수에 대한 일반적인 동등 연산이 됩니다. 에서 이 경우에는 다른 연산자 이름을 사용해야 합니다. complex_abs_eq.
둘째, Postgres는 다음과 같은 연산자를 사용할 수 있지만 입력 데이터 유형이 다르면 동일한 이름을 사용할 수 있습니다. 특정 이름, 마침표가 있는 하나의 전역 루틴에만 대처합니다. 그래서 C 함수 이름을 다음과 같이 간단하게 지정하면 안 됩니다.abs_eq. 일반적으로 다음을 포함하는 것이 좋습니다. 충돌하지 않도록 C 함수 이름의 데이터 유형 이름 다른 데이터 유형에 대한 함수를 사용합니다.
셋째, 함수의 Postgres 이름을 만들 수 있었습니다.abs_eq, Postgres를 사용하여 입력 데이터 유형으로 다른 Postgres와 구별 같은 이름의 함수. 예제를 단순하게 유지하기 위해 다음을 만듭니다. 함수는 C 레벨과 Postgres에서 동일한 이름을 갖습니다. 수준.
마지막으로, 이 연산자 함수는 부울값을 반환한다는 점에 유의하십시오. 가치. 액세스 방법은 이 사실에 의존합니다. (반면에, 지원 기능은 특정 액세스가 무엇이든 반환합니다. 메소드는 -- 이 경우 부호 있는 정수를 기대합니다.) 최종 파일의 루틴은 우리가 언급한 "지원 루틴"입니다. 의 amsupport 열에 대해 논의했습니다.pg_am테이블. 우리는 이것을 나중에 사용할 것입니다. 지금으로서는, 무시하세요.
이제 연산자를 정의할 준비가 되었습니다:
연산자 생성 = (
leftarg = 복잡함, rightarg = 복잡함,
절차 = complex_abs_eq,
제한 = eqsel, 조인 = eqjoinsel
)여기서 중요한 것은 절차 이름입니다(C위에 정의된 함수) 및
제한 및 조인 선택 기능. 당신은 단지
예제에 사용된 선택성 함수(참조복합체.소스). 이런 종류가 있으니 참고하세요
보다 작음, 같음, 보다 큼의 경우에 대한 함수입니다. 이것들
제공되어야 합니다. 그렇지 않으면 옵티마이저가 효과적인 작업을 수행할 수 없습니다.
인덱스를 사용합니다.다음 단계는 이 연산자에 대한 항목을 다음에 추가하는 것입니다.pg_amop관계. 이를 위해 우리는 필요하다oid연산자 중 우리는 방금 정의되었습니다. 우리는 모든 운영자의 이름을 검색할 것입니다 두복잡한es, 그리고 우리 것을 골라보세요:
o.oid AS opoid 선택, o.oprname
INTO 테이블 complex_ops_tmp
pg_operator o, pg_type t에서
여기서 o.oprleft = t.oid 및 o.oprright = t.oid
t.typname = '복잡함';
오피이드 | 이름
--------+---------
277963 | +
277970 | <
277971 | <=
277972 | =
277973 | =
277974 |
(6행)(다시 말하지만, 당신 중 일부는oid숫자
거의 확실히 다를 것입니다.) 우리가 운영하는 운영자는
관심 있는 사람은 다음과 같습니다.oids 277970
277974를 통해. 당신이 얻는 값은 아마도 다를 것입니다.
아래 값으로 대체해야 합니다. 우리는 이것을 할 것이다
선택 문으로.이제 업데이트할 준비가 되었습니다.pg_amop새로운 연산자 클래스를 사용합니다. 이 중 가장 중요한 것은 전체 논의는 연산자가 더 적은 것부터 순서를 정한다는 것입니다. 보다 큼, inpg_amop. 필요한 행을 추가합니다.
pg_amop에 삽입(amopid, amopclaid, amopopr, amopstrategy)
선택 am.oid, opcl.oid, c.opoid, 1
pg_am am, pg_opclass opcl, complex_ops_tmp c에서
여기서 amname = 'btree' AND
opcname = 'complex_abs_ops' AND
c.oprname = '<';이제 "1"을 대체하는 다른 연산자에 대해 이 작업을 수행하십시오.
위의 세 번째 줄에, 마지막 줄에 "<"가 있습니다. 참고하세요
순서: "보다 작음"은 1, "작거나 같음"은 2, "같음"은 3,
"크거나 같음"은 4이고 "보다 큼"은 5입니다.다음 단계는 "지원 루틴" 등록입니다 이전에 우리의 논의에서 설명한 바와 같습니다.pg_am.oid이것의 지원 루틴은에 저장됩니다.pg_amproc액세스 방법으로 키가 지정된 테이블oid그리고 연산자 클래스oid. 먼저, 함수를 등록해야 합니다.포스트그레스(우리가 넣은 것을 기억하세요C이 루틴을 구현하는 코드 연산자를 구현한 파일의 맨 아래에 루틴):
CREATE FUNCTION complex_abs_cmp(복합,복잡)
반환 int4
AS 'PGROOT/tutorial/obj/complex.so'
언어 'ㄷ';
SELECT oid, proname FROM pg_proc
WHERE proname = 'complex_abs_cmp';
이드 | 성씨
------+------
277997 | complex_abs_cmp
(1행)(다시 말하지만, 당신의oid번호는
아마도 다를 수 있습니다.) 다음과 같이 새 행을 추가할 수 있습니다.pg_amproc에 삽입(amid, amopclaid, amproc, amprocnum)
a.oid, b.oid, c.oid, 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';
그리고 우리는 끝났습니다! (휴.) 이제 생성이 가능해졌을 겁니다. 그리고 btree 인덱스를 사용하세요.복잡한열.