दिलचस्प पोस्ट
मुख्य थ्रेड में दूसरे थ्रेड से कोड चलाना iPhone / iPad के लिए जावास्क्रिप्ट स्क्रॉल ईवेंट? एंड्रॉइड स्रोत कोड का मुख्य तरीका क्या नहीं है और अभी भी चल रहा है? मैं आईओएस में एक कस्टम फ़ाइल प्रकार कैसे पंजीकृत करूं? एंड्रॉइड: इरादा के माध्यम से फेसबुक पर टेक्स्ट के साथ छवि कैसे साझा करें? वर्तमान तिथि / समय सेकंड में प्राप्त करें Chrome.notifications API को कुछ सेकंड के बाद मेरी सूचना को छुपाने से रोकें कैसे युनिकोड स्ट्रिंग्स के साथ डीजेंगो का काम ठीक से करने के लिए? सबसेट एक्सट्स ऑब्जेक्ट दिन के समय से कैसे जावा में पथ गठबंधन करने के लिए? मैं स्वागत पृष्ठ को स्ट्रट्स एक्शन के लिए कैसे सेट कर सकता हूं? SQL सर्वर चुपचाप varchar की संग्रहीत कार्यविधियों में छंटनी करता है Src और सामग्री के साथ स्क्रिप्ट टैग क्या होता है? अजाक्स कॉलिंग यूआरएल का पता लगाएं जावा में जेएसएन में सूची डेटा को कैसे रूपांतरित करें

कम से कम समय में 10 मिलियन रिकॉर्ड कैसे सम्मिलित कर सकते हैं?

मेरे पास एक फ़ाइल है (जिसमें 10 मिलियन रिकॉर्ड हैं) नीचे दिए गए हैं:

line1 line2 line3 line4 ....... ...... 10 million lines 

तो मूल रूप से मैं डेटाबेस में 10 मिलियन रिकॉर्ड सम्मिलित करना चाहता हूं। इसलिए मैंने फाइल को पढ़ा और इसे SQL सर्वर पर अपलोड किया

सी # कोड

 System.IO.StreamReader file = new System.IO.StreamReader(@"c:\test.txt"); while((line = file.ReadLine()) != null) { // insertion code goes here //DAL.ExecuteSql("insert into table1 values("+line+")"); } file.Close(); 

लेकिन सम्मिलन में एक लंबा समय लगेगा मैं सी # का उपयोग कर कम से कम समय में 10 मिलियन रिकॉर्ड कैसे जोड़ सकता हूं?

अपडेट 1:
थोक INSERT:

 BULK INSERT DBNAME.dbo.DATAs FROM 'F:\dt10000000\dt10000000.txt' WITH ( ROWTERMINATOR =' \n' ); 

मेरी टेबल नीचे की तरह है:

 DATAs ( DatasField VARCHAR(MAX) ) 

लेकिन मुझे निम्नलिखित त्रुटि मिल रही है:

संदेश 4866, स्तर 16, राज्य 1, रेखा 1
बल्क लोड विफल हुआ स्तंभ 1, कॉलम 1 के लिए डेटा फ़ाइल में बहुत लंबा है। सत्यापित करें कि फ़ील्ड टर्मिनेटर और पंक्ति टर्मिनेटर को सही ढंग से निर्दिष्ट किया गया है।

संदेश 7399, स्तर 16, राज्य 1, रेखा 1
लिंक किए गए सर्वर "(रिक्त)" के लिए ओएलई डीबी प्रदाता "बल्क" ने एक त्रुटि की सूचना दी। प्रदाता ने त्रुटि के बारे में कोई जानकारी नहीं दी

संदेश 7330, स्तर 16, राज्य 2, रेखा 1
लिंक किए गए सर्वर "(रिक्त)" के लिए OLE DB प्रदाता "BULK" से एक पंक्ति प्राप्त नहीं कर सकता

नीचे कोड काम किया है:

 BULK INSERT DBNAME.dbo.DATAs FROM 'F:\dt10000000\dt10000000.txt' WITH ( FIELDTERMINATOR = '\t', ROWTERMINATOR = '\n' ); 

Solutions Collecting From Web of "कम से कम समय में 10 मिलियन रिकॉर्ड कैसे सम्मिलित कर सकते हैं?"

BulkCopy के माध्यम से लोड करने के लिए कृपया कोई DataTable बनाएं। यह डेटा के छोटे सेट के लिए ठीक समाधान है, लेकिन डेटाबेस को कॉल करने से पहले सभी 10 मिलियन पंक्तियों को स्मृति में लोड करने का कोई कारण नहीं है।

आपकी सबसे अच्छी शर्त ( BCP / BULK INSERT / OPENROWSET(BULK...) ) तालिका से महत्वपूर्ण मानदंड (टीवीपी) के माध्यम से फाइल में सामग्री को फाइल में प्रसारित करना है। एक TVP का उपयोग करके आप फ़ाइल खोल सकते हैं, एक पंक्ति पढ़ सकते हैं और एक पंक्ति को तब तक भेज सकते हैं जब तक कि फ़ाइल को बंद न करें। इस पद्धति में सिर्फ एक ही पंक्ति का एक मेमोरी पदचिह्न है मैंने एक लेख लिखा, SQL Server 2008 में डेटा स्ट्रीमिंग , एक आवेदन से , जिसमें इस परिदृश्य का एक उदाहरण है

संरचना का एक सरलीकृत अवलोकन निम्न प्रकार है। ऊपर दिए गए प्रश्न में दिखाए गए अनुसार मैं समान आयात तालिका और फ़ील्ड नाम मान रहा हूं।

आवश्यक डेटाबेस ऑब्जेक्ट्स:

 -- First: You need a User-Defined Table Type CREATE TYPE ImportStructure AS TABLE (Field VARCHAR(MAX)); GO -- Second: Use the UDTT as an input param to an import proc. -- Hence "Tabled-Valued Parameter" (TVP) CREATE PROCEDURE dbo.ImportData ( @ImportTable dbo.ImportStructure READONLY ) AS SET NOCOUNT ON; -- maybe clear out the table first? TRUNCATE TABLE dbo.DATAs; INSERT INTO dbo.DATAs (DatasField) SELECT Field FROM @ImportTable; GO 

उपरोक्त SQL ऑब्जेक्ट्स का उपयोग करने के लिए सी # ऐप कोड नीचे है। ऑब्जेक्ट (जैसे डेटाटाइल) को भरने और उसके बाद संग्रहीत कार्यविधि को निष्पादित करने की बजाए नोटिस कैसे इस पद्धति में यह संग्रहित प्रक्रिया का निष्पादन है जो फ़ाइल सामग्री के पढ़ने की शुरुआत करता है। संसाधित प्रोक का इनपुट पैरामीटर एक चर नहीं है; यह एक विधि का वापसी मूल्य है, GetFileContents उस विधि को तब कहा जाता है जब SqlCommand ExecuteNonQuery कॉल करता है, जो फ़ाइल को खोलता है, एक पंक्ति पढ़ता है और IEnumerable<SqlDataRecord> और yield return निर्माण के माध्यम से पंक्ति को SQL सर्वर पर भेजता है, और फिर फ़ाइल को बंद कर देता है। संग्रहीत कार्यविधि में सिर्फ एक टेबल वैरिएबल, @ImportTable देखता है, जो डेटा पर आने पर जैसे ही पहुंच हो सकती है ( ध्यान दें: डेटा थोड़े समय तक जारी रहता है, भले ही पूर्ण सामग्री नहीं, tempdb में )

 using System.Collections; using System.Data; using System.Data.SqlClient; using System.IO; using Microsoft.SqlServer.Server; private static IEnumerable<SqlDataRecord> GetFileContents() { SqlMetaData[] _TvpSchema = new SqlMetaData[] { new SqlMetaData("Field", SqlDbType.VarChar, SqlMetaData.Max) }; SqlDataRecord _DataRecord = new SqlDataRecord(_TvpSchema); StreamReader _FileReader = null; try { _FileReader = new StreamReader("{filePath}"); // read a row, send a row while (!_FileReader.EndOfStream) { // You shouldn't need to call "_DataRecord = new SqlDataRecord" as // SQL Server already received the row when "yield return" was called. // Unlike BCP and BULK INSERT, you have the option here to create a string // call ReadLine() into the string, do manipulation(s) / validation(s) on // the string, then pass that string into SetString() or discard if invalid. _DataRecord.SetString(0, _FileReader.ReadLine()); yield return _DataRecord; } } finally { _FileReader.Close(); } } 

नीचे दी गई GetFileContents विधि को GetFileContents प्रक्रिया के लिए इनपुट पैरामीटर मान के रूप में उपयोग किया जाता है:

 public static void test() { SqlConnection _Connection = new SqlConnection("{connection string}"); SqlCommand _Command = new SqlCommand("ImportData", _Connection); _Command.CommandType = CommandType.StoredProcedure; SqlParameter _TVParam = new SqlParameter(); _TVParam.ParameterName = "@ImportTable"; _TVParam.TypeName = "dbo.ImportStructure"; _TVParam.SqlDbType = SqlDbType.Structured; _TVParam.Value = GetFileContents(); // return value of the method is streamed data _Command.Parameters.Add(_TVParam); try { _Connection.Open(); _Command.ExecuteNonQuery(); } finally { _Connection.Close(); } return; } 

अतिरिक्त नोट्स:

  1. कुछ संशोधनों के साथ, उपरोक्त सी # कोड को डेटा में बैच करने के लिए अनुकूलित किया जा सकता है।
  2. मामूली संशोधन के साथ, उपरोक्त सी # कोड को कई क्षेत्रों में भेजने के लिए अनुकूलित किया जा सकता है (उदाहरण के लिए "स्टीमिंग डेटा …" में दिखाया गया है कि लेख 2 क्षेत्रों में उपरोक्त लिंक से संबंधित है)।
  3. आप SELECT में SELECT कथन में प्रत्येक रिकॉर्ड के मूल्य को भी हेरफेर कर सकते हैं।
  4. आप proc में एक WHERE शर्त का उपयोग करके पंक्तियों को भी फ़िल्टर कर सकते हैं।
  5. आप कई बार टीवीपी टैबिल वैरिएबल एक्सेस कर सकते हैं; यह वाकई है लेकिन "केवल आगे" नहीं है
  6. SqlBulkCopy पर फायदे:
    1. SqlBulkCopy केवल INSERT है, जबकि एक TVP का उपयोग करते हुए किसी भी तरह से डेटा का उपयोग किया जा सकता है: आप MERGE को कॉल कर सकते हैं; आप कुछ शर्त पर आधारित DELETE सकते हैं; आप डेटा को कई तालिकाओं में विभाजित कर सकते हैं; और इसी तरह।
    2. किसी टीवीप को केवल INSERT न होने के कारण, आपको डेटा को डंप करने के लिए अलग स्टेजिंग तालिका की आवश्यकता नहीं है
    3. ExecuteNonQuery बजाय ExecuteReader को कॉल करके आप डेटाबेस से डेटा को वापस प्राप्त कर सकते हैं। उदाहरण के लिए, यदि DATAs आयात तालिका में एक IDENTITY फ़ील्ड है, तो आप INSERT को वापस INSERT एक OUTPUT क्लॉज जोड़ सकते हैं INSERTED.[ID] (मानते हुए ID IDENTITY फ़ील्ड का नाम है)। या फिर आप एक पूरी तरह से अलग क्वेरी के परिणामों को वापस पास कर सकते हैं, या दोनों के बाद से कई परिणाम सेट भेजे जा सकते हैं और Reader.NextResult() माध्यम से पहुंचा जा सकता है। SqlBulkCopy का उपयोग करते समय डेटाबेस से वापस जानकारी प्राप्त करना संभव नहीं है, फिर भी यहां बहुत सारे प्रश्न हैं जो वास्तव में ऐसा करना चाहते हैं (कम से कम नए बनाए गए IDENTITY मूल्यों के संबंध में)।
    4. संपूर्ण प्रक्रिया के लिए कभी-कभी तेज़ तेज़ी के लिए, यहां तक ​​कि अगर डिस्क से SQL सर्वर में डेटा प्राप्त करने में थोड़ा धीमा हो, तो कृपया इस श्वेत पत्र को SQL सर्वर ग्राहक सलाहकार टीम से देखें: TVP के साथ अधिकतम इनपुट

सी # में, सबसे अच्छा समाधान है कि SqlBulkCopy फ़ाइल पढ़ता है। ऐसा करने के लिए आपको SqlBulkCopy.WriteToServer विधि से प्रत्यक्ष IDataReader पास करना होगा। यहां एक उदाहरण है: http://www.codeproject.com/Articles/228332/IDataReader-implementation-plus-SqlBulkCopy

सबसे अच्छा तरीका यह है कि आपका पहला समाधान और 2 के बीच एक मिश्रण है, DataTable बनाएं और लूप में इसके लिए पंक्तियां जोड़ें फिर एक कनेक्शन में डीबी में अपलोड करने के लिए BulkCopy का उपयोग करें, बल्क प्रतिलिपि में सहायता के लिए इसका उपयोग करें

ध्यान देने के लिए एक अन्य बात यह है कि थोक प्रति एक बहुत ही संवेदनशील ऑपरेशन है कि लगभग हर गलती प्रतिलिपि को रद्द कर देगी, जैसे कि आप डेटाटैबल में "टेक्स्ट" के रूप में कॉलम नाम को घोषित करते हैं और डीबी में "पाठ" में यह एक अपवाद फेंकता है , सौभाग्य।