Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

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

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

आपका सर्वश्रेष्ठ दांव (BCP . के बाहर / BULK INSERT / OPENROWSET(BULK...) ) फ़ाइल से सामग्री को तालिका-मूल्यवान पैरामीटर (TVP) के माध्यम से डेटाबेस में स्ट्रीम करना है। एक टीवीपी का उपयोग करके आप फ़ाइल खोल सकते हैं, एक पंक्ति पढ़ सकते हैं और एक पंक्ति को तब तक भेज सकते हैं जब तक कि यह पूरा न हो जाए और फिर फ़ाइल को बंद कर दें। इस पद्धति में केवल एक पंक्ति का मेमोरी फ़ुटप्रिंट है। मैंने एक लेख लिखा था, एक अनुप्रयोग से SQL सर्वर 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 ऑब्जेक्ट का उपयोग करने के लिए C# ऐप कोड नीचे है। ध्यान दें कि किसी ऑब्जेक्ट (जैसे डेटाटेबल) को भरने और फिर संग्रहीत प्रक्रिया को निष्पादित करने के बजाय, यह संग्रहीत प्रक्रिया का निष्पादन है जो फ़ाइल सामग्री को पढ़ने की शुरुआत करता है। संग्रहित प्रक्रिया का इनपुट पैरामीटर एक चर नहीं है; यह एक विधि का वापसी मूल्य है, GetFileContents . उस विधि को तब कहा जाता है जब SqlCommand कॉल ExecuteNonQuery , जो फ़ाइल खोलता है, एक पंक्ति पढ़ता है और पंक्ति को SQL सर्वर को IEnumerable<SqlDataRecord> के माध्यम से भेजता है और yield return बनाता है, और फिर फ़ाइल को बंद कर देता है। संग्रहीत प्रक्रिया केवल एक तालिका चर, @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 उपरोक्त विधि का उपयोग नीचे दिखाए गए अनुसार संग्रहीत प्रक्रिया के लिए इनपुट पैरामीटर मान के रूप में किया जाता है:

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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL सर्वर - SQL सर्वर / TSQL ट्यूटोरियल पार्ट 111 में सेलेक्ट स्टेटमेंट में अज्ञात के साथ नल मानों को कैसे बदलें?

  2. SQL सर्वर (T-SQL) में किसी दिनांक से ISO सप्ताह संख्या लौटाएँ

  3. स्पॉटलाइट क्लाउड बेसिक:बेस्ट फ्री डेटाबेस परफॉर्मेंस मॉनिटरिंग टूल

  4. तालिका के केवल एक कॉलम के आधार पर डुप्लिकेट मानों को हटाना

  5. SQL सर्वर में चेक बाधा को सक्षम करते समय आपको NOCHECK के बारे में क्या पता होना चाहिए