2010-02-19 8 views
8

मैं वर्तमान में जब SQL सर्वर 2005 पर के साथ एक sql फ़ाइल को क्रियान्वित करने 26MB के बारे में त्रुटि संदेश निम्न हो रही है से बाहर:SQL सर्वर 2005 त्रुटि 701 - स्मृति

Msg 701, Level 17, State 123 
There is insufficient system memory to run this query. 

मैं 4GB रैम के साथ काम कर रहा हूँ, 64 बिट विंडोज 7 अल्टीमेट, कोर 2 डीओओ टी 6400 (2GHz) ...

क्या यह संदेश प्राप्त किए बिना इसे निष्पादित करने का कोई तरीका है (शायद एसक्यूएल सर्वर को स्वैप फ़ाइल का उपयोग करने के लिए मजबूर करें?) या इसे भागों में निष्पादित करने का एक तरीका (जैसे 100 प्रश्न एक समय) ...

फ़ाइल मूल रूप से एक CREATE तालिका है जिसके बाद INSER के thousads टी प्रश्न और मेरे पास बहुत सारे हैं (एबीसी डीबीएफ कन्वर्टर का उपयोग कर एसक्यूएल प्रश्नों में परिवर्तित डीबीएफ फाइलें)

किसी भी विचार की बहुत सराहना की जाएगी!

उत्तर

9

यह प्रश्न वास्तव में यहां हर बार आने लगता है। Mark में सही (और आमतौर पर नियोजित) उत्तर है, लेकिन मुझे यह स्पष्ट करने के लिए जो कुछ भी मैं कर सकता हूं उसे जोड़ने की कोशिश करता हूं।

त्रुटि संदेश थोड़ा भ्रामक है। एसक्यूएल सर्वर आपको बताता है कि इसमें रन क्वेरी के लिए पर्याप्त स्मृति नहीं है, लेकिन इसका वास्तव में क्या अर्थ है कि इसमें पार्स क्वेरी के लिए पर्याप्त स्मृति नहीं है।

जब क्वेरी चल रहा है, तो SQL सर्वर सभी आवश्यकतानुसार उपयोग कर सकता है - यदि आवश्यक हो तो गीगाबाइट्स। पार्सिंग एक और कहानी है; सर्वर को एक पार्स पेड़ बनाना है और इसके लिए केवल स्मृति की एक सीमित मात्रा उपलब्ध है। मुझे कहीं भी दस्तावेज की वास्तविक सीमा कभी नहीं मिली है, लेकिन INSERT कथन से भरा एक सामान्य बैच के लिए, यह एक समय में कुछ एमबी से अधिक संभाल नहीं सकता है।

तो मुझे आपको यह बताने में खेद है कि आप नहीं कर सकते हैं SQL सर्वर इस स्क्रिप्ट को ठीक उसी तरह निष्पादित करता है जैसा लिखा है। कोई रास्ता नहीं, कोई फर्क नहीं पड़ता कि आप किन सेटिंग्स को ट्विक करते हैं।

  1. उपयोग GO बयान:

    विशेष रूप से, आप तीन विकल्प हैं: आप करते हैं, हालांकि, विकल्पों में से एक नंबर उसके चारों ओर काम करना है। इसका उपयोग एसएसएमएस और बैच विभाजक के रूप में कई अन्य उपकरणों द्वारा किया जाता है। पूरी लिपि के लिए एक ही पार्स पेड़ उत्पन्न होने के बजाय, GO से अलग बैच के प्रत्येक खंड के लिए अलग-अलग पार्स पेड़ उत्पन्न होते हैं। अधिकांश लोग ऐसा करते हैं, और स्क्रिप्ट को लेनदेन-सुरक्षित बनाने के लिए यह बहुत आसान है, जैसा कि अन्य ने दिखाया है और मैं यहां दोहराना नहीं चाहूंगा।

  2. सभी पंक्तियों को सम्मिलित करने के लिए एक विशाल स्क्रिप्ट उत्पन्न करने के बजाय, डेटा को एक टेक्स्ट फ़ाइल (यानी अल्पविराम से अलग) में रखें। फिर इसे bcp utility का उपयोग करके आयात करें। यदि आपको इसे "स्क्रिप्ट करने योग्य" होने की आवश्यकता है - यानी आयात को उसी स्क्रिप्ट/लेनदेन में CREATE TABLE कथन के रूप में होने की आवश्यकता है, तो इसके बजाय BULK INSERT का उपयोग करें। हालांकि BULK INSERT एक गैर-लॉगऑन ऑपरेशन है, मान लीजिए या नहीं, इसे अभी भी BEGIN TRAN/COMMIT TRAN ब्लॉक में रखा जा सकता है।

  3. आप सच में, सच, INSERT एक लॉग इन आपरेशन होने के लिए, और बैचों में है, तो आप OPENROWSET उपयोग कर सकते हैं एक पाठ फ़ाइल को खोलने के लिए सम्मिलन हो नहीं करना चाहती चाहते हैं फ़ाइल एक्सेल, एक के रूप में आदि ad-hoc "table", और उसके बाद इसे अपनी नव निर्मित तालिका में डालें। मैं आमतौर पर OPENROWSET के उपयोग की अनुशंसा करता हूं, लेकिन चूंकि यह स्पष्ट रूप से एक प्रशासनिक लिपि है, यह वास्तव में एक बड़ी समस्या नहीं है।


पिछला टिप्पणियों सुझाव है कि आप # 1 के साथ असहज कर रहे हैं, हालांकि यह सिर्फ एक गलत धारणा है कि यह एक एकल लेनदेन में नहीं किया जा सकता की वजह से हो सकता है, जिसमें मामले Thomas देख ' जवाब लेकिन अगर आप किसी अन्य तरीके से मरने के लिए तैयार हैं, तो मैं सुझाव देता हूं कि # 2 के साथ जाकर, एक टेक्स्ट फ़ाइल बनाएं और BULK INSERT का उपयोग करें। एक "सुरक्षित" स्क्रिप्ट का एक उदाहरण होगा:

BEGIN TRAN 

BEGIN TRY 

    CREATE TABLE MyTable (...) 

    BULK INSERT MyTable 
    FROM 'C:\Scripts\Data\MyTableData.txt' 
    WITH (
     FIELDTERMINATOR = ',', 
     ROWTERMINATOR = '\r\n', 
     BATCHSIZE = 1000, 
     MAXERRORS = 1 
    ) 

    COMMIT 

END TRY 

BEGIN CATCH 

    ROLLBACK 

END CATCH 

उम्मीद है कि इस सही रास्ते पर डाल मदद करता है। मुझे पूरा यकीन है कि यह आपके सभी उपलब्ध "बॉक्स में" विकल्पों को कवर करता है - इनके अलावा, आपको काम करने के लिए वास्तविक एप्लिकेशन प्रोग्राम या शैल स्क्रिप्ट लिखना शुरू करना होगा, और मुझे नहीं लगता कि जटिलता का स्तर है वास्तव में यहाँ वांछित।

4

आप फ़ाइल को कई बैचों में तोड़ सकते हैं - उदा। प्रत्येक हज़ार आवेषण

उदा।

insert db..table(field list) values ... 
insert db..table(field list) values ... 
go 
insert db..table(field list) values ... 
... 
insert db..table(field list) values ... 
go 

एक और तरीका हो सकता है आप जैसे थोक अपलोड करने का उपयोग BCP

+0

संपादित होने तक, उसका मतलब है कि हर हज़ार डालने के बाद 'जाओ' कथन जोड़ना। –

+0

धन्यवाद एलेक्स - सुझाए गए – Mark

+0

के रूप में अपडेट किया गया है, मैंने समस्या को हल करने के लिए पहले से ही गो स्टेटमेंट का उपयोग किया है, लेकिन मैं बैच-निष्पादन का उपयोग नहीं करना चाहता क्योंकि अगर मुझे कोई त्रुटि है तो मुझे रोलबैकिंग लेनदेन में समस्या होगी ... – Tufo

0

इसके अलावा GO बयान हर इतने सारे रिकॉर्ड, अगर आप या वापस रोलिंग पूरी बात चल बारे में चिंतित हैं तो तरह लेन-देन का उपयोग छिड़काव:

SET XACT_ABORT ON 
BEGIN TRAN 

Insert ... 
Insert ... 
Insert ... 
... 
GO 
Insert .. 
Insert .. 
Insert .. 
GO 

If @@TranCount > 0 Commit Tran 

XACT_ABORT के साथ चालू पर सेट, किसी भी डालने बयान जो विफल रहता है पूरे लेनदेन को रोलबैक करेगा।

-1

आप की तरह जोड़ सकते हैं बी सी सी में आदेश अपने एसक्यूएल प्रश्नों के बीच:

DBCC FREESYSTEMCACHE ('ALL') 
GO 
DBCC FREESESSIONCACHE 
GO 
DBCC FREEPROCCACHE 
GO 

यह मदद मिलेगी जारी स्मृति। साथ ही, माइक्रोसॉफ्ट एसक्यूएल सर्वर 2005 में इस मुद्दे को हल करने के लिए एक हॉटफिक्स जारी करता है (देखें here)। हॉटफिक्स \ सर्विस पैक को स्थापित करने का प्रयास करें।