2011-09-30 21 views
76

किसी भी समय अतीत में, अगर किसी ने मुझे varchar(max) के लिए अधिकतम आकार पूछा था, तो मैंने 2 जीबी कहा होगा, या अधिक सटीक figure (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) चर के लिए क्या है?


+0

'घोषणा @x वर्कर (अधिकतम) = 'एक्सएक्स'; चयन करें लेंस (उत्तर दें (@ x, 2147483647)) 'मेरे लिए '42 9 4 9 672 9 4' देता है लेकिन 'चयन' वापस आने के बाद भी चलाने में लंबा समय लगता है, इसलिए यह सुनिश्चित न करें कि उस अतिरिक्त समय में क्या खर्च किया जा रहा है। –

उत्तर

62

जहां तक ​​मेरा बता सकते हैं 2008 में

कोई ऊपरी सीमा SQL सर्वर 2005 में अपने प्रश्न में कोड

प्रयास कर रहा है के साथ @GGMMsg चर करने के लिए काम पर विफल रहता है में है 2,147,483,647 बाइट्स के अधिकतम स्वीकृत आकार से अधिक LOB को बढ़ाने के लिए। नीचे

कोड के साथ

को दोहराने में विफल रहता है: परिणाम की लंबाई लक्ष्य बड़े आकार की लंबाई सीमा (2GB) से अधिक है।

हालांकि ऐसा लगता है कि इन सीमाओं को चुपचाप हटा लिया गया है।2008 को

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

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

SELECT LEN(@y) 

रिटर्न

8589767761 

मैं अपने 32 बिट डेस्कटॉप मशीन पर इस भाग गया तो यह 8GB स्ट्रिंग चल रहा है

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 गणना में वृद्धि नहीं हुई।

इसका उल्लेख करने का कारण यह है क्योंकि पृष्ठ की गणना मुझे अपेक्षा से अधिक है। एक 8 केबी पेज मानते हुए यह 16.36 जीबी पर काम करता है जो स्पष्ट रूप से आवश्यक होता है जो कम या ज्यादा दोगुना होता है। मैं अनुमान लगाता हूं कि यह स्ट्रिंग कॉन्सटेनेशन ऑपरेशन की अक्षमता के कारण पूरे विशाल स्ट्रिंग की प्रतिलिपि बनाने की आवश्यकता है और मौजूदा स्ट्रिंग के अंत में जोड़ने में सक्षम होने के बजाय अंत में एक खंड को जोड़ना है। दुर्भाग्य से इस समय .WRITE वर्चर (अधिकतम) चर के लिए isn't supported विधि।

अलावा

मैं भी 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 
+0

उत्कृष्ट - तो ऐसा प्रतीत होता है कि प्रलेखन बल्कि "अधूरा" है - मुझे लगता है कि सामान्य पृष्ठ अधिकतम "भंडारण आकार" को संदर्भित करता है, जो संभावित रूप से केवल कॉलम पर लागू होता है, चर नहीं। –

+0

@ डेमियन - निश्चित रूप से उस तरह से प्रकट होता है। निश्चित नहीं है कि कुछ अन्य सीमाएं हैं जिन्हें पृष्ठों की कुल संख्या के संदर्भ में पहुंचा जा सकता है लेकिन मुझे लगता है कि यह बी वृक्ष संरचना (एसक्यूएल सर्वर 2008 आंतरिक के पी.381 के आधार पर) में संग्रहीत है, इसलिए सिद्धांत रूप में निश्चित रूप से विस्तार किया जा सकता है। –

+0

@Damien_The_Unbeliever - [यहां प्रलेखन] (http://msdn.microsoft.com/en-us/library/ms345368.aspx) यहां प्रयोगों के आधार पर गलत साबित होता है, जो स्पष्ट रूप से स्पष्ट रूप से बताता है कि "बड़ी वस्तु (LOB) डेटा प्रकार चर और पैरामीटर ... प्रकार 2 जीबी आकार में हो सकते हैं " –

9

संपादित (। एसक्यूएल सर्वर 2008 (नहीं R2) पर पूरा परीक्षण से ऊपर मुझे कोई दिलचस्पी को पता है कि क्या यह अन्य संस्करणों पर लागू होता होगा): आगे की जांच पड़ताल करने के बाद, अपने मूल धारणा यह है कि यह declare @var datatype = value वाक्यविन्यास का एक विसंगति (बग?) गलत था।

मैंने 2005 के लिए अपनी स्क्रिप्ट संशोधित की है क्योंकि वाक्यविन्यास समर्थित नहीं है, फिर 2008 में संशोधित संस्करण की कोशिश की। 2005 में, मुझे Attempting to grow LOB beyond maximum allowed size of 2147483647 bytes. त्रुटि संदेश मिला। 2008 में, संशोधित लिपि अभी भी सफल है।

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

स्क्रिप्ट हमेशा एक त्रुटि उत्पन्न करती है (तालिका सम्मिलित करने का प्रयास करके), लेकिन 2008 में, मुझे हमेशा पहले परिणाम सेट में एक परिणाम मिलता है, यह दर्शाता है कि चर मौजूद है, और लंबाई 2^31-1 से अधिक है । –

+0

@Damien_The_Unbeliever: मैंने स्क्रिप्ट को केवल परिवर्तनीय भाग में काट दिया और अब आपके जैसा ही परिणाम प्राप्त करें। 2005 में, मुझे 'सेट @GGMMsg = ...' कथन पर 'बढ़ने का प्रयास ...' त्रुटि मिलती है। 2008 में, लिपि सफल रही है। –

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