Postgresql - একটি ভারচার কলামের আকারকে কম দৈর্ঘ্যে পরিবর্তন করুন


153

ALTER TABLEসত্যই বড় টেবিলের (প্রায় 30 মিলিয়ন সারি) কমান্ড সম্পর্কে আমার একটি প্রশ্ন আছে । এর কলামগুলির একটি হ'ল varchar(255)আমি এটির আকার পরিবর্তন করতে চাই varchar(40)। মূলত, আমি নিম্নলিখিত কমান্ডটি চালিয়ে আমার কলামটি পরিবর্তন করতে চাই:

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

প্রক্রিয়াটি খুব দীর্ঘ হলে আমার কোনও সমস্যা নেই তবে মনে হয় ALTER TABLE কমান্ড চলাকালীন আমার টেবিলটি আর পঠনযোগ্য নয়। একটি স্মার্ট উপায় আছে? হতে পারে একটি নতুন কলাম যুক্ত করুন, পুরানো কলাম থেকে মানগুলি অনুলিপি করুন, পুরাতন কলামটি ফেলে দিন এবং নতুনটির নতুন নামকরণ করুন?

যে কোনও ক্লু প্রশংসিত হবে! আগাম ধন্যবাদ,

দ্রষ্টব্য: আমি PostgreSQL 9.0 ব্যবহার করি।


11
কেবল পরিষ্কার করে বলতে: আপনি কি জানেন যে resizingএতে টেবিলটি কম জায়গা দখল করবে না?
এএইচ

এমনকি আমার ক্ষেত্রেও? আমি বোঝাতে চাইছি কলামটিতে 255 এর পরিবর্তে 40 মাপের আকার হবে (তাই অক্টেটস)?
Labynocle

16
আপনি যদি varchar(255)PostgreSQL কে বলেন তবে এটি এমন মানের জন্য 255 বাইট বরাদ্দ করবে না যা আসল দৈর্ঘ্য 40 বাইট। এটি 40 বাইট বরাদ্দ করবে (কিছু অভ্যন্তরীণ ওভারহেড)। be changed by the টেবিলে পরিবর্তিত হওয়ার একমাত্র জিনিসটি হ'ল পিজি থেকে ত্রুটি না পেয়ে আপনি এই কলামে সর্বাধিক সংখ্যক বাইট সংরক্ষণ করতে পারবেন।
এএইচ

ওভারহেড এএইচ সম্পর্কে উল্লিখিত: ভারচর (এন) এর ওভারহেড কী?
এরউইন ব্র্যান্ডসেটেটার

একটি আপডেটের জন্য এখানে উত্তরটি দেখুন dba.stackexchange.com/questions/189890/…
ইভান ক্যারল

উত্তর:


73

ডেটা পরিবর্তন না করে পোস্টগ্রিএসকিউএল টেবিলের কলামের আকার পরিবর্তন করে কীভাবে এটি করবেন তার একটি বর্ণনা রয়েছে । আপনাকে ডাটাবেস ক্যাটালগ ডেটা হ্যাক করতে হবে। আনুষ্ঠানিকভাবে এটি করার একমাত্র উপায় হ'ল অল্টার টেবিল, এবং আপনি উল্লেখ করেছেন যে পরিবর্তনটি চলার সময় পুরো টেবিলটিকে লক করে আবার লিখতে হবে।

এটি পরিবর্তন করার আগে আপনি ডক্সের চরিত্রের ধরণগুলি পড়েছেন তা নিশ্চিত করুন । সব ধরণের অদ্ভুত কেস এখানে সচেতন হতে হবে। সারিগুলিতে মান সংরক্ষণ করা হলে দৈর্ঘ্য পরীক্ষা করা হয়। আপনি যদি সেখানে কোনও নিম্ন সীমা হ্যাক করেন তবে তা বিদ্যমান মানগুলির আকারকে হ্রাস করবে না। পরিবর্তনটি করার পরে ক্ষেত্রের দৈর্ঘ্য> 40 টি অক্ষর সারি সন্ধান করার জন্য পুরো টেবিলটি স্ক্যান করে নেওয়া বুদ্ধিমানের কাজ। আপনাকে কীভাবে সেগুলি ম্যানুয়ালি কাটতে হবে তা নির্ধারণ করতে হবে - সুতরাং আপনি কিছুটা লককে কেবল বড় আকারের লোকের উপরে ফিরে এসেছেন - কারণ যদি কেউ সেই সারিটিতে কিছু আপডেট করার চেষ্টা করে তবে এটি এখন এটিকে অনেক বড় হিসাবে প্রত্যাখ্যান করবে going এটি সারিটির নতুন সংস্করণ সঞ্চয় করে। হিলারিটি ব্যবহারকারীর পক্ষে।

ভর্চার একটি ভয়াবহ প্রকার যা কেবলমাত্র এসকিউএল স্ট্যান্ডার্ডের সাথে সম্পর্কিত ভয়ঙ্কর অংশের সাথে সম্মতি জানাতে পোস্টগ্র্রেএসকিউএল-তে বিদ্যমান। যদি আপনি মাল্টি-ডাটাবেস সামঞ্জস্যের বিষয়ে চিন্তা করেন না, তবে আপনার ডেটাটিকে টেক্সট হিসাবে সংরক্ষণের কথা বিবেচনা করুন এবং এর দৈর্ঘ্য সীমাবদ্ধ করতে একটি সীমাবদ্ধতা যুক্ত করুন। এই টেবিল লক / পুনর্লিখন সমস্যা ছাড়াই আপনি চারপাশে পরিবর্তন করতে পারেন এবং তারা কেবল দুর্বল দৈর্ঘ্যের চেকের চেয়ে আরও সততা পরীক্ষা করতে পারে।


উত্তরের জন্য ধন্যবাদ. আমি আপনার লিঙ্ক চেক করব। আমি ম্যানুয়াল আকারের চেক সম্পর্কে উদ্বিগ্ন নই কারণ আমার সমস্ত সামগ্রীতে সর্বোচ্চ আকার 40 টি রয়েছে rs আমাকে পাঠ্যবন্ধে বাধা সম্পর্কে আরও পড়তে হবে কারণ আমি বিশ্বাস করি যে ল্যাঞ্চ পরীক্ষা করা ভ্রচারটি আরও ভাল ছিল :)
ল্যাবিনোকল

6
পরিবর্তনের দৈর্ঘ্যের পরিবর্তনটি টেবিলটি পুনরায় লিখবে না। এটি কেবল পুরো টেবিলের বিপরীতে সীমাবদ্ধতার দৈর্ঘ্যটি চেক কনট্রন্ট হিসাবে ঠিক পরীক্ষা করে। যদি আপনি দৈর্ঘ্য বৃদ্ধি করেন তবে কিছু করার নেই, কেবলমাত্র পরবর্তী সন্নিবেশ বা আপডেটগুলি বড় দৈর্ঘ্য গ্রহণ করবে। যদি আপনি দৈর্ঘ্য হ্রাস করেন এবং সমস্ত সারিগুলি নতুন ছোট সীমাবদ্ধতা অতিক্রম করে, পরবর্তী serোকানো বা আপডেটগুলি কেবলমাত্র নতুন দৈর্ঘ্যে লেখার অনুমতি দেওয়ার জন্য Pg কোনও আরও পদক্ষেপ নেয় না।
মনিয়েরো

3
@ বিগাউন, কেবল পরিষ্কার করার জন্য, আপনার বক্তব্যটি পোস্টগ্র্রেএসকিউএল 9.2+ এর জন্যই সত্য , পুরানোগুলি নয়।
ম্যাথিউস ওল

12
লিঙ্কটি এখন মারা গেছে।
বিরল

এটি কীভাবে কাজ করে তা সম্পর্কে আরও তথ্যের জন্য dba.stackexchange.com/questions/189890/…
ইভান ক্যারল

100

PostgreSQL 9.1 এ আরও সহজ উপায় রয়েছে

http://www.postgresql.org/message-id/162867790801110710g3c686010qcdd852e721e7a559@mail.gmail.com

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) |

6
মনে রাখবেন এটি কেবলমাত্র কাজ করে কারণ আপনি বড় আকার (30> 10) নির্দিষ্ট করছেন । যদি আকারটি ছোট হয় তবে আপনি আমার চেয়ে একই ত্রুটি পাবেন ।
ম্যাথিউ

2
যদি আপনি একটি ALTER TABLE ক্যোয়ারির মাধ্যমে ভার্চারের আকারটি কম করেন তবে পোস্টগ্রাসে কোনও ত্রুটি ছুঁড়ে ফেলা উচিত নয় যতক্ষণ না আরও একটি সারিতে একটি নতুন মানের চেয়ে বেশি থাকে।
বলুন

@ বলুন, আকর্ষণীয়। তার মানে কি পোস্টগ্রিস টেবিলের পুরো স্ক্যান করে, বা কোনওভাবে তার পরিসংখ্যানগুলিতে সর্বোচ্চ আকার রাখে?
ম্যাথিউইউ

47

ঠিক আছে, আমি সম্ভবত পার্টিতে দেরি করেছি, তবে ...

আপনার মামলায় কলম পুনরায় আকার দেওয়ার দরকার নেই!

কিছু অন্যান্য ডাটাবেসের বিপরীতে পোস্টগ্রাগেস কেবল স্ট্রিংয়ের জন্য উপযুক্ত পর্যাপ্ত স্থান ব্যবহার করতে যথেষ্ট স্মার্ট (এমনকি দীর্ঘতর স্ট্রিংয়ের জন্য সংক্ষেপণ ব্যবহার করে), এমনকি যদি আপনার কলামটি VARCHAR (255) হিসাবে ঘোষিত হয় - আপনি যদি 40-অক্ষরের স্ট্রিংগুলিতে সঞ্চয় করেন তবে কলামে, স্পেসের ব্যবহার 40 বাইট ওভারহেডের +1 বাইট হবে।

একটি সংক্ষিপ্ত স্ট্রিংয়ের জন্য স্টোরের প্রয়োজনীয়তা (126 বাইট পর্যন্ত) 1 বাইট প্লাস প্রকৃত স্ট্রিং, যা চরিত্রের ক্ষেত্রে স্পেস প্যাডিং অন্তর্ভুক্ত করে। দীর্ঘতর স্ট্রিংগুলিতে ১ টির পরিবর্তে ওভারহেডের 4 বাইট থাকে Long খুব দীর্ঘ মানগুলি ব্যাকগ্রাউন্ড সারণিতেও সংরক্ষণ করা হয় যাতে তারা সংক্ষিপ্ত কলাম মানগুলিতে দ্রুত অ্যাক্সেসে হস্তক্ষেপ না করে।

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

ভ্রচারে আকারের স্পেসিফিকেশন কেবল ationোকানো মানগুলির আকার পরীক্ষা করতে ব্যবহৃত হয়, এটি ডিস্কের বিন্যাসকে প্রভাবিত করে না। প্রকৃতপক্ষে, ভ্রচার ও পাঠ্য ক্ষেত্রগুলি পোস্টগ্রিসে একইভাবে সংরক্ষণ করা হয়


8
"কেন" সম্পর্কে আরও তথ্য যুক্ত করতে খুব বেশি দেরি করবেন না! এই সমস্ত তথ্যের জন্য আপনাকে ধন্যবাদ
Labynocle

আপনার ডাটাবেসের কাঠামোর সাথে সামঞ্জস্য থাকা দরকার। এমনকি যদি 2 কলামের একটি সম্পর্ক না থাকে তবে ধারণার দৃষ্টিতে তাদের একটি সম্পর্ক থাকতে পারে, উদাহরণস্বরূপ EAV মডেলটি চেকআউট করুন।
আলেকজান্দ্রে

36

আমি 32 থেকে 8 অবধি একটি VARCHAR ছাঁটাই করার চেষ্টা করার সাথে সাথে একই সমস্যার মুখোমুখি হয়েছি ERROR: value too long for type character varying(8)। আমি যথাসম্ভব এসকিউএল এর কাছাকাছি থাকতে চাই কারণ আমি একটি স্ব-তৈরি জেপিএ-জাতীয় কাঠামো ব্যবহার করছি যা আমাদের গ্রাহকের পছন্দ অনুসারে বিভিন্ন ডিবিএমএসে যেতে হতে পারে (পোস্টগ্রিসএসকিউএলটি ডিফল্ট হিসাবে রয়েছে)। অতএব, আমি সিস্টেম সারণী পরিবর্তন করার কৌশল ব্যবহার করতে চাই না।

আমি এই USINGবিবৃতিটি ব্যবহার করে শেষ করেছি ALTER TABLE:

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

@ রেলু যেমন উল্লেখ করেছেন, ALTERটেবিলের উপর একটি একচেটিয়া লক অর্জন করেছে তাই এটি শেষ না হওয়া পর্যন্ত অন্যান্য সমস্ত ক্রিয়াকলাপ বিলম্বিত হবে।


2
ALTERটেবিল আটকায় এবং উপর একটি একচেটিয়া লক acquires সব অন্যান্য অপারেশন
raylu

8

নতুন কলাম যুক্ত করা এবং আমার জন্য পুরানো কাজের সাথে একটি নতুনকে প্রতিস্থাপন করা, রেডশিফ্ট পোস্টগ্রিসক্লিতে, আরও তথ্যের জন্য এই লিঙ্কটি দেখুন 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;

7

গ্রেগ স্মিথ বর্ণিত পৃষ্ঠার ক্যাশে এখানে Here সেই সাথে যদি মারা যায় তবে পরিবর্তিত বিবৃতিটি এরকম দেখাচ্ছে:

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

যেখানে আপনার টেবিলটি TABLE1, কলামটি COL1 এবং আপনি এটি 35 টি অক্ষরে সেট করতে চান (লিঙ্ক অনুযায়ী উত্তরাধিকারের উদ্দেশ্যে +4 প্রয়োজন, সম্ভবত মন্তব্যগুলিতে এইএইচ দ্বারা বর্ণিত ওভারহেড)।


7

যদি আপনি কোনও লেনদেনের ক্ষেত্রে পরিবর্তনটি রেখে দেন তবে টেবিলটি লক করা উচিত নয়:

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

এটি আমার পক্ষে দ্রুত জ্বলজ্বলে কাজ করেছে, ৪০০k এরও বেশি সারি সহ একটি টেবিলে কয়েক সেকেন্ড।


5
আপনি কেন স্পষ্ট লেনদেনের মোড়কটি ALTERবিবৃতিটির লকিংয়ের আচরণটি পরিবর্তন করবেন ? এটা হয় না।
এরউইন ব্র্যান্ডসটেটার

লেনদেনের মোড়কের সাথে এবং ছাড়া নিজেকে চেষ্টা করুন, আপনি একটি বিশাল পার্থক্য লক্ষ্য করবেন।
জ্যাকট্রেড

2
আপনার উত্তর অধ্যক্ষের উপর ভুল। সুস্পষ্ট লেনদেনের মোড়ক ছাড়াই যে কোনও ডিডিএল বিবৃতি সুস্পষ্টভাবে কোনও লেনদেনের অভ্যন্তরে চলে। সুস্পষ্ট লেনদেনের একমাত্র সম্ভাব্য প্রভাব হ'ল লকগুলি আরও দীর্ঘ রাখা হয় - যতক্ষণ না স্পষ্ট COMMIT। আপনি যদি একই লেনদেনে আরও কমান্ড স্থাপন করতে চান তবে মোড়কটি কেবল তখনই বোঝায়।
এরউইন ব্র্যান্ডসটেটার

আপনি সম্পূর্ণরূপে ঠিক বলেছেন, কিন্তু আমি জোর দিয়েছি: নিজেকে চেষ্টা করুন, এগিয়ে যান। এবং তারপরে জিজ্ঞাসা করুন কেন একইভাবে কাজ করছেন না।
জ্যাকট্রেড

Postgres 9.3 এ সাহায্য করেনি।
নুমেনন

1

আমি আকার পরিবর্তন করার খুব সহজ উপায়টি পেয়েছি যেমন টীকাটি @ সাইজ (মিনিট = 1, সর্বোচ্চ = 50) যা "আমদানি জাভ্যাক্স.এলডিয়েশন.কন্ট্রেন্টস" এর অর্থ যা "আমদানি জাভ্যাক্স.এলডিয়েশন.কন্ট্রেন্টস.সাইজ;"

@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),

.....

)

আপনার পোস্টের জন্য ধন্যবাদ! দয়া করে আপনার পোস্টগুলিতে স্বাক্ষর / ট্যাগলাইন ব্যবহার করবেন না। আপনার ব্যবহারকারীর বাক্সটি আপনার স্বাক্ষর হিসাবে গণ্য হয়েছে এবং আপনি নিজের প্রোফাইল সম্পর্কে নিজের পছন্দমতো কোনও তথ্য পোস্ট করতে ব্যবহার করতে পারেন। স্বাক্ষর / ট্যাগলাইন সম্পর্কিত FAQ
অ্যান্ড্রু বারবার

0

পরিবর্তিত টেবিলটি অনুসরণ করে চালানোর চেষ্টা করুন:

ALTER TABLE public.users 
ALTER COLUMN "password" TYPE varchar(300) 
USING "password"::varchar;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.