PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

PostgreSQL में सिस्टम कॉलम को समझना

तो आप अपने हाथों से एक कीबोर्ड पर बैठते हैं और सोचते हैं कि "मुझे अपने जीवन को और भी उत्सुक बनाने में क्या मज़ा आ सकता है? ..." ठीक है - निश्चित रूप से एक टेबल बनाएं!

vao=# create table nocol();
CREATE TABLE
vao=# select * from nocol;
--
(0 rows)

बिना डेटा वाली तालिका में क्या मज़ा है?.. बिल्कुल नहीं! लेकिन मैं इसे आसानी से ठीक कर सकता हूं:

vao=# insert into nocol default values;
INSERT 0 1

बिना कॉलम और एक पंक्ति वाली टेबल रखना अजीब और काफी बेवकूफी भरा लगता है। उल्लेख नहीं है कि यह स्पष्ट नहीं है कि वहां कौन से "डिफ़ॉल्ट मान" डाले गए थे ... ठीक है - दस्तावेज़ों से कुछ पंक्तियों को पढ़ने से पता चलता है कि "सभी कॉलम उनके डिफ़ॉल्ट मानों से भरे जाएंगे ।" फिर भी मेरे पास कोई कॉलम नहीं है! खैर - मेरे पास निश्चित रूप से कुछ है:

vao=# select attname, attnum, atttypid::regtype, attisdropped::text from pg_attribute where attrelid = 'nocol'::regclass;
 attname  | attnum | atttypid | attisdropped 
----------+--------+----------+--------------
 tableoid |     -7 | oid      | false
 cmax     |     -6 | cid      | false
 xmax     |     -5 | xid      | false
 cmin     |     -4 | cid      | false
 xmin     |     -3 | xid      | false
 ctid     |     -1 | tid      | false
(6 rows)

तो ये छह निश्चित रूप से ALTER TABLE DROP COLUMN जॉम्बी नहीं हैं क्योंकि एटिसड्रॉप्ड झूठा है। साथ ही मैं देखता हूं कि उन कॉलम का प्रकार नाम "आईडी" के साथ समाप्त होता है। वस्तु पहचानकर्ता प्रकार के निचले भाग को पढ़ने से विचार मिलेगा। एक और मजेदार अवलोकन है - -2 गायब है! मुझे आश्चर्य है कि मैं इसे कहाँ खो सकता था - मैंने अभी एक टेबल बनाया है! एचएम, मेरी तालिका में कौन सी वस्तु पहचानकर्ता गुम है? परिभाषा से मेरा मतलब है। मेरे पास टपल, कमांड और xact आईडी हैं। ठीक है जब तक कि कुछ "वैश्विक संपूर्ण डीबी पहचानकर्ता", जैसे ओआईडी? .. जांचना आसान है - मैं ओआईडीएस के साथ तालिका बनाउंगा:

vao=# create table nocol_withoid() with oids;
CREATE TABLE
vao=# select attname, attnum, atttypid::regtype, attisdropped::text from pg_attribute where attrelid = 'nocol_withoid'::regclass;
 attname  | attnum | atttypid | attisdropped 
----------+--------+----------+--------------
 tableoid |     -7 | oid      | false
 cmax     |     -6 | cid      | false
 xmax     |     -5 | xid      | false
 cmin     |     -4 | cid      | false
 xmin     |     -3 | xid      | false
 oid      |     -2 | oid      | false
 ctid     |     -1 | tid      | false
(7 rows)

वोइला! तो लापता -2 वास्तव में गायब है और हमें यह पसंद है। उपयोग की गई डेटा पंक्तियों के लिए खर्च करना एक बुरा विचार होगा, इसलिए मैं OIDS के बिना तालिका के साथ खेलना जारी रखूंगा।

मैंरे पास क्या है? मेरे पास "नो कॉलम टेबल" बनाने के बाद 6 विशेषताएँ हैं (oids=false)। क्या मुझे सिस्टम कॉलम का उपयोग करना चाहिए? यदि हां, तो वे क्यों छिपे हुए हैं? खैर - मुझे लगता है कि वे इतने व्यापक रूप से विज्ञापित नहीं हैं, क्योंकि उपयोग सहज नहीं है और भविष्य में व्यवहार बदल सकता है। उदाहरण के लिए टपल आईडी (सीटीआईडी) देखने के बाद कुछ लोग सोच सकते हैं "आह - यह आंतरिक पीके की तरह है" (और यह इस तरह का है):

vao=# select ctid from nocol;
 ctid  
-------
 (0,1)
(1 row)

पहला अंक (शून्य) पृष्ठ संख्या के लिए है और दूसरा (एक) टपल संख्या के लिए है। वे अनुक्रमिक हैं:

vao=# insert into nocol default values;
INSERT 0 1
vao=# select ctid from nocol;
 ctid  
-------
 (0,1)
 (0,2)
(2 rows)

लेकिन यह क्रम आपको यह भी परिभाषित करने में मदद नहीं करेगा कि कौन सी पंक्ति उसके बाद आई:

vao=# alter table nocol add column i int;
ALTER TABLE
vao=# update nocol set i = substring(ctid::text from 4 for 1)::int;
UPDATE 2
vao=# select i, ctid from nocol;
 i | ctid  
---+-------
 1 | (0,3)
 2 | (0,4)
(2 rows)

यहां मैंने एक कॉलम जोड़ा (मेरी पंक्तियों की पहचान करने के लिए) और इसे प्रारंभिक टपल संख्या से भर दिया (दिमाग दोनों पंक्तियों को शारीरिक रूप से स्थानांतरित कर दिया गया था)

vao=# delete from nocol where ctid = '(0,3)';
DELETE 1
vao=# vacuum nocol;
VACUUM
vao=# insert into nocol default values;
INSERT 0 1
vao=# select i, ctid from nocol;
 i | ctid  
---+-------
   | (0,1)
 2 | (0,4)
(2 rows)

आह! (बढ़ते स्वर के साथ कहा) - यहाँ मैंने अपनी एक पंक्ति हटा दी, खराब टेबल पर वैक्यूम को बाहर निकाल दिया और एक नई पंक्ति डाली। परिणाम - बाद में जोड़ी गई पंक्ति पहले पृष्ठ के पहले टपल में है, क्योंकि पोस्टग्रेज़ ने बुद्धिमानी से अंतरिक्ष को बचाने और खाली स्थान का पुन:उपयोग करने का निर्णय लिया।

तो पेश की गई पंक्तियों के अनुक्रम को प्राप्त करने के लिए ctid का उपयोग करने का विचार बुरा लगता है। कुछ स्तर तक - यदि आप एक लेन-देन में काम करते हैं तो क्रम बना रहता है - एक ही टेबल पर नई प्रभावित पंक्तियों में "बड़ा" ctid होगा। बेशक वैक्यूम (ऑटोवैक्यूम) के बाद या यदि आप पहले से ही HOT अपडेट पाने के लिए पर्याप्त भाग्यशाली हैं या अभी जारी किए गए अंतराल का पुन:उपयोग किया जाएगा - अनुक्रमिक क्रम को तोड़ना। लेकिन डरो मत - छह छिपे हुए गुण थे, एक नहीं!

vao=# select i, ctid, xmin from nocol;
 i | ctid  | xmin  
---+-------+-------
   | (0,1) | 26211
 2 | (0,4) | 26209
(2 rows)

यदि मैं xmin की जांच करता हूं, तो मैं देखूंगा कि अंतिम सम्मिलित पंक्ति पेश करने वाली लेनदेन आईडी (+2) अधिक है (+1 हटाई गई पंक्ति थी)। तो अनुक्रमिक पंक्ति पहचानकर्ता के लिए मैं पूरी तरह से अलग विशेषता का उपयोग कर सकता हूं! बेशक यह इतना आसान नहीं है, अन्यथा इस तरह के उपयोग को प्रोत्साहित किया जाएगा। 9.4 से पहले xmin कॉलम वास्तव में xid रैपराउंड से बचाने के लिए ओवरराइट किया गया था। इतना जटिल क्यों? Postgres में MVCC बहुत स्मार्ट है और इसके आसपास के तरीके समय के साथ बेहतर होते जाते हैं। बेशक यह जटिलता लाता है। काश। कुछ लोग सिस्टम कॉलम से भी बचना चाहते हैं। दुगना अफसोस। क्योंकि सिस्टम कॉलम शांत और अच्छी तरह से प्रलेखित हैं। सबसे शीर्ष विशेषता (याद रखें कि मैं ओड्स छोड़ता हूं) टेबलॉयड है:

vao=# select i, tableoid from nocol;
 i | tableoid 
---+----------
   |   253952
 2 |   253952
(2 rows)
आज श्वेतपत्र डाउनलोड करें क्लस्टरकंट्रोल के साथ पोस्टग्रेएसक्यूएल प्रबंधन और स्वचालन इस बारे में जानें कि पोस्टग्रेएसक्यूएल को तैनात करने, मॉनिटर करने, प्रबंधित करने और स्केल करने के लिए आपको क्या जानना चाहिए। श्वेतपत्र डाउनलोड करें

हर पंक्ति में समान मूल्य होना बेकार लगता है - है ना? और फिर भी कुछ समय पहले यह बहुत लोकप्रिय विशेषता थी - जब हम सभी नियमों और विरासत में मिली तालिकाओं का उपयोग करके विभाजन का निर्माण कर रहे थे। टेबलॉयड के साथ नहीं होने पर आप किस तालिका से पंक्ति आ रहे हैं, आप कैसे डिबग करेंगे? इसलिए जब आप नियमों, विचारों (समान नियमों) या यूनियन का उपयोग करते हैं तो टेबलॉयड विशेषता आपको स्रोत की पहचान करने में मदद करती है:

vao=# insert into nocol_withoid default values;
INSERT 253967 1
vao=# select ctid, tableoid from nocol union select ctid, tableoid from nocol_withoid ;
 ctid  | tableoid 
-------+----------
 (0,1) |   253952
 (0,1) |   253961
 (0,4) |   253952
(3 rows)

वाह क्या था? मुझे INSERT 0 1 देखने की इतनी आदत हो गई है कि मेरा psql आउटपुट अजीब लग रहा था! आह - सच - मैंने ओड्स के साथ एक टेबल बनाया और बस बेहद बेकार ढंग से एक (253967) पहचानकर्ता का उपयोग किया! खैर - पूरी तरह से व्यर्थ नहीं (हालांकि सख्त) - चयन एक ही सीटीआईडी ​​(0,1) के साथ दो पंक्तियों को लौटाता है - आश्चर्य की बात नहीं है - मैं दो तालिकाओं से चयन कर रहा हूं और फिर परिणाम एक दूसरे में जोड़ रहा हूं, इसलिए एक ही सीटीआईडी ​​​​होने का मौका इतना कम नहीं है। उल्लेख करने वाली आखिरी बात यह है कि मैं इसे सुंदर दिखाने के लिए फिर से वस्तु पहचानकर्ता प्रकारों का उपयोग कर सकता हूं:

vao=# select ctid, tableoid::regclass from nocol union select ctid, tableoid from nocol_withoid ;
 ctid  |   tableoid    
-------+---------------
 (0,1) | nocol
 (0,1) | nocol_withoid
 (0,4) | nocol
(3 rows)

आह! (बढ़ते स्वर के साथ कहा) - तो यहां डेटा स्रोत को स्पष्ट रूप से पिन करने का यही तरीका है!

अंत में एक और बहुत लोकप्रिय और दिलचस्प उपयोग - यह परिभाषित करना कि कौन सी पंक्ति डाली गई थी और कौन सी अपर्टेड:

vao=# update nocol set i = 0 where i is null;
UPDATE 1
vao=# alter table nocol alter COLUMN i set not null;
ALTER TABLE
vao=# alter table nocol add constraint pk primary key (i);
ALTER TABLE

अब जब हमारे पास PK है, तो मैं ON CONFLICT निर्देश का उपयोग कर सकता हूं:

vao=# insert into nocol values(0),(-1) on conflict(i) do update set i = extract(epoch from now()) returning i, xmax;
     i      |   xmax    
------------+-----------
 1534433974 |     26281
         -1 |         0
(2 rows)
संबंधित संसाधन PostgreSQL के लिए ClusterControl PostgreSQL सिस्टम कैटलॉग को समझना और पढ़ना PostgreSQL में डेटाबेस इंडेक्सिंग का अवलोकन

इतना खुश क्यों हो? क्योंकि मैं (कुछ गोपनीयता के साथ) बता सकता हूं कि xmax वाली पंक्ति शून्य के बराबर नहीं है कि इसे अपडेट किया गया था। और यह मत सोचो कि यह स्पष्ट है - ऐसा इसलिए लगता है क्योंकि मैंने पीके के लिए यूनिक्सटाइम का उपयोग किया है, इसलिए यह वास्तव में एक अंक के मूल्यों से अलग दिखता है। कल्पना कीजिए कि आप बड़े सेट पर ऐसे ऑन कॉन्फ्लिक्ट ट्विस्ट करते हैं और यह पहचानने का कोई तार्किक तरीका नहीं है कि किस मूल्य में संघर्ष था और कौन सा नहीं। xmax ने कठिन समय में टन DBA की मदद की। और यह कैसे काम करता है इसका सबसे अच्छा विवरण मैं यहां सुझाऊंगा - जैसे मैं सभी तीन चर्चा प्रतिभागियों (एबेलिस्टो, इरविन और लॉरेन्ज़) को अन्य पोस्टग्रेज टैग प्रश्नों और उत्तरों को SO पर पढ़ने की सलाह दूंगा।

बस।

tableoid, xmax, xmin और ctid किसी भी DBA के अच्छे दोस्त हैं। cmax, cmin और oid का अपमान न करें - ये भी उतने ही अच्छे दोस्त हैं! लेकिन यह एक छोटी समीक्षा के लिए पर्याप्त है और मैं अब कीबोर्ड से अपना हाथ हटाना चाहता हूं।


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PostgreSQL में उपलब्ध कॉलेशन की सूची कैसे लौटाएं

  2. PostgreSQL के लिए जस्ट-इन-टाइम कंपाइलेशन (JIT) का अवलोकन

  3. आप सक्रिय उपयोगकर्ताओं को SQL के माध्यम से postgreSQL डेटाबेस से कैसे कनेक्ट कर सकते हैं?

  4. PostgreSQL विदेशी कुंजी शर्त के लिए बाधा की जाँच करें

  5. पोस्टग्रेज:यदि यह पहले से मौजूद नहीं है तो बाधा जोड़ें