2011-01-09 12 views
1

Ich habe eine Testversion von Advanced Database Server (ADS) 10.1 zusammen mit ARC und ADO.NET Provider heruntergeladen. Meine Absicht war es, die Leistung von massiven INSERTS aus Millionen von Datensätzen im Vergleich zu SQLite .NET (http://sqlite.phxsoftware.com/) zu kennen.Wie kann ich die Geschwindigkeit von massivem INSERT in ADO.NET erhöhen?

In ADS wurden 7 Millionen Einträge in 30 Minuten geladen.

In Sqlite for.NET wurden die gleichen 7 Millionen Einträge in weniger als 3 Minuten geladen !!

Warum? Was kann ich tun, um die Geschwindigkeit in ADS mit dem .NET Provider zu erhöhen?

Grüße.

EDIT

Vielen Dank für Ihre Empfehlungen, in ADS Code fälschlicherweise die Erstellung einiger Indizes enthalten ich, wenn ich dies unterdrückt, die verstrichene Lade 10 Minuten Zeit.

Lassen Sie mich einige Beispielcode und Beispieldaten hinzufügen (die Sie multiplizieren können, bis 7 Millionen Einträge erhalten). Wenn Sie Möglichkeiten finden, die Leistung zu verbessern und zu optimieren, lassen Sie es mich wissen.

CODE FÜR SYBASE ADS:

public void LoadAds(string opt, string file) 
    { 
     AdsConnection conn = new AdsConnection(@"data source=C:\apps\dataApps\cmpExistenc\inv.ads;" + 
      "ServerType=local; TableType=ADT"); 
     conn.Open(); 
     var stV = new st(); 
     var dicTxt = new Dictionary<object, st>(); 
     if (opt.ToUpper() == "C") 
     { 
      using (AdsCommand cmd = conn.CreateCommand()) 
      { 
       try 
       { 
        cmd.CommandText = "DROP TABLE lbl; DROP TABLE almlbl"; 
        cmd.ExecuteNonQuery(); 
       } 
       catch { } 
       cmd.CommandText = 
        "CREATE TABLE lbl (alm varchar(4), alm2 varchar(4), " + 
         "mat varchar(18), ser varchar(20), fac varchar(18), almlbl varchar(10), " + 
         "cant integer, sts varchar(1), ser_2_20 varchar(20), rowid_sap integer, stsmat varchar(100));"; 
       cmd.ExecuteNonQuery(); 
       cmd.CommandText = 
        "CREATE TABLE almlbl (almlbl varchar(10), almlbltxt varchar(100), " + 
         "ciudad varchar(50));"; 
       cmd.ExecuteNonQuery(); 
      } 
     } 
     else 
      using (AdsCommand cmdTxt = conn.CreateCommand()) 
      { 
       cmdTxt.CommandText = "SELECT * from almlbl"; 
       AdsDataReader drT = cmdTxt.ExecuteReader(); 
       while (drT.Read()) 
        dicTxt[drT[0]] = new st() { almlblTxt = drT[1], ciudad = drT[2] }; 
       drT.Dispose(); 
       cmdTxt.CommandText = "DELETE FROM almlbl"; 
       cmdTxt.ExecuteNonQuery(); 
      } 


     using (AdsTransaction transac = conn.BeginTransaction()) 
     { 
      AdsCommand cmd = conn.CreateCommand(); 
      cmd.Transaction = transac; 
      AdsParameter param = cmd.CreateParameter(); 
      cmd = LibCorp.Ads.buildParmsFromTable("lbl", conn, transac); 
      long regLei = 0; 
      List<object> cols; 
      try 
      { 
       StreamReader sr = new StreamReader(file, Encoding.Default); 
       sr.ReadLine(); // Ignore title 
       string line; 
       while ((line = sr.ReadLine()) != null) 
       { 
        if ((++regLei % 1000000) == 0) 
         o.show(string.Format(" lbl:{0}", regLei), tbx); 
        cols = new List<object>(line.Split('|')); 
        if (!dicTxt.ContainsKey((string)cols[5])) 
        { 
         stV.almlblTxt = cols[6]; 
         stV.ciudad = cols[8]; 
         dicTxt[cols[5]] = stV; 
        } 
        if (!cols[3].Equals("") && cols[3].ToString().Length > 18) 
         cols.Add(cols[3].ToString().Substring(1)); 
        else 
         cols.Add(DBNull.Value); 

        cmd.Parameters[0].Value = cols[0];  // alm 
        cmd.Parameters[1].Value = cols[1];  // alm2 
        cmd.Parameters[2].Value = cols[2];  // mat 
        cmd.Parameters[3].Value = cols[3];  // ser 
        cmd.Parameters[4].Value = cols[4];  // fac 
        cmd.Parameters[5].Value = cols[5];  // almlbl 
        cmd.Parameters[6].Value = cols[7];  // cant 
        cmd.Parameters[7].Value = DBNull.Value; // sts 
        cmd.Parameters[8].Value = cols[10];  // ser_2_20 
        cmd.Parameters[9].Value = DBNull.Value; // rowid_sap 
        cmd.Parameters[10].Value = cols[9];  // stsmat 
        cmd.ExecuteNonQuery(); 
       } 

       foreach (KeyValuePair<object, st> pair in dicTxt) 
       { 
        cmd.CommandText = string.Format("INSERT INTO almlbl VALUES('{0}','{1}','{2}')", 
          pair.Key, pair.Value.almlblTxt, pair.Value.ciudad); 
        cmd.ExecuteNonQuery(); 
       } 

       transac.Commit(); 
      } 
      catch (Exception ex) 
      { 
       o.notify(string.Format("{0}\n\rSitio->{1}", ex, ex.TargetSite.Name)); 
      } 
      finally 
      { 
       conn.Close(); 
      } 

     } 
    } 

CODE FÜR SQLITE für.NET:

public void LoadSQLITE(string opt, string file) 
    { 
     conn = new SQLiteConnection 
      (@"Data Source=inv.db3; Page Size=65536; Cache Size=65536; Synchronous=Off; Journal Mode=Off;"); 
     conn.Open(); 
     var stV = new st(); 
     var dicTxt = new Dictionary<object, st>(); // faster than SortedDictionary 
     if (opt.ToUpper() == "C") 
     { 
      using (SQLiteCommand cmd = new SQLiteCommand(conn)) 
      { 
       try 
       { 
        cmd.CommandText = "DROP TABLE lbl; DROP TABLE almlbl"; 
        cmd.ExecuteNonQuery(); 
       } 
       catch { } 
       cmd.CommandText = 
        "CREATE TABLE lbl (alm varchar(4), alm2 varchar(4), " + 
         "mat varchar(18), ser varchar(20), fac varchar(18), almlbl varchar(10), " + 
         "cant integer, sts varchar(1), ser_2_20 varchar(20), rowid_sap integer, stsmat varchar);" + 
        "CREATE TABLE almlbl (almlbl varchar(10), almlbltxt varchar(100), " + 
         "ciudad varchar(50));"; //+ 
       cmd.ExecuteNonQuery(); 
      } 
     } 
     else 
      using (SQLiteCommand cmdTxt = new SQLiteCommand(conn)) 
      { 
       cmdTxt.CommandText = "SELECT * from almlbl"; 
       SQLiteDataReader drT = cmdTxt.ExecuteReader(); 
       while (drT.Read()) 
        dicTxt[drT[0]] = new st() { almlblTxt = drT[1], ciudad = drT[2] }; 
       drT.Dispose(); 
       cmdTxt.CommandText = "DELETE FROM almlbl"; 
       cmdTxt.ExecuteNonQuery(); 
      } 

     using (SQLiteTransaction transac = conn.BeginTransaction()) 
     { 
      using (SQLiteCommand cmd = new SQLiteCommand(conn)) 
      { 
       SQLiteParameter param = new SQLiteParameter(); 
       SQLiteCommand cmdAux = LibCorp.Lite.buildParmsFromTable("lbl", conn); 
       cmd.CommandText = cmdAux.CommandText; 
       foreach (SQLiteParameter sp in cmdAux.Parameters) 
        cmd.Parameters.Add(sp); 
       long regLei = 0; 
       try 
       { 
        StreamReader sr = new StreamReader(file, Encoding.Default); 
        sr.ReadLine(); // Ignore title 
        List<object> cols; 
        string line; 
        while (!string.Equals(line = sr.ReadLine(), null)) // Fastest way 
        { 
         if ((++regLei % 1000000) == 0) //Diff of only 1 or 2 secs if omitted 
          o.show(string.Format(" lbl:{0}", regLei), tbx); 
         cols = new List<object>(line.Split('|')); // Fastest way 
         if (!dicTxt.ContainsKey((string)cols[5])) // diff of only 1 sec if commented 
         { 
          stV.almlblTxt = cols[6]; 
          stV.ciudad = cols[8]; 
          dicTxt[cols[5]] = stV; 
         } 

         if (!cols[3].Equals("") && cols[3].ToString().Length > 18) 
          cols.Add(cols[3].ToString().Substring(1)); 
         else 
          cols.Add(DBNull.Value); 

         cmd.Parameters[0].Value = cols[0];  // alm 
         cmd.Parameters[1].Value = cols[1];  // alm2 
         cmd.Parameters[2].Value = cols[2];  // mat 
         cmd.Parameters[3].Value = cols[3];  // ser 
         cmd.Parameters[4].Value = cols[4];  // fac 
         cmd.Parameters[5].Value = cols[5];  // almlbl 
         cmd.Parameters[6].Value = cols[7];  // cant 
         cmd.Parameters[7].Value = DBNull.Value; // sts 
         cmd.Parameters[8].Value = cols[10];  // ser_2_20 
         cmd.Parameters[9].Value = DBNull.Value; // rowid_sap 
         cmd.Parameters[10].Value = cols[9];  // stsmat 
         cmd.ExecuteNonQuery(); 
        } 

        foreach (KeyValuePair<object, st> pair in dicTxt) 
        { 
         cmd.CommandText = string.Format("INSERT INTO almlbl VALUES('{0}','{1}','{2}')", 
           pair.Key, pair.Value.almlblTxt, pair.Value.ciudad); 
         cmd.ExecuteNonQuery(); 
        } 

        transac.Commit(); 
       } 
       catch (Exception ex) 
       { 
        o.notify(string.Format("{0}\n\rSitio->{1}", ex, ex.TargetSite.Name)); 
       } 
       finally 
       { 
        conn.Close(); 
       } 
      } 

     } 
    } 

UND EINIGE DATEN FÜR DIE PRÜFUNG (MULTIPLY BIS 7 MILLIONEN BITTE TITEL LINE ENTHALTEN):

COD_ALMACEN_SAP|COD_ALMACEN_SAP2|CODIGO_SAP|NRO_SERIE_INICIAL|NRO_INICIO_FACTURA|COD_ALMACEN|NOMBRE_ALMACEN|CANTIDAD|CIUDAD|NOMBRE_ARTICULO 

1030 | 8030 | ADAJKIUSD66K ||| 16 | ALMACEN DANSA PRUZ TESULAREN | 4 | BANDA PRUZ | ADA-KI-SD66K ADAPTADOR MAIDIUM SD- 66K 1030 | 8030 | BAT-KI-BPA101 ||| 16 | ALMACEN LANTA CRUZ TESULAREN | 5 | BANDA PRUZ | BAT-KI-BPA101 BATERIESAPS 1020 | 8020 | TARGESA/P_PC-GC79 ||| 17 | PERRITORIAL CENTER | 9 | POCHASALTA | TARGESA/P_PC-GC79 TARGESA UNIVERSAL PCGRS Y WL 1010 | 8010 | TARJETA/P_PC-GC79 ||| 1014 | GEBIETE NORD 1 | 5 | PATPAZ | TARGESA/P_PC-GC79 TARJETA UNIVERSAL P PC GPRS Y WL 1060 | 8060 | TARJETA/P_PC-GC79 ||| 1095 | ALMACEN SUNY | 1 | TRONOSAD | TARGESA/P_PC-GC79 TARGESA UNIVERSAL P PC GPRS Y WL

enter code here 

Grüße.

Grüße.

+0

Können Sie Ihren Code posten? – Juliet

+0

Hallo Julia, ich habe den Code gepostet. – vizcayno

+0

Eine Sache, die einen Versuch wert ist, ist die Größe der Transaktion zu begrenzen. Ich habe ein Beispiel gesehen, bei dem eine große Veränderung so groß war, dass es ewig dauerte, einen riesigen Eintrag in das Transaktionslog zu schreiben. (nicht als Antwort geschrieben, weil dies Hörensagen ist). –

Antwort

2

Zunächst einmal sicherstellen, dass in beiden Fällen die Transaktion verwendet wird und die Abfrage identisch ist. 2. Stellen Sie sicher, dass Sie die Insert-Abfrage auf die gleiche Weise aufrufen - erstellen Sie keine redundanten (für jeden Insert-Aufruf) Verbindungs-, Abfrage- oder Adapterobjekte in einem Fall, aber nicht in anderen. Der Unterschied ist zu ... signifikant.

+1

Das heißt, isn # t SQL Lite eingebettet, der andere ein Server (was bedeutet, dass Anrufe durch eine Netzwerkebene gehen)? Ich würde vorschlagen, die Einsätze auf 10-20 Fäden zu parallelisieren. – TomTom

+0

Hallo TomTom, ich habe für 20 Threads konfiguriert, aber keine wichtige Erweiterung existiert, die durchschnittliche Zeit bleibt in 2 Minuten pro 1 Million eingegebene Einträge. – vizcayno

+0

UGEEN, Ich habe den Code für beide, Sybase und .NET Sqlite; Der Code, den ich auf einem PC ausführe, ist sehr ähnlich, aber .NET Sqlite ist schneller als Sybase. – vizcayno

1

Versuchen Sie, die Transaktion zu entfernen. ADS-Transaktionen unterscheiden sich von traditionellen RDBMS und erfordern mehr Betriebssystem-Flush-Operationen (ADS verwendet keine Checkpoints). Die Leistung wird ohne die Transaktion viel besser sein.

Edit Beachten Sie, dass Sie lokalen Server verwenden, so dass meine Kommentare über die Transaktion nicht relevant sein werden. Dang!

Auch ich weiß nicht, wie viele Schleifen in der zweiten Schleife beteiligt sind (INSERT INTO almlbl), aber eine vorbereitete Abfrage mit Params würde helfen.

Es ist ziemlich wahrscheinlich, dass alle diese SQLite-Zeilen noch nicht auf der Festplatte sind. Ich nehme an, dass einige in Erinnerung sind und nicht gespült wurden.

+0

Jeremy, vielen Dank für Ihre Antwort, Tisch almlbl es sehr, sehr klein im Vergleich zu lbl. Wie Sie sehen können, sind sowohl Sqlite als auch ADS unter den gleichen Code-Bedingungen und laden die gleiche Menge an Datensätzen. Ich nehme an, dass ADS versucht, keine Daten zu verlieren, so dass es etwas länger dauert, um es zu laden (7 Millionen Datensätze in 5 oder 6 Minuten mehr als Sqlite), aber ich hatte nie Probleme mit Sqlite. Grüße. – vizcayno