2011-10-11 25 views
88

के आकार को बदलें मेरे पास वास्तव में बड़ी तालिका (लगभग 30 लाख पंक्तियों) पर ALTER TABLE कमांड के बारे में एक प्रश्न है। इसके कॉलम में से एक varchar(255) है और मैं इसे varchar(40) पर आकार बदलना चाहता हूं। असल में, मैं निम्न आदेश चलाकर मेरे कॉलम परिवर्तन करना चाहते हैं: यदि प्रक्रिया बहुत लंबी है लेकिन ऐसा लगता है मेरी मेज ALTER तालिका आदेश के दौरान कोई और अधिक पठनीय हैपोस्टग्रेस्क्ल - एक वर्कर कॉलम

ALTER TABLE mytable ALTER COLUMN mycolumn TYPE varchar(40); 

मुझे कोई समस्या नहीं है। क्या कोई शानदार तरीका है? शायद एक नया कॉलम जोड़ें, पुराने कॉलम से मूल्य कॉपी करें, पुराने कॉलम को छोड़ दें और आखिरकार नया नाम बदलें?

किसी भी सुराग की सराहना की जाएगी! अग्रिम धन्यवाद,

नोट: मैं PostgreSQL 9.0 का उपयोग करता हूं।

+8

बस स्पष्ट होने के लिए: आप जानते हैं कि 'आकार बदलने' तालिका को कम जगह पर कब्जा नहीं करेगा? –

+0

मेरे मामले में भी? मेरा मतलब है कि 255 के बजाय कॉलम का अधिकतम आकार 40 char (so octets) होगा? – Labynocle

+10

यदि आप पोस्टग्रेएसक्यूएल में 'वर्चर (255)' कहते हैं तो यह एक मान के लिए 255 बाइट आवंटित करेगा जो वास्तविक लंबाई 40 बाइट्स है। यह 40 बाइट आवंटित करेगा (साथ ही कुछ आंतरिक ओवरहेड)। एकमात्र चीज जिसे 'वैकल्पिक तालिका' द्वारा बदला जाएगा, वह अधिकतम बाइट्स है जिसे आप पीजी से त्रुटि प्राप्त किए बिना उस कॉलम में स्टोर कर सकते हैं। –

उत्तर

58

Resize a column in a PostgreSQL table without changing data पर यह कैसे करें इसका विवरण है। आपको डेटाबेस कैटलॉग डेटा हैक करना होगा। आधिकारिक रूप से ऐसा करने का एकमात्र तरीका वैकल्पिक तालिका के साथ है, और जैसा कि आपने ध्यान दिया है कि परिवर्तन लॉक हो जाएगा और पूरे टेबल को फिर से लिखने के दौरान फिर से लिख देगा।

सुनिश्चित करें कि आप इसे बदलने से पहले दस्तावेज़ों के Character Types अनुभाग को पढ़ लें। अजीब मामलों के सभी प्रकार यहां से अवगत होंगे। जब पंक्तियों में मान संग्रहीत होते हैं तो लम्बाई जांच की जाती है। यदि आप वहां कम सीमा हैक करते हैं, तो मौजूदा मानों के आकार को कम नहीं करेगा। आप पंक्तियों की तलाश में पूरी तालिका पर एक स्कैन करना बुद्धिमान होगा जहां परिवर्तन की अवधि के बाद फ़ील्ड की लंबाई> 40 वर्ण हैं। आपको यह समझने की आवश्यकता होगी कि मैन्युअल रूप से उनको कैसे मिटाया जाए - ताकि आप केवल कुछ लोगों को ओवरसीज पर वापस कर सकें - क्योंकि अगर कोई उस पंक्ति पर कुछ भी अपडेट करने का प्रयास करता है तो यह अब इसे बहुत बड़ा अस्वीकार कर देगा, बिंदु पर यह पंक्ति के नए संस्करण को स्टोर करने के लिए चला जाता है। उपयोगकर्ता के लिए Hilarity ensues।

वाराचर एक भयानक प्रकार है जो केवल पोस्टग्रेएसक्यूएल में मौजूद है जो SQL मानक के अपने संबंधित भयानक हिस्से का अनुपालन करता है। यदि आपको बहु-डेटाबेस संगतता की परवाह नहीं है, तो अपने डेटा को टेक्स्ट के रूप में संग्रहीत करने पर विचार करें और इसकी लंबाई को सीमित करने के लिए बाधा जोड़ें। इस तालिका के बिना आप बाधाओं को पुनर्स्थापित कर सकते हैं/समस्या को फिर से लिख सकते हैं, और वे कमजोर लंबाई की जांच से अधिक अखंडता जांच कर सकते हैं।

+0

उत्तर के लिए धन्यवाद। मैं आपका लिंक देखूंगा। मैं मैन्युअल आकार की जांच के बारे में चिंता नहीं करता क्योंकि मेरी सभी सामग्री का अधिकतम आकार 40 वर्ण है।मुझे टेक्स्ट पर बाधा के बारे में और अधिक पढ़ने की जरूरत है क्योंकि मुझे विश्वास था कि वेंचर लेंटघ की जांच करने के लिए बेहतर था :) – Labynocle

+0

खतरनाक सलाह जो ओपी की समस्या को ठीक नहीं कर रही है ... – Sergey

+3

वर्चर लंबाई बदलें तालिका को फिर से लिखना नहीं है। यह पूरी तरह से जांच के रूप में पूरी तालिका के खिलाफ बाधा लंबाई की जांच करें। यदि आप लंबाई बढ़ाते हैं तो ऐसा करने के लिए कुछ भी नहीं है, बस अगले डालने या अपडेट बड़ी लंबाई स्वीकार करेंगे। यदि आप लंबाई कम करते हैं और सभी पंक्तियां नई छोटी बाधा को पार करती हैं, तो पीजी अगली आवेषण या अपडेट को नई लंबाई लिखने की अनुमति देने के अलावा आगे कोई कार्रवाई नहीं करता है। – Maniero

7

ग्रेग स्मिथ द्वारा वर्णित पृष्ठ के the cache यहां है।

UPDATE pg_attribute SET atttypmod = 35+4 
WHERE attrelid = 'TABLE1'::regclass 
AND attname = 'COL1'; 

कहाँ अपनी मेज Table1 है, स्तंभ Col1 है और आप अधिकतम 35 वर्ण (4 अनुसार विरासत प्रयोजनों के लिए आवश्यक है करने के लिए यह निर्धारित करना चाहते हैं: ऐसा होता है कि रूप में अच्छी तरह मर जाता है में, बदलने बयान इस तरह दिखता है लिंक में, संभावित रूप से ओवरहेड टिप्पणियों में एएच द्वारा संदर्भित)।

19

मुझे 32 से 8 तक VARCHAR को छीनने और ERROR: value too long for type character varying(8) प्राप्त करने की कोशिश करने में एक ही समस्या का सामना करना पड़ रहा था। मैं जितना संभव हो सके एसक्यूएल के करीब रहना चाहता हूं क्योंकि मैं एक स्व-निर्मित जेपीए जैसी संरचना का उपयोग कर रहा हूं जिसे हमें ग्राहक के विकल्पों के अनुसार अलग-अलग डीबीएमएस पर स्विच करना पड़ सकता है (PostgreSQL डिफ़ॉल्ट है)। इसलिए, मैं सिस्टम टेबल को बदलने की चाल का उपयोग नहीं करना चाहता हूं।

ALTER TABLE "MY_TABLE" ALTER COLUMN "MyColumn" TYPE varchar(8) 
USING substr("MyColumn", 1, 8) 

मैं अगर तालिका किसी अन्य प्रोग्राम द्वारा पहुँचा जा रहा है या यदि तालिका अनुक्रमणित है नहीं वास्तव में प्रभाव पर विचार किया है:

मैं ALTER TABLE में USING कथन का उपयोग समाप्त हो गया। मुझे लगता है कि पोस्टग्रेस स्वचालित रूप से उस तरह का करता है?

1

मुझे आकार बदलने के लिए एक बहुत ही आसान तरीका है अर्थात् एनोटेशन @ आकार (न्यूनतम = 1, अधिकतम = 50) जो "आयात javax.validation.constraints" यानी "आयात javax.validation.constraints का हिस्सा है .Size, "

@Size(min = 1, max = 50) 
private String country; 


when executing this is hibernate you get in pgAdmin III 


CREATE TABLE address 
(
..... 
    country character varying(50), 

..... 

) 
+0

आपकी पोस्ट के लिए धन्यवाद! कृपया अपनी पोस्ट में हस्ताक्षर/टैगलाइन का उपयोग न करें। आपका उपयोगकर्ता बॉक्स आपके हस्ताक्षर के रूप में गिना जाता है, और आप अपनी प्रोफ़ाइल का उपयोग अपने पसंदीदा बारे में किसी भी जानकारी को पोस्ट करने के लिए कर सकते हैं। [हस्ताक्षर/टैगलाइन पर अक्सर पूछे जाने वाले प्रश्न] (http://stackoverflow.com/faq#signatures) –

40

ठीक है, मैं शायद पार्टी के लिए देर से वहां आपकी मामले में स्तंभ का आकार बदलने सं नीड हूँ, लेकिन ...

!

पोस्टग्रेस, कुछ अन्य डेटाबेस के विपरीत, केवल स्ट्रिंग फिट करने के लिए पर्याप्त जगह का उपयोग करने के लिए पर्याप्त स्मार्ट है (यहां तक ​​कि लंबे तारों के लिए संपीड़न का उपयोग भी), भले ही आपका कॉलम VARCHAR (255) के रूप में घोषित किया गया हो - यदि आप 40 स्टोर करते हैं कॉलम में ट्रैक्टर स्ट्रिंग्स, स्पेस यूज ओवरहेड के 40 बाइट्स + 1 बाइट होंगे।

एक छोटी स्ट्रिंग (अप करने के लिए 126 बाइट्स) के लिए भंडारण की आवश्यकता 1 बाइट प्लस वास्तविक स्ट्रिंग, जिस स्थिति चरित्र की में अंतरिक्ष गद्दी शामिल है। लंबे तारों के बजाय 4 बाइट्स ओवरहेड होते हैं। लंबे स्ट्रिंग सिस्टम द्वारा स्वचालित रूप से संपीड़ित होते हैं, इसलिए डिस्क पर भौतिक आवश्यकता कम हो सकती है। बहुत लंबे मूल्य पृष्ठभूमि तालिकाओं में संग्रहीत हैं ताकि वे कम कॉलम मानों तक पहुंच तक हस्तक्षेप न करें।

(http://www.postgresql.org/docs/9.0/interactive/datatype-character.html)

VARCHAR में आकार विनिर्देश केवल मान जो डाला जाता है के आकार की जाँच करने के लिए किया जाता है, यह डिस्क लेआउट को प्रभावित नहीं करता। वास्तव में, VARCHAR and TEXT fields are stored in the same way in Postgres

+6

"क्यों" के बारे में अधिक जानकारी जोड़ने में कभी देर नहीं हुई! इस जानकारी के लिए धन्यवाद – Labynocle

+0

कभी-कभी आपको अपने डेटाबेस की संरचना में सुसंगत होने की आवश्यकता होती है। भले ही 2 कॉलम का संबंध न हो, फिर भी वे अवधारणा के दृष्टिकोण में एक रिश्ता हो सकते हैं, उदाहरण के लिए मॉडल ईएवी चेकआउट करें। – Alexandre

4

नया स्तंभ जोड़ना और साथ पुराने मेरे लिए काम किया नया एक की जगह, लाल विचलन PostgreSQL पर, अधिक जानकारी के https://gist.github.com/mmasashi/7107430

BEGIN; 
LOCK users; 
ALTER TABLE users ADD COLUMN name_new varchar(512) DEFAULT NULL; 
UPDATE users SET name_new = name; 
ALTER TABLE users DROP name; 
ALTER TABLE users RENAME name_new TO name; 
END; 
49

के लिए इस लिंक का उल्लेख PostgreSQL 9.1 में वहाँ एक आसान तरीका

http://www.postgresql.org/message-id/[email protected]

है
CREATE TABLE foog(a varchar(10)); 

ALTER TABLE foog ALTER COLUMN a TYPE varchar(30); 

postgres=# \d foog 

Table "public.foog" 
Column |   Type   | Modifiers 
--------+-----------------------+----------- 
a  | character varying(30) | 
+4

ध्यान दें कि यह केवल इसलिए काम करता है क्योंकि आप ** बड़ा ** आकार (30> 10) निर्दिष्ट कर रहे हैं। यदि आकार छोटा है, तो आपको [मेरी तुलना में वही त्रुटि मिल जाएगी] (http://stackoverflow.com/a/10991954/1098603)। – Matthieu

3

यदि आप लेनदेन में बदलाव डालते हैं तो तालिका को लॉक नहीं किया जाना चाहिए:

BEGIN; 
    ALTER TABLE "public"."mytable" ALTER COLUMN "mycolumn" TYPE varchar(40); 
COMMIT; 

यह मेरे लिए 400k पंक्तियों से अधिक तालिका के साथ तेज, कुछ सेकंड तेज करने के लिए काम करता है।

+0

आप स्पष्ट लेनदेन रैपर को 'ALTER' कथन के लॉकिंग व्यवहार को बदलने की अपेक्षा क्यों करेंगे? यह नहीं है –

+0

लेन-देन रैपर के साथ और उसके बिना स्वयं को आज़माएं, आपको एक बड़ा अंतर दिखाई देगा। – jipipayo

+0

आपका उत्तर प्रिंसिपल पर गलत है। स्पष्ट लेनदेन रैपर के बिना कोई भी डीडीएल स्टेटमेंट एक लेनदेन के अंदर निहित है। स्पष्ट लेनदेन का एकमात्र संभावित प्रभाव यह है कि ताले को * लंबा * रखा जाता है - स्पष्ट 'COMMIT' तक। रैपर केवल तभी समझ में आता है जब आप एक ही लेनदेन में अधिक आदेश देना चाहते हैं। –

संबंधित मुद्दे