MultiThreading mit SQL Server WOW!!!

  • C#
  • .NET 4.0

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von KBT.

    MultiThreading mit SQL Server WOW!!!

    Hallo Liebe Gemeinde,

    Erstmal Danke an alle hier im Forum, Ihr seid einfach Super und sehr geduldig :-).

    Nun zu meinen Erfolgen sowie auch einem Problem, was ich nicht lösen kann bzw. nicht weiß wie ich das verhindern ändern kann.

    Erfolge:
    Habe es heute endlich geschafft meinen SQL-Test im Multithreading abzuschließen und bin begeistert.
    konnte mit 20 Threads in meine Lokale SQL-Devoloper Datenbank schreiben.
    Test war 1000000 Datensätze simultan in die Tabelle zu schreiben.
    Das funktioniert wunderbar hat nur 86 sek. gedauert. Für lokal und für einen Test supi.

    Problem:
    Jedoch mache ich beim erstellen der Tabelle noch was Falsch. Und zwar zeigt er mir einen Indexierungsfehler bei diesem Schlüssel an(Bild Anhang). Dieser Schlüssel wird automatisch vom System erstellt und ich musste Ihn löschen damit es Problemlos funktioniert. Nur gehe ich mal davon aus das es einen besseren weg gibt ohne den Schlüssel zu löschen. Hier mal der Code mit dem ich die Tabelle erstelle.

    C#-Quellcode

    1. public void CreateNewRealTimeTable(string _TableName)
    2. {
    3. SqlConnection con = new SqlConnection
    4. {
    5. ConnectionString = "Data Source= ***********\\TZCADSQLSERVER;" +
    6. "Initial Catalog = RealTimeDatabase;" +
    7. "Integrated Security= True;"
    8. };
    9. con.Open();
    10. _TableName = "CREATE TABLE " + _TableName;
    11. _TableName = _TableName + "(InstrumentID int NOT NULL PRIMARY KEY,";
    12. _TableName = _TableName + "Instrument NCHAR(6) NULL,";
    13. _TableName = _TableName + "Time datetime NULL,";
    14. _TableName = _TableName + "Bid NUMERIC(18, 7) NULL,";
    15. _TableName = _TableName + "Ask NUMERIC(18, 7) NULL,";
    16. _TableName = _TableName + "High NUMERIC(18, 7) NULL,";
    17. _TableName = _TableName + "Low NUMERIC(18, 7) NULL,";
    18. _TableName = _TableName + "PipCost NUMERIC(18, 7) NULL);";
    19. using (SqlCommand cmd = new SqlCommand(_TableName, con))
    20. {
    21. cmd.ExecuteNonQuery();
    22. }
    23. }


    Gruß
    Bilder
    • PK_Schlüssel.PNG

      11 kB, 309×242, 10 mal angesehen
    Habe das Problem gelöst ohne den Schlüssel löschen zu müssen. Das problem lag beim erstellen der Threads. eine kleine sleep Schleife hat das Problem gelöst.

    C#-Quellcode

    1. private void StartThreads(object source, EventArgs args)
    2. {
    3. int anzahlthreads = 30;
    4. for (int i = 0; i <= anzahlthreads - 1; i ++)
    5. {
    6. int _ThreadNr = i + 1;
    7. String _Threadname;
    8. _Threadname = "Thread_" + _ThreadNr.ToString();
    9. System.Threading.Thread thread = new System.Threading.Thread(delegate () { Addrows2(i, 1000000, anzahlthreads, _Threadname); });
    10. thread.Start();
    11. System.Threading.Thread.Sleep(10);
    12. }
    13. _endtime = System.DateTime.Now;
    14. }


    ohne die sleep anweisung, haben manchmal 2 Threads den selben Index erstellt. warum, kann ich leider nicht sagen. aber jetzt funktioniert es.

    In der praxis werde ich bei meinem System, niemals gleichzeitig soviele Threads brauchen, es ist halt nur ein Test um zu sehen was möglich ist.
    Da du ja nix über den Schlüssel geschrieben hast kann ich nur vermuten das dieser anhand eines Timestamps generiert wird. Und wenn 2 Verbindungen mal zufällig zur Gleichen Zeit inserten dann kann es je nach Genauigkeit des Timestamps vermutlich mal zu gleichen Werten kommen.

    Probier mal mit deiner Tabelle folgendes
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Shared Sub Main(ByVal args As String())
    2. Console.WriteLine("Enter the table name to insert:")
    3. Dim _TableName = Console.ReadLine()
    4. Dim sw = New Stopwatch()
    5. sw.Start()
    6. Dim sql = New SqlConnection("YourConnectionstring")
    7. sql.Open()
    8. Console.WriteLine("Connected: " & sw.Elapsed)
    9. Dim _sql = "CREATE TABLE " & _TableName
    10. _sql = _sql & "(InstrumentID int NOT NULL PRIMARY KEY,"
    11. _sql = _sql & "Instrument NCHAR(6) NULL,"
    12. _sql = _sql & "[Time] datetime NULL,"
    13. _sql = _sql & "Bid NUMERIC(18, 7) NULL,"
    14. _sql = _sql & "Ask NUMERIC(18, 7) NULL,"
    15. _sql = _sql & "High NUMERIC(18, 7) NULL,"
    16. _sql = _sql & "Low NUMERIC(18, 7) NULL,"
    17. _sql = _sql & "PipCost NUMERIC(18, 7) NULL);"
    18. Using cmd = New SqlCommand(_sql, sql)
    19. cmd.ExecuteNonQuery()
    20. End Using
    21. Console.WriteLine("Table created: " & sw.Elapsed)
    22. Dim dt = New DataTable()
    23. dt.Columns.Add("InstrumentID")
    24. dt.Columns.Add("Instrument")
    25. dt.Columns.Add("Time")
    26. dt.Columns.Add("Bid")
    27. dt.Columns.Add("Ask")
    28. dt.Columns.Add("High")
    29. dt.Columns.Add("Low")
    30. dt.Columns.Add("PipCost")
    31. Dim bulk = New SqlBulkCopy(sql) With {.DestinationTableName = _TableName, .BatchSize = 10000}
    32. For i = 0 To 1000000 - 1
    33. Dim row = dt.NewRow()
    34. row("Instrument") = "abcede"
    35. row("Time") = DateTime.Now
    36. row("InstrumentID") = i
    37. row("Bid") = i
    38. row("Ask") = i
    39. row("High") = i
    40. row("Low") = i
    41. row("PipCost") = i
    42. dt.Rows.Add(row)
    43. Next
    44. Console.WriteLine("In Memory: " & sw.Elapsed)
    45. bulk.WriteToServer(dt)
    46. sw.[Stop]()
    47. Console.WriteLine("In database: " & sw.Elapsed)
    48. Console.Read()
    49. End Sub


    Dauert bei mir 40 Sekunden mit allem und ist völlig ohne Threading. Würde mich mal interessieren wie das im Vgl dazu abschneidet von der Performance.

    LG
    Das ist meine Signatur und sie wird wunderbar sein!

    Neu

    Mir ist noch nicht klar warum Threading irgendeinen Einfluss auf nen Datenbank-Server haben soll. Die Dinger sind ja dafür gemacht viele Kanäle offen zu halten zu diversen Usern. Was mir bei dem Code den man sieht nicht klar wird ist, ob jeder Thread einen eigenen Kanal öffnet oder alle über einen funken. Ich würde sogar soweit gehen zu behaupten, dass das Codeseitige erstellen der Datensätze länger dauert als das schreiben der Datensätze auf die Datenbank. Die Performance ist natürlich in deinem Fall weiterhin davon abhängig, dass beides über den selben Rechner läuft. Ich vermute mal du hast keine 20 Kerne, wie der kleinere Server den ich gerade betreue ;D