मैं पृष्ठ और पंक्ति संख्याओं में ctid को कैसे हटाऊं?


16

तालिका की प्रत्येक पंक्ति में एक प्रकार का एक सिस्टम कॉलम ctid होता tidहै जो पंक्ति के भौतिक स्थान का प्रतिनिधित्व करता है:

create table t(id serial);
insert into t default values;
insert into t default values;
select ctid
     , id
from t;
ctid | आईडी
: ---- | -:
(0,1) | 1
(0,2) | 2

यहाँ dbfiddle

ctidसबसे उपयुक्त प्रकार (जैसे integer, bigintया numeric(1000,0)) से केवल पृष्ठ संख्या प्राप्त करने का सबसे अच्छा तरीका क्या है ?

एक ही रास्ता मैं के बारे में सोच सकते हैं बहुत बदसूरत है।


1
IIRC यह एक वेक्टर प्रकार है और हमारे पास इन पर एक्सेस करने के तरीके नहीं हैं। मुझे यकीन नहीं है कि आप इसे सी फंक्शन से कर सकते हैं। क्रेग सुनिश्चित करने के लिए बताएंगे :)
dezso

2
क्या आप POINT के रूप में कास्ट कर सकते हैं? उदाहरण के लिए। select ct[0], ct[1] from (select ctid::text::point as ct from pg_class where ...) y;
शाम

1
शीर्षक से पता चलता है कि आप पृष्ठ संख्या और टपल इंडेक्स दोनों के बाद हैं, बाद में आप पृष्ठ संख्या में कम हो जाते हैं। मैं शरीर में संस्करण के साथ गया था, टपल इंडेक्स एक तुच्छ विस्तार है।
इरविन ब्रान्डेसटेटर

जवाबों:


21
SELECT (ctid::text::point)[0]::bigint AS page_number FROM t;

मेरे समाधान के साथ आपकी बेला

@bma ने पहले ही एक टिप्पणी में कुछ इसी तरह का संकेत दिया। यहां है ...

प्रकार के लिए तर्क

ctidप्रकार tid(टुपल आइडेंटिफ़ायर) है, जिसे ItemPointerC कोड में कहा जाता है। प्रति प्रलेखन:

यह सिस्टम कॉलम का डेटा प्रकार है ctid। एक टपल आईडी एक जोड़ी ( ब्लॉक नंबर , ब्लॉक के भीतर टपल इंडेक्स ) है जो अपनी तालिका के भीतर पंक्ति के भौतिक स्थान की पहचान करती है।

बोल्ड जोर मेरा। तथा:

( ItemPointer, के रूप में भी जाना जाता है CTID)

मानक प्रतिष्ठानों में एक ब्लॉक 8 KB है। अधिकतम तालिका आकार 32 टीबी हैयह तार्किक रूप से इस प्रकार है कि ब्लॉक संख्या में कम से कम अधिकतम (@Daniel द्वारा टिप्पणी के अनुसार निर्धारित गणना) को समायोजित करना होगा :

SELECT (2^45 / 2^13)::int      -- = 2^32 = 4294967294

जो एक अहस्ताक्षरित में फिट होगा integer। आगे की जांच में मैंने सोर्स कोड में पाया कि ...

ब्लॉक क्रमिक रूप से गिने जाते हैं, 0 से 0xFFFFFFFE

बोल्ड जोर मेरा। जो पहले गणना की पुष्टि करता है:

SELECT 'xFFFFFFFE'::bit(32)::int8 -- max page number: 4294967294

पोस्टग्रेटेड हस्ताक्षरित पूर्णांक का उपयोग करता है और इसलिए यह एक छोटा है। मैं हस्ताक्षरित पूर्णांक को समायोजित करने के लिए पाठ प्रतिनिधित्व को स्थानांतरित कर दिया गया है या नहीं, फिर भी, मैं नीचे पिन नहीं कर सकता। जब तक कोई इसे साफ नहीं कर सकता, तब तक मैं वापस गिर जाऊंगा bigint, जो किसी भी मामले में काम करता है।

कास्ट

नहीं है कोई पंजीकृत कलाकारों के लिए tidPostgres 9.3 में प्रकार:

SELECT *
FROM   pg_cast
WHERE  castsource = 'tid'::regtype
OR     casttarget = 'tid'::regtype;

 castsource | casttarget | castfunc | castcontext | castmethod
------------+------------+----------+-------------+------------
(0 rows)

आप अभी भी डाल सकते हैं textPostgres में सब कुछ के लिए एक पाठ प्रतिनिधित्व है :

एक अन्य महत्वपूर्ण अपवाद यह है कि "स्वचालित 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;

intbigintयहाँ के बजाय , परीक्षण के उद्देश्य के लिए ज्यादातर अप्रासंगिक है। मैंने दोहराया नहीं bigint। @ जेक टिप्पणी की तरह उपयोगकर्ता परिभाषित समग्र प्रकार पर निर्माण
करने के लिए कलाकारों t_tid
इसका सार: कास्टिंग स्ट्रिंग हेरफेर की तुलना में अधिक तेज़ हो जाती है। नियमित भाव महंगे हैं। उपरोक्त समाधान सबसे छोटा और सबसे तेज़ है।


1
धन्यवाद इरविन, उपयोगी सामान। से यहाँ ऐसा लगता है कि ctidऔर पंक्ति के लिए पेज के लिए 4 2 के साथ 6 बाइट है। मैं कास्टिंग के बारे में चिंतित था, floatलेकिन मुझे लगता है कि आपको यहां कहने की ज़रूरत नहीं है। ऐसा लगता है कि एक उपयोगकर्ता परिभाषित समग्र प्रकार बहुत धीमी है, फिर उपयोग pointकरते हुए , क्या आप इसे भी ढूंढते हैं?
जैक का कहना है कि topanswers.xyz

@JackDouglas: आगे की जांच के बाद मैं वापस गिर गया bigint। अद्यतन पर विचार करें।
एरविन ब्रैंडस्टैटर

1
@JackDouglas: मुझे एक कास्ट के अपने विचार एक समग्र प्रकार के लिए पसंद है। यह साफ है और बहुत अच्छा प्रदर्शन करता है - भले ही कास्ट टू pointएंड बैक int8अभी भी तेज है)। पूर्वनिर्धारित प्रकारों को कास्ट करना हमेशा थोड़ा तेज होगा। मैंने इसे तुलना करने के लिए अपने परीक्षण में जोड़ा। मुझे (page_number bigint, row_number integer)यकीन है कि हो जाएगा।
एरविन ब्रैंडस्टैटर

1
2^40केवल 1TB है, 32TB नहीं है 2^45, जो कि विभाजित 2^13है 2^32, इसलिए पूर्ण 32 बिट्स पेज नंबर के लिए आवश्यक है।
डैनियल वेत्रे

1
शायद यह भी ध्यान देने योग्य है कि blgno केbigint लिए pg_freespacemap का उपयोग करता है
जैक कहते हैं
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.