ভার্চারের সর্বোচ্চ আকার (সর্বোচ্চ) পরিবর্তনশীল


90

অতীতে যে কোনও সময়ে, কেউ যদি আমাকে varchar(max)একটির জন্য সর্বোচ্চ আকার জিজ্ঞাসা করে থাকে , আমি 2 জিবি বলেছি বা আরও সঠিক চিত্রটি দেখেছি (2 ^ 31-1, বা 2147483647)।

তবে সাম্প্রতিক কিছু পরীক্ষায় আমি আবিষ্কার করেছি যে varchar(max)ভেরিয়েবলগুলি দৃশ্যত এই আকারটি ছাড়িয়ে যেতে পারে:

create table T (
    Val1 varchar(max) not null
)
go
declare @KMsg varchar(max) = REPLICATE('a',1024);
declare @MMsg varchar(max) = REPLICATE(@KMsg,1024);
declare @GMsg varchar(max) = REPLICATE(@MMsg,1024);
declare @GGMMsg varchar(max) = @GMsg + @GMsg + @MMsg;
select LEN(@GGMMsg)
insert into T(Val1) select @GGMMsg
select LEN(Val1) from T

ফলাফল:

(no column name)
2148532224
(1 row(s) affected)
Msg 7119, Level 16, State 1, Line 6
Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes.
The statement has been terminated.

(no column name)
(0 row(s) affected)

সুতরাং, প্রদত্ত যে আমি এখন জানি যে একটি ভেরিয়েবল 2 জিবি বাধা অতিক্রম করতে পারে - কেউ কি জানেন যে varchar(max)ভেরিয়েবলের আসল সীমাটি কী ?


(উপরের টেস্টটি এসকিউএল সার্ভার ২০০৮ এ সম্পন্ন হয়েছে (আর ২ নয়)


declare @x varchar(max) = 'XX'; SELECT LEN(REPLICATE(@x,2147483647))4294967294আমার জন্য দেয় তবে দৌড়াতে অনেক সময় লাগে - এমনকি SELECTফিরে আসার পরেও নিশ্চিত হন না যে অতিরিক্ত সময়টি কী ব্যয় করছে।
মার্টিন স্মিথ

উত্তর:


75

আমি যতদূর বলতে পারি ২০০৮ সালে কোনও উচ্চতর সীমা নেই।

এসকিউএল সার্ভার ২০০৫-এ আপনার প্রশ্নের কোডটি @GGMMsgভেরিয়েবলের সাথে অ্যাসাইনমেন্টে ব্যর্থ হয়

সর্বাধিক অনুমোদিত আকার 2,147,483,647 বাইটের বাইরে LOB বৃদ্ধির চেষ্টা করা হচ্ছে।

নীচের কোডটি ব্যর্থ হয়

প্রত্যাহার: ফলাফলের দৈর্ঘ্য লক্ষ্য বৃহত ধরণের দৈর্ঘ্যের সীমা (2 জিবি) অতিক্রম করে।

তবে দেখা যাচ্ছে যে এই সীমাবদ্ধতাগুলি নিঃশব্দে সরানো হয়েছে। ২০০৮-তে

DECLARE @y VARCHAR(MAX) = REPLICATE(CAST('X' AS VARCHAR(MAX)),92681); 

SET @y = REPLICATE(@y,92681);

SELECT LEN(@y) 

ফিরে আসে

8589767761

আমি এটি আমার 32 বিট ডেস্কটপ মেশিনে চালিয়েছি যাতে এই 8 জিবি স্ট্রিংটি ঠিকানাযোগ্য মেমরির চেয়ে বেশি

চলছে

select internal_objects_alloc_page_count
from sys.dm_db_task_space_usage
WHERE session_id = @@spid

ফিরে এসেছে

internal_objects_alloc_page_co 
------------------------------ 
2144456    

সুতরাং আমি অনুমান করি যে এটি কেবলমাত্র দৈর্ঘ্যে কোনও বৈধতা ছাড়াই LOBপৃষ্ঠাগুলিতে সঞ্চিত হবে tempdb। পৃষ্ঠা গণনা বৃদ্ধি সমস্ত SET @y = REPLICATE(@y,92681);বিবৃতিতে যুক্ত ছিল । প্রাথমিক পরিবর্তনশীল অ্যাসাইনমেন্ট @yএবং LENগণনা এটি বাড়েনি।

এটি উল্লেখ করার কারণ কারণ পৃষ্ঠার গণনা আমার প্রত্যাশার চেয়ে বিশাল বেশি huge একটি 8 কেবি পৃষ্ঠা অনুমান করে তারপরে এটি 16.36 গিগাবাইটে কার্যকর হবে যা সম্ভবত কম-বেশি দ্বিগুণ যা প্রয়োজনীয় বলে মনে হয়। আমি অনুমান করি যে এটি সম্ভবত স্ট্রিং কনটেনটেশন অপারেশনের অদক্ষতার কারণে পুরো বিশাল স্ট্রিংটি অনুলিপি করতে হবে এবং বিদ্যমান স্ট্রিংয়ের শেষের দিকে যোগ করতে সক্ষম হবার চেয়ে শেষ পর্যন্ত যোগ করতে হবে। দুর্ভাগ্যক্রমে এই মুহুর্তে .WRITEপদ্ধতিটি ভার্চার (সর্বোচ্চ) ভেরিয়েবলগুলির জন্য সমর্থিত নয়

যোগ

আমিও concatenating সঙ্গে আচরণ পরীক্ষিত থাকেন nvarchar(max) + nvarchar(max)এবং nvarchar(max) + varchar(max)। এই উভয়ই 2 জিবি সীমা অতিক্রম করতে দেয়। এর ফলাফলগুলি একটি টেবিলের মধ্যে সংরক্ষণের চেষ্টা করে Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes.আবার ত্রুটি বার্তাটি দিয়ে ব্যর্থ হয়। এর জন্য স্ক্রিপ্টটি নীচে রয়েছে (এটি চালাতে অনেক সময় নিতে পারে)।

DECLARE @y1 VARCHAR(MAX) = REPLICATE(CAST('X' AS VARCHAR(MAX)),2147483647); 
SET @y1 = @y1 + @y1;
SELECT LEN(@y1), DATALENGTH(@y1)  /*4294967294, 4294967292*/


DECLARE @y2 NVARCHAR(MAX) = REPLICATE(CAST('X' AS NVARCHAR(MAX)),1073741823); 
SET @y2 = @y2 + @y2;
SELECT LEN(@y2), DATALENGTH(@y2)  /*2147483646, 4294967292*/


DECLARE @y3 NVARCHAR(MAX) = @y2 + @y1
SELECT LEN(@y3), DATALENGTH(@y3)   /*6442450940, 12884901880*/

/*This attempt fails*/
SELECT @y1 y1, @y2 y2, @y3 y3
INTO Test

4
দুর্দান্ত - সুতরাং এটি প্রদর্শিত হবে যে ডকুমেন্টেশনটি বরং "অসম্পূর্ণ" - আমি মনে করি যে সাধারণ পৃষ্ঠাটি সর্বাধিক "স্টোরেজ আকার" বোঝায়, যা সম্ভবত কেবল কলামগুলিতে প্রয়োগ হয়, ভেরিয়েবল নয়।
দামিয়েন_এই_বিশ্বাসীরা

@ ড্যামিয়েন - অবশ্যই সেভাবে উপস্থিত হয়। নিশ্চিত না যে পৃষ্ঠাগুলির মোট সংখ্যার পরিপ্রেক্ষিতে আরও কিছু সীমা পৌঁছে যেতে পারে তবে আমি মনে করি এটি একটি বি গাছের কাঠামোতে সংরক্ষিত রয়েছে (এসকিউএল সার্ভার ২০০৮ এর ইন্টার্নিয়ালের পি .৩৮১ এর উপর ভিত্তি করে) যাতে নীতিগতভাবে অবশ্যই বাড়ানো যেতে পারে।
মার্টিন স্মিথ

@ ড্যামিয়েন_সে_ অবিশ্বাস্য - এখানে পরীক্ষাগুলির ভিত্তিতে ডকুমেন্টেশনগুলি ভুল বলে মনে হচ্ছে, মোটামুটি দ্ব্যর্থহীনভাবে বলে যে "বৃহত্তর অবজেক্ট (এলওবি) ডাটা টাইপের ভেরিয়েবল এবং প্যারামিটার ... ধরণের আকার 2 জিবি পর্যন্ত হতে পারে"
মার্টিন স্মিথ

কিন্ডা অকেজো কিন্তু আকর্ষণীয় যদিও। তত্ত্বের মধ্যে আপনি একটি পরিবর্তনশীল দিয়ে ডিস্কটি পূরণ করতে পারেন ... :-)
gbn

আমার এখানে কিছুটা দ্বিধা আছে কারণ একটি ভেরিয়েবেলে একটি মান সংরক্ষণ করা কলামে এটি সংরক্ষণ করার মতো নয়। পরিবর্তে কোনও কলাম দিয়ে এটি চেষ্টা করার মতো মনে হচ্ছে - বা আপনার কাছে কোনও আপডেট আছে? এমনকি এসকিউএল সার্ভার 2000 এর varcharকোডটিতে আক্ষরিক স্ট্রিংয়ের 8000 টিরও বেশি অক্ষরের মান থাকতে পারে , যতক্ষণ না আপনি এটিকে ভেরিয়েবল বা varcharকলামে রাখার চেষ্টা করেননি ।
এরিক

9

সম্পাদনা : আরও তদন্তের পরে, আমার মূল অনুমান যে এটি declare @var datatype = valueসিনট্যাক্সের একটি অসঙ্গতি (বাগ?) ছিল ভুল।

আমি আপনার স্ক্রিপ্টটি 2005 এর জন্য সংশোধন করেছি যেহেতু সিনট্যাক্সটি সমর্থিত নয়, তারপরে ২০০ on-তে পরিবর্তিত সংস্করণটি চেষ্টা করেছিলাম 2005 2005 সালে, আমি Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes.ত্রুটি বার্তাটি পাই । ২০০৮ সালে, পরিবর্তিত স্ক্রিপ্টটি এখনও সফল।

declare @KMsg varchar(max); set @KMsg = REPLICATE('a',1024);
declare @MMsg varchar(max); set @MMsg = REPLICATE(@KMsg,1024);
declare @GMsg varchar(max); set @GMsg = REPLICATE(@MMsg,1024);
declare @GGMMsg varchar(max); set @GGMMsg = @GMsg + @GMsg + @MMsg;
select LEN(@GGMMsg)

স্ক্রিপ্টটি সর্বদা একটি ত্রুটি তৈরি করে (টেবিল সন্নিবেশ করানোর চেষ্টা করে) তবে ২০০৮-এ আমি সর্বদা প্রথম ফলাফলের সেটে একটি ফলাফল পাই যা ভেরিয়েবলের উপস্থিতি নির্দেশ করে এবং দৈর্ঘ্যে 2 ^ 31-1 এর চেয়ে দীর্ঘ হয়।
দামিয়েন_তে_বিশ্বাসীরা

@ ডামিয়েন_সে_ অবিশ্বাসী: আমি স্ক্রিপ্টটি কেবলমাত্র পরিবর্তনশীল অংশে কেটেছি এবং এখন আপনার মতো ফলাফল পেয়েছি। 2005 সালে, আমি বিবৃতিতে Attempting to grow...ত্রুটি পেয়েছি set @GGMMsg=...। 2008 সালে, স্ক্রিপ্টটি সফল is
জো স্টেফেনেলি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.