मैं स्मृति से बाहर चलने के बिना कई आवेषण के साथ एक बड़ी स्क्रिप्ट कैसे चला सकता हूं?


28

सवाल:

मेरे पास चुनिंदा बयानों से लगभग 45 हजार डालने के साथ एक स्क्रिप्ट है। जब मैं कोशिश करता हूं और इसे चलाता हूं, तो मुझे एक त्रुटि संदेश मिलता है जिसमें कहा गया है कि मैं स्मृति से बाहर चला गया हूं। मैं इस स्क्रिप्ट को कैसे चला सकता हूं?

प्रसंग:

  1. एक ऐप को क्लाइंट द्वारा उपयोग किए जाने वाले ऐप के साथ अच्छा बनाने के लिए कुछ नए डेटा फ़ील्ड जोड़े गए।
  2. उन डेटा से भरे क्लाइंट से डेटा की एक स्प्रेडशीट प्राप्त करें जो इन नए क्षेत्रों के लिए वर्तमान डेटा आइटम को मैप करता है।
  3. स्टेटमेंट डालने के लिए परिवर्तित स्प्रैडशीट।
  4. अगर मैं केवल कुछ बयानों को चलाता हूं तो यह काम करता है लेकिन पूरी स्क्रिप्ट नहीं है।
  5. नहीं, कोई टाइपो नहीं हैं।

यदि कोई अलग तरीका है, तो मुझे इस डेटा को लोड करना चाहिए ताकि मैं इसका पीछा कर सकूं और मुझे बता सकूं।


SO पर इसी तरह का सवाल: ( stackoverflow.com/questions/222442/… ) यकीन नहीं होता अगर जवाब मदद करता है
जम्पडार्ट

जवाबों:


17

SQL Server 2005 के लिए अधिकतम बैच का आकार 65,536 * नेटवर्क पैकेट आकार (NPS) है, जहाँ NPS आमतौर पर 4KB होता है। यह 256 एमबी तक काम करता है। इसका मतलब यह होगा कि आपके इंसर्ट स्टेटमेंट 5.8 केबी औसतन होंगे। यह सही प्रतीत नहीं होता है, लेकिन हो सकता है कि वहाँ कोई बाहरी स्थान या कुछ असामान्य हो।

मेरा पहला सुझाव हर INSERT के बयान के बाद "GO" स्टेटमेंट डालना होगा। यह 45,000 INSERT कथनों के अपने एकल बैच को 45,000 अलग-अलग बैचों में तोड़ देगा। यह पचाने में आसान होना चाहिए। सावधान रहें, यदि उन आवेषणों में से एक विफल हो जाता है तो आपको अपराधी को खोजने में मुश्किल समय हो सकता है। आप लेन-देन से अपनी सुरक्षा करना चाहते हैं। यदि आपके संपादक की अच्छी खोज-और-जगह है, तो आप उन कथनों को शीघ्रता से जोड़ सकते हैं (जो आपको \ n \ _) या मैक्रो सुविधा जैसे वापसी वर्णों को खोजने और बदलने देंगे।

दूसरा सुझाव एक्सेल से सीधे डेटा आयात करने के लिए एक विज़ार्ड का उपयोग करना है। विज़ार्ड आपके लिए, दृश्यों के पीछे, और उसके बाद थोड़ा SSIS पैकेज बनाता है। यह यह समस्या नहीं होगी।


2
हर बयान के GOबाद एक ? ठीक है, मुझे लगता है कि यदि आप उन्हें एक और स्क्रिप्ट का उपयोग करके उत्पन्न कर रहे हैं जो ठीक है। अन्यथा, मैं हर १००० के बाद एक लगाता हूँ । लेन-देन को परमाणु बनाने और लेन-देन के आकार को कम करने के संबंध में, सभी पंक्तियों को एक अस्थायी तालिका या टेबल चर में क्यों नहीं लोड करें और फिर उन्हें वहां से एक शॉट में लक्ष्य तालिका में लोड करें? INSERT
निक चामास

एक 1000 सिर्फ 1 के रूप में अच्छा है, लेकिन गिनती करना कठिन है। सच कहूं तो, वह केवल एक GO स्टेटमेंट के साथ, आधे रास्ते के निशान पर, बयान 21,500 के पास से दूर हो सकता है। मुझे GO फिक्स पसंद है क्योंकि इसमें वर्तमान स्क्रिप्ट के जटिल संपादन की आवश्यकता नहीं है, या INSERT स्टेटमेंट्स की गिनती करना (जो कि सीधे संख्याओं के लिए मैप नहीं हो सकता है)।
डारिन स्ट्रेट

2
निश्चित रूप से, यहां तक ​​कि 1000 बयानों का एक बुरा अनुमान काफी अच्छा है। :)
निक चम्मास

1
GOs को जोड़ना एक त्वरित और आसान फिक्स था .. 25mb स्क्रिप्ट बिना किसी समस्या के 9min से थोड़ा कम में चलती है। जब यह बाहर जाता है, तो इसे हमारे मानक पैच परिनियोजन प्रक्रिया के भीतर रखने के लिए एक स्क्रिप्ट के रूप में होना चाहता था।
स्पेगेटीकोवॉय

14

BULK INSERTया bcp45,000 सम्मिलित विवरणों की तुलना में अधिक उपयुक्त विकल्प प्रतीत होते हैं।

यदि आपको आवेषण कथनों के साथ चिपकना है, तो मैं कुछ विकल्पों पर विचार करूंगा:

ए: लॉग और बैच पर प्रभाव को कम करने के लिए प्रत्येक में 100 या 500 या 1000 बयानों के लेनदेन और रैप बैचों का उपयोग करें। जैसे

BEGIN TRANSACTION;
INSERT dbo.table(a, ...) SELECT 1, ...
INSERT dbo.table(a, ...) SELECT 2, ...
...
INSERT dbo.table(a, ...) SELECT 500, ...
COMMIT TRANSACTION;
GO

BEGIN TRANSACTION;
INSERT dbo.table(a, ...) SELECT 1, ...
INSERT dbo.table(a, ...) SELECT 2, ...
...
INSERT dbo.table(a, ...) SELECT 500, ...
COMMIT TRANSACTION;
GO

बी: व्यक्तिगत डालने के बयानों के बजाय, UNION ALLएक बार में 100 या 500 बयानों का उपयोग करें , जैसे

INSERT dbo.table(a, ...)
SELECT 1, ...
UNION ALL SELECT 2, ...
...
UNION ALL SELECT 500, ...
GO

INSERT dbo.table(a, ...)
SELECT 501, ...
UNION ALL SELECT 502, ...
...
UNION ALL SELECT 1000, ...
GO

मैंने संक्षिप्तता के लिए त्रुटि को छोड़ दिया है, लेकिन मुद्दा यह है कि मैं SQL सर्वर पर 45,000 व्यक्तिगत बयानों का एक भी बैच भेजने की कोशिश नहीं करूंगा।


1
बहुत बुरा ओपी टेबल-वैल्यू बिल्डरों का उपयोग नहीं कर सकता , 2008+ की सुविधा। उसे अभी भी आवेषण को 1000 पंक्तियों के समूहों में बैचना होगा, जो कि अधिकतम है जिसे आप टीवीसी के साथ मिलकर कर सकते हैं।
निक चामास

यह मेरा पहला सुझाव होने जा रहा था जब तक कि मैंने संस्करण टैग नहीं देखा।
हारून बर्ट्रेंड

2
@NickChammas - बीटीडब्ल्यू मानों की संख्या के साथ गैर-रैखिक रूप से उन लोगों के प्रदर्शन में गिरावट आती है । मैंने 2008 में 10.5 कॉलम के साथ 1000 पंक्तियाँ डालने की एक रीप्रो के साथ एक कनेक्ट आइटम प्रस्तुत किया था, जो कि मेरे 2008 देव उदाहरण पर 12.5 मिनट के संकलन समय के VARCHAR(800)साथ है क्योंकि यह केवल डालने के साथ ही प्राप्त करने के बजाय मूल्यों की तुलना में अनावश्यक काम करता है। तेज जब पैरामीटर और कोई मूल्यों को देखने के लिए)। हालांकि 2012 में बहुत सुधार हुआ है, लेकिन अभी भी नॉन लीनियर पैटर्न मौजूद है और इसके बाद के संस्करण में तय किया जाना चाहिए।
मार्टिन स्मिथ

9

मुझे यकीन नहीं है कि आप मेमोरी त्रुटि से बाहर निकल रहे हैं, लेकिन एक आसान तरीका है।

यदि आप स्प्रेडशीट से डेटा को एक सीमांकित प्रारूप (जैसे सीएसवी) में निर्यात कर सकते हैं, तो आप डेटा डालने के लिए एसएसएमएस में डेटा आयात विज़ार्ड का उपयोग कर सकते हैं:

SSMS डेटा कार्य आयात करता है।


यह उपयोगी है, लेकिन मैं ग्राहक डेटाबेस तक पहुँच नहीं है। मैं स्क्रिप्ट में पैच और dataloads तैयार करना है
spaghetticowboy

0

एकाधिक SqlBulkCopy का उपयोग करके, एक अस्थायी तालिका बनाएं। अस्थायी तालिका में नया डेटा सम्मिलित करें, फिर अस्थायी तालिका में डेटा को मौजूदा में मर्ज करें। C # SqlBulkCopy.WriteToServer Method (DataTable) का उपयोग करके उदाहरण । आशा करता हूँ की ये काम करेगा


0

हां, हम ऐसा कर सकते हैं, मैंने आउटऑफमेरी मुद्दे से बचने के लिए बीसीपी (बल्क कॉपी प्रोग्राम) दृष्टिकोण के साथ प्रयास किया ।

नोट : SQL सर्वर 2014 पर कोशिश की गई।

BCP में, पहले हमें स्रोत डेटाबेस डेटा को bcp फ़ाइल (स्थानीय निर्देशिका फ़ोल्डर में) में निर्यात करने की आवश्यकता है और फिर गंतव्य डेटाबेस में उस bcp फ़ाइल को आयात करने की आवश्यकता है ।

यहाँ छवि विवरण दर्ज करें

नीचे केक चलने के चरण दिए गए हैं:

ध्यान दें:

क) सुनिश्चित करें कि खाली तालिका गंतव्य डेटाबेस में मौजूद है

बी) सुनिश्चित करें कि अस्थायी फ़ोल्डर सी ड्राइव में मौजूद है

  1. नीचे दिखाए गए कमांड के साथ Export_Data.bat नाम की एक बैट फ़ाइल बनाएँ :

    bcp.exe [Source_DataBase_Name].[dbo].[TableName] OUT "C:\Temp\TableName.bcp" -S "Computer Name" -U "SQL Server UserName" -P "SQL Server Password" -n -q 

    ठहराव

  2. उस बैट फ़ाइल को चलाएँ, जिसके परिणामस्वरूप bcp फ़ाइल Temp फ़ोल्डर में जनरेट हो जाएगी

  3. फिर एक अन्य बैट फ़ाइल बनाएँ, जिसका नाम Import_Data.bat है , जो निम्न कमांड के साथ है:

    bcp.exe [Destination_DataBase_Name].[dbo].[TableName] IN "C:\Temp\TableName.bcp" -S "Computer Name" -U "SQL Server UserName" -P "SQL Server Password" -n -q 

    ठहराव

और अब हम चले!


त्रुटि प्राप्त करना "एक वैध तालिका नाम के लिए, बाहर, या प्रारूप विकल्पों के लिए आवश्यक है।" जब डेटा निर्यात करने का प्रयास किया गया।
सेन जैकब

1
क्या आप सभी विशेषता मान के साथ आजमाई गई कमांड को पेस्ट कर सकते हैं। कृपया नीचे दिए गए उदाहरण का अनुसरण करें: bcp.exe ExportDB.dbo.AddressCountry OUT "C: \ Temp \ AddressCountry.bcp" -S "IN-L20054" -U "sa" -पी "सा" -n -q उस [ExportDB -> स्रोत DB, AddressCountry-> तालिका वर्तमान स्रोत DB, IN-L20054 में -> मशीन का नाम, "सा" DB का उपयोगकर्ता नाम / pwd है]
Kms

मेरे पास अब नहीं है। मैंने SSMS में आयात डेटा सुविधा का उपयोग करके समाप्त किया। फिर एमएस डीएलई डीबी कनेक्शन का उपयोग करके डीबी (v14.0) को स्रोत डीबी (v.15.0) से जोड़ा गया और यह डेटा की बहु-मिलियन पंक्तियों को आयात करने के लिए काफी तेज था। धन्यवाद!
सेन जैकब
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.