SELECT (ctid::text::point)[0]::bigint AS page_number FROM t;
ซอของคุณด้วยโซลูชันของฉัน
@bma พูดถึงสิ่งที่คล้ายกันในความคิดเห็นแล้ว นี่คือ ...
เหตุผลสำหรับประเภท
ctid
เป็นประเภทtid
(tuple identifier) เรียกว่าItemPointer
ในรหัส C ตามเอกสาร:
ctid
นี้เป็นชนิดข้อมูลของคอลัมน์ระบบ tuple ID คือคู่ ( หมายเลขบล็อก , ดัชนี tuple ภายในบล็อก ) ที่ระบุตำแหน่งทางกายภาพของแถวภายในตาราง
เหมืองเน้นหนัก และ:
( ItemPointer
หรือที่เรียกว่าCTID
)
บล็อกคือ8 KBในการติดตั้งมาตรฐาน ขนาดโต๊ะได้สูงสุด32 TB ตามด้วยเหตุผลว่าหมายเลขบล็อกต้องมีอย่างน้อยสูงสุด (การคำนวณแก้ไขตามความคิดเห็นโดย @Daniel):
SELECT (2^45 / 2^13)::int -- = 2^32 = 4294967294
integer
ซึ่งจะพอดีไม่ได้ลงนาม ในการตรวจสอบเพิ่มเติมฉันพบในซอร์สโค้ดที่ ...
บล็อกจะมีหมายเลขลำดับ0 ถึง 0xFFFFFFFE
เหมืองเน้นหนัก ซึ่งยืนยันการคำนวณครั้งแรก:
SELECT 'xFFFFFFFE'::bit(32)::int8 -- max page number: 4294967294
Postgres ใช้จำนวนเต็มที่ลงนามแล้วดังนั้นจึงสั้นหนึ่งบิต ฉันยังปักหมุดลงไม่ได้ว่าการแสดงข้อความถูกเลื่อนเพื่อรองรับจำนวนเต็มที่ลงนามหรือไม่ จนกว่าจะมีใครสามารถเคลียร์สิ่งนี้ได้ฉันก็จะถอยกลับไปbigint
ทำงานในทุกกรณี
โพลล์
มีการโยนไม่มีการลงทะเบียนสำหรับtid
การพิมพ์ใน Postgres 9.3:
SELECT *
FROM pg_cast
WHERE castsource = 'tid'::regtype
OR casttarget = 'tid'::regtype;
castsource | casttarget | castfunc | castcontext | castmethod
------------+------------+----------+-------------+------------
(0 rows)
text
คุณยังสามารถส่งข้อมูลไปยัง มีการแสดงข้อความสำหรับทุกสิ่งใน Postgres :
อีกข้อยกเว้นที่สำคัญก็คือว่า "บรรยากาศการแปลงฉันอัตโนมัติ / O" ผู้ดำเนินการโดยใช้ชนิดข้อมูลของตัวเองฟังก์ชั่น I / O แปลงไปยังหรือจากข้อความหรือประเภทสตริงอื่น ๆ
pg_cast
ที่ไม่ได้เป็นตัวแทนอย่างชัดเจนใน
การแทนข้อความตรงกับจุดซึ่งประกอบด้วยfloat8
ตัวเลขสองตัว
คุณสามารถเข้าถึงหมายเลขแรกของจุดที่มีค่าดัชนี 0. Cast bigint
มา voila
ประสิทธิภาพ
ฉันทำการทดสอบอย่างรวดเร็วบนโต๊ะที่มีแถว 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
ผมไม่ได้ทำซ้ำ คาสต์
เพื่อt_tid
สร้างบนคอมโพสิตประเภทที่ผู้ใช้กำหนดเช่น @Jake แสดงความคิดเห็น
ส่วนสำคัญของมัน: การคัดเลือกนักแสดงมีแนวโน้มที่จะเร็วกว่าการจัดการสตริง การแสดงออกปกติมีราคาแพง วิธีแก้ปัญหาข้างต้นนั้นสั้นที่สุดและเร็วที่สุด