एक चर (अधिकतम) चर का अधिकतम आकार


89

अतीत में किसी भी समय, अगर किसी ने मुझसे अधिकतम आकार पूछा है varchar(max), तो मैंने 2GB कहा होगा, या एक अधिक सटीक आंकड़ा (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)

तो, यह देखते हुए कि अब मुझे पता है कि एक चर 2GB अवरोध को पार कर सकता है - क्या कोई जानता है कि एक varchar(max)चर के लिए वास्तविक सीमा क्या है ?


(SQL Server 2008 पर पूरा परीक्षण ऊपर (R2 नहीं)। मुझे यह जानने में दिलचस्पी होगी कि क्या यह अन्य संस्करणों पर लागू होता है)


declare @x varchar(max) = 'XX'; SELECT LEN(REPLICATE(@x,2147483647))4294967294मेरे लिए देता है लेकिन दौड़ने में लंबा समय लेता है - SELECTवापस आने के बाद भी सुनिश्चित नहीं है कि अतिरिक्त समय क्या कर रहा है।
मार्टिन स्मिथ

जवाबों:


74

जहां तक ​​मैं बता सकता हूं कि 2008 में कोई ऊपरी सीमा नहीं है।

SQL Server 2005 में @GGMMsgचर के साथ असाइनमेंट पर आपके प्रश्न में कोड विफल रहता है

2,147,483,647 बाइट्स के अधिकतम अनुमत आकार से परे LOB बढ़ने का प्रयास।

नीचे दिए गए कोड के साथ विफल रहता है

REPLICATE: परिणाम की लंबाई लक्ष्य बड़े प्रकार की लंबाई सीमा (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गणना में यह वृद्धि नहीं हुई।

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

इसके अलावा

मैंने भी समवर्ती nvarchar(max) + nvarchar(max)और के साथ व्यवहार का परीक्षण किया है nvarchar(max) + varchar(max)। ये दोनों 2GB की सीमा को पार करने की अनुमति देते हैं। फिर इसके परिणामों को एक तालिका में संग्रहीत करने की कोशिश करना, फिर त्रुटि संदेश के साथ फिर से विफल हो जाता है 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

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

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

@Damien_The_Unbeliever - यहाँ का प्रलेखन यहाँ के प्रयोगों के आधार पर गलत प्रतीत होता है, जिसमें स्पष्ट रूप से स्पष्ट रूप से कहा गया है कि "बड़ी वस्तु (LOB) डेटा प्रकार चर और पैरामीटर ... प्रकार आकार में 2 GB तक हो सकते हैं"
मार्टिन स्मिथ

हालांकि बेकार बेकार लेकिन दिलचस्प। सिद्धांत रूप में आप डिस्क को एक चर के साथ भर सकते हैं ... :-)
gbn

मुझे यहाँ कुछ झिझक है क्योंकि किसी वैरिएबल में वैल्यू स्टोर करना एक कॉलम में स्टोर करने जैसा नहीं है। क्या आपको इसके बजाय एक कॉलम के साथ ऐसा करने का मन करता है - या क्या आपके पास कोई अपडेट है? यहां तक ​​कि SQL सर्वर 2000 varcharमें कोड में शाब्दिक तार में 8000 से अधिक वर्ण हो सकते हैं , जब तक कि आपने इसे एक चर या varcharकॉलम में डालने की कोशिश नहीं की थी ।
ErikE

9

संपादित करें : आगे की जांच के बाद, मेरी मूल धारणा यह है कि यह 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)

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

@Damien_The_Unbeliever: मैंने स्क्रिप्ट को केवल चर भाग तक काट दिया है और अब आप के समान परिणाम प्राप्त करते हैं। 2005 में, मुझे कथन Attempting to grow...पर त्रुटि मिली set @GGMMsg=...। 2008 में, स्क्रिप्ट सफल है।
जो स्टेफनेली सेप
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.