SELECT (ctid::text::point)[0]::bigint AS page_number FROM t;
내 솔루션과 당신의 바이올린 .
@bma는 이미 주석에서 비슷한 것을 암시했습니다. 여기에 ...
유형에 대한 이론적 근거
ctid
C 코드에서 tid
호출 ItemPointer
되는 유형 (튜플 식별자) 입니다. 문서 당 :
이것은 시스템 열의 데이터 유형입니다 ctid
. 튜플 ID는 테이블 내 행의 물리적 위치를 식별 하는 쌍 ( 블록 번호 , 블록 내 튜플 색인 )입니다.
대담한 강조 광산. 과:
( ItemPointer
라고도 함 CTID
)
표준 설치에서 블록은 8KB 입니다. 최대 테이블 크기는 32TB 입니다. 이 블록 번호가 수용해야하는 것이 논리적 다음 적어도 최대 (계산 @Daniel하여 주석에 의한 고정) :
SELECT (2^45 / 2^13)::int -- = 2^32 = 4294967294
서명되지 않은 사람에게 적합합니다 integer
. 추가 조사 를 통해 소스 코드 에서 ...
블록은 0부터 0xFFFFFFFE 까지 순차적으로 번호가 매겨집니다 .
대담한 강조 광산. 첫 번째 계산을 확인합니다.
SELECT 'xFFFFFFFE'::bit(32)::int8 -- max page number: 4294967294
Postgres는 부호있는 정수를 사용하므로 1 비트가 짧습니다. 부호있는 정수를 수용하기 위해 텍스트 표현이 이동했는지 여부는 아직 알 수 없었습니다. 누군가가 이것을 정리할 때까지, 나는 bigint
어떤 경우에도 작동합니다.
캐스트
Postgres 9.3 에는 유형에 등록 된 캐스트 가 없습니다tid
.
SELECT *
FROM pg_cast
WHERE castsource = 'tid'::regtype
OR casttarget = 'tid'::regtype;
castsource | casttarget | castfunc | castcontext | castmethod
------------+------------+----------+-------------+------------
(0 rows)
여전히에 캐스팅 할 수 있습니다 text
. Postgres의 모든 것에 대한 텍스트 표현 이 있습니다 .
또 다른 중요한 예외는 텍스트 또는 다른 문자열 유형으로 변환하기 위해 데이터 유형의 자체 I / O 함수를 사용하여 수행 된 "자동 I / O 변환 캐스트"가 명시 적으로 표시되지 않는 것입니다
pg_cast
.
텍스트 표현은 두 개의 float8
숫자 로 구성된 점의 표현과 일치 하며 캐스트는 무손실입니다.
인덱스가 0 인 포인트의 첫 번째 번호에 액세스 할 수 있습니다 bigint
. 캐스트 . 보일라
공연
원본을 포함하여 몇 가지 대체 표현에 대해 30k 행 (최고 5)의 테이블에서 빠른 테스트를 실행했습니다.
SELECT (ctid::text::point)[0]::int -- 25 ms
,right(split_part(ctid::text, ',', 1), -1)::int -- 28 ms
,ltrim(split_part(ctid::text, ',', 1), '(')::int -- 29 ms
,(ctid::text::t_tid).page_number -- 31 ms
,(translate(ctid::text,'()', '{}')::int[])[1] -- 45 ms
,(replace(replace(ctid::text,'(','{'),')','}')::int[])[1] -- 51 ms
,substring(right(ctid::text, -1), '^\d+')::int -- 52 ms
,substring(ctid::text, '^\((\d+),')::int -- 143 ms
FROM tbl;
int
대신 bigint
시험의 목적을 위해 주로 관련이없는, 여기. 나는 반복하지 않았다 bigint
. @Jake와 같은 사용자 정의 복합 유형에 빌드
캐스트는 t_tid
주석 처리되었습니다.
요점 : 캐스팅은 문자열 조작보다 빠릅니다. 정규 표현식은 비싸다. 위의 솔루션은 가장 짧고 빠릅니다.