2010-04-22 11 views
5

मैं सी # के माध्यम से थोक डेटा लोड करने का सबसे तेज़ तरीका ढूंढ रहा हूं। मेरे पास यह स्क्रिप्ट है जो नौकरी करता है लेकिन धीमा है। मैंने साक्ष्य पढ़ा है कि एसकब्लूल्ककॉपी सबसे तेज़ है।
1000 रिकॉर्ड 2.5 सेकंड। फ़ाइलों में 250000 पर 5000 रिकॉर्ड्स के करीब कहीं भी शामिल है जो कुछ चीजें हैं जो इसे धीमा कर सकती हैं?SqlBulkCopy गुड़ के रूप में धीमी

टेबल डेफ:

CREATE TABLE [dbo].[tempDispositions](
    [QuotaGroup] [varchar](100) NULL, 
    [Country] [varchar](50) NULL, 
    [ServiceGroup] [varchar](50) NULL, 
    [Language] [varchar](50) NULL, 
    [ContactChannel] [varchar](10) NULL, 
    [TrackingID] [varchar](20) NULL, 
    [CaseClosedDate] [varchar](25) NULL, 
    [MSFTRep] [varchar](50) NULL, 
    [CustEmail] [varchar](100) NULL, 
    [CustPhone] [varchar](100) NULL, 
    [CustomerName] [nvarchar](100) NULL, 
    [ProductFamily] [varchar](35) NULL, 
    [ProductSubType] [varchar](255) NULL, 
    [CandidateReceivedDate] [varchar](25) NULL, 
    [SurveyMode] [varchar](1) NULL, 
    [SurveyWaveStartDate] [varchar](25) NULL, 
    [SurveyInvitationDate] [varchar](25) NULL, 
    [SurveyReminderDate] [varchar](25) NULL, 
    [SurveyCompleteDate] [varchar](25) NULL, 
    [OptOutDate] [varchar](25) NULL, 
    [SurveyWaveEndDate] [varchar](25) NULL, 
    [DispositionCode] [varchar](5) NULL, 
    [SurveyName] [varchar](20) NULL, 
    [SurveyVendor] [varchar](20) NULL, 
    [BusinessUnitName] [varchar](25) NULL, 
    [UploadId] [int] NULL, 
    [LineNumber] [int] NULL, 
    [BusinessUnitSubgroup] [varchar](25) NULL, 
    [FileDate] [datetime] NULL 
) ON [PRIMARY] 

और यहाँ, कोड

private void BulkLoadContent(DataTable dt) 
    { 
     OnMessage("Bulk loading records to temp table"); 
     OnSubMessage("Bulk Load Started"); 
     using (SqlBulkCopy bcp = new SqlBulkCopy(conn)) 
     { 
      bcp.DestinationTableName = "dbo.tempDispositions"; 
      bcp.BulkCopyTimeout = 0; 
      foreach (DataColumn dc in dt.Columns) 
      { 
       bcp.ColumnMappings.Add(dc.ColumnName, dc.ColumnName); 
      } 
      bcp.NotifyAfter = 2000; 
      bcp.SqlRowsCopied += new SqlRowsCopiedEventHandler(bcp_SqlRowsCopied); 
      bcp.WriteToServer(dt); 
      bcp.Close(); 
     } 
    } 
+1

क्या तुलना में धीमी है? कितने रिकॉर्ड? आपने किस अन्य दृष्टिकोण की कोशिश की है? क्या यह "धीमी" है जैसे "जी, मैं बेहतर कुछ कॉफी लेता हूं" या जैसा कि "मैं इसे हाथ से तेज़ी से टाइप कर सकता हूं"? – GalacticCowboy

+0

"मैं बेहतर कुछ कॉफी पकड़ो" 1000 रिकॉर्ड 2.5 सेकंड के रूप में धीमा। फ़ाइलों में 250k –

+0

पर 5000 रिकॉर्ड्स के पास कहीं भी शामिल है क्या आपके डीबी में 'लोड डेटा इन्फाइल' फ़ंक्शन है और क्या आप इसे सीधे कॉल कर सकते हैं? – dnagirl

उत्तर

7

आप किसी भी अनुक्रमित है है चलाता है या कि मेज पर बाधाओं?

इससे मंदी पर मंदी का कारण बन जाएगा - विशेष रूप से क्लस्टर्ड इंडेक्स को चोट पहुंच जाएगी। जब आप डेटा की मात्रा को विस्फोट करते हैं, तो पहले इंडेक्स को छोड़ना सबसे अच्छा होता है, और बाद में उन्हें फिर से लागू करना सर्वोत्तम होता है।

इसके बारे में एक अच्छा पोस्ट यहाँ है: What's the fastest way to bulk insert a lot of data in SQL Server (C# client)

1

चीज़ें है कि नीचे थोक प्रतिलिपि धीमा कर सकते हैं: तालिका प्रविष्ट पर -Triggers पर पूर्ण पाठ अनुक्रमणिका -Foreign कुंजी बाधाओं

3

आप डेटा के बहुत सारे है, तो एक यथोचित बड़ी संख्या के लिए batchsize स्थापित करने में मदद कर सकता है:

bcp.BatchSize = 10000; 
0

IDataReader कार्यान्वयन मैं सुझाव यहां अनुमान लगाया गया है How to implement IDataReader? शायद आपकी मदद करता है। मैं SqlBulkCopy के साथ यह प्रयोग किया जाता इस प्रकार है:

using (MyFileDataReader reader = new MyFileDataReader(@"C:\myfile.txt")) 
{ 
     SqlBulkCopy bulkCopy = new SqlBulkCopy(connection); 
     bulkCopy.DestinationTableName = "[my_table]"; 
     bulkCopy.BatchSize = 10000; 

     bulkCopy.WriteToServer(reader); 

     bulkCopy.Close(); 

} 
1

मैंने देखा है कि शुरू में बहुत तेजी से है बड़े डेटासेट फ्लश करने के लिए कोशिश कर रहा है, लेकिन समय के साथ नीचे काफी धीमा कर देती है। मुझे एक बफर किए गए दृष्टिकोण का उपयोग करके प्रदर्शन में मामूली वृद्धि मिली है, उसी कनेक्शन के तहत एक समय में बल्ककोपी को केवल कुछ हज़ार रिकॉर्ड खिला रहे हैं। ऐसा लगता है कि प्रति बैच लेनदेन समय समय के साथ नीचे रहता है, जो (समय के साथ), प्रदर्शन में सुधार करता है। मेरे समाधान पर, मैंने ध्यान दिया है कि एक ही विधि un-buffered उसी विधि के लगभग 7,500,000 रिकॉर्ड्स को उसी डीबी में सहेजने के लिए इस विधि को लेकर 5,000,000 रिकॉर्ड सहेज लेगा। उम्मीद है कि यह किसी की मदद करेगा।

public void flush_DataTable(DataTable dt, string tableName)//my incoming DTs have a million or so each and slow down over time to nothing. This helps. 
    { int bufferSize = 10000; 
     int bufferHigh = bufferSize; 
     int lowBuffer = 0; 
     if (dt.Rows.Count >= bufferSize) 
     { using (SqlConnection conn = getConn()) 
      { conn.Open(); 
       while (bufferHigh < dt.Rows.Count) 
       { 
        using (SqlBulkCopy s = new SqlBulkCopy(conn)) 
        { s.BulkCopyTimeout = 900; 
         s.DestinationTableName = tableName; 
         s.BatchSize = bufferSize; 

         s.EnableStreaming = true; 
         foreach (var column in dt.Columns) 
          s.ColumnMappings.Add(column.ToString(), column.ToString()); 
         DataTable bufferedTable = dt.Clone(); 
         for (int bu = lowBuffer; bu < bufferHigh; bu++) 
         { 
          bufferedTable.ImportRow(dt.Rows[bu]); 
         } 
         s.WriteToServer(bufferedTable); 
         if (bufferHigh == dt.Rows.Count) 
         { 
          break; 
         } 
         lowBuffer = bufferHigh; 
         bufferHigh += bufferSize; 

         if (bufferHigh > dt.Rows.Count) 
         { 
          bufferHigh = dt.Rows.Count; 
         } 
        } 
       } 
       conn.Close(); 
      } 
     } 
     else 
     { 
      flushDataTable(dt, tableName);//perofrm a non-buffered flush (could just as easily flush the buffer here bu I already had the other method 
     } 
    } 
+0

आप शायद समानांतर का उपयोग करके चीजों को गति दे सकते हैं। तालिका की प्रतिलिपि बनाने के लिए और/या थ्रेडिंग का लाभ लेते हुए प्रतीक्षा करने के लिए 2-3 समानांतर आवेषणों का उपयोग करके प्रतीक्षा करें। RiteToServerAsync। आप प्रयोग (लों) के अंदर लूप लॉजिक (WHILE) डालने का प्रयास कर सकते हैं और कॉलम मैपिंग के बाद भी यह सब SQLBulkCopy के उसी उदाहरण के तहत होता है - मैं समय के साथ प्रदर्शन में 50% की वृद्धि के साथ पर्याप्त खुश था, कुछ कोशिश करने के लिए नहीं इन अन्य चालों में से। वाईएमएमवी –

+1

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

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