none
Performance RRS feed

  • Frage

  • Guten Tag,

    ich habe da zwei drei Fragen zu Performance und SQL.
    In einer Testumgebung, VB.Net 2010, lese ich über einen Reader eine Textdatei mit 183 MB und ca. 27Mio Datensätzen
    ein.
    Das reine Einlesen benötigt ca. 6 Sekunden und die Verarbeitung dann um die 20 Sekunden.
    Jetzt die Frage, geht das mit einer SQL Datenbank schneller?

    Hier mal etwas Code. Kann man da noch etwas verbessern?

       Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    
            Try
    
                Dim Start As Date = System.DateTime.Now
                Dim Datei As String = "test.txt"
                Dim tx As New IO.StreamReader("d:\Marktdaten\" & Datei)
    
                Do
                    line = tx.ReadLine()
                    If IsNothing(line) Then Exit Do
                    feDaten1(x) = line : c_Markt.Schwankung(feDaten1(x)) : Einlesen(x) : x += 1
    
                Loop
    
                Testzeit = System.DateTime.Now.Subtract(Start).TotalMilliseconds / 1000
                Timer1.Start()
    
            Catch ex As Exception
               
            End Try
        End Sub


    Hier noch die Klasse dazu

    Public Class Schwankung
    
        Private SW As Double
        Private doHoch = 0, doTief As Double = 0
        Private doAHoch = 0, doATief As Double = 0
        Private FHoch = True, FTief As Boolean = True
        Private Wert As Double = 0
    
    
        'Umschaltwert wird bei Erzeugung abgefragt
        Public Sub New(ByVal SW_1 As Double)
            SW = SW_1
        End Sub
    
        'Rückgabewerte
        Function Ausgabe_Wert() As Double
            Ausgabe_Wert = Wert
        End Function
    
        'Schwankungen berechnen
        Sub Schwankung(ByVal Kurs As Double)
    
            If Kurs >= doHoch Then
                doHoch = Kurs
                If FTief = True Then FTief = False : Wert = doTief : FHoch = True
                doTief = doHoch - SW
            End If
    
            If Kurs <= doTief Then
                doTief = Kurs
                If FHoch = True Then FHoch = False : Wert = doHoch : FTief = True
                doHoch = doTief + SW
            End If
    
        End Sub
    
    End Class

    Frage zu dieser Klasse... Kann man das auch in SQL Code darstellen. Ich habe mal gelesen das es schneller
    wäre, wenn Berechnungen in der DB gemacht werden. 

    Fragen über Fragen...

    Gruß Olaf


    Dienstag, 5. August 2014 08:43

Antworten

  • Hallo Olaf,

    grundsätzlich solltest Du Deinen Code mit Option Strict On schreiben. Das erlaubt Visual Basic weniger Konvertierungen führt oft aber zu schnellerer Ausführung. Oben hast Du versehentlich einige Stolpersteine eingebaut wie:

    Private doHoch = 0, doTief As Double = 0
    Private doAHoch = 0, doATief As Double = 0
    
    ' sollte sein:
    Private doHoch As Double = 0, doTief As Double = 0
    ' oder besser (sinnvoller)
    Private doAHoch, doATief As Double
    

    Das würde durch Option Strict On angemäkelt. Durch die Initialisierung mit 0 müsstest Du bei jeder Deklaration As Double schreiben. Da aber ohnehin jede Variable mit 0 (bzw. hier richtiger 0.0) initialisiert wird, kann man die Zuweisung ganz weglassen. (Entsprechendes gilt für die Boolean Variablen)

    Dann könnte man, wie in der zweiten Variante gezeigt, beide Variablen mit einer Deklaration versehen. Wobei ich der Lesbarkeit darauf verzichten würde und jeder Variable eine eigene Zeile spendieren würde  - ebenso wird der Code lesbarer (wenn auch nicht schneller), wenn man auf ":" verzichtet - wie Du es in Schwankung praktizierst.

    Die Einlese-Schleife kann man (.NET 4.0 vorausgesetzt) mit File.ReadLines etwas effizienter schreiben:

            Dim Datei As String = "test.txt"
            Try
                Dim watch = System.Diagnostics.Stopwatch.StartNew()
    
                For Each line In System.IO.File.ReadLines(System.IO.Path.Combine("d:\Marktdaten", Datei))
                    Dim sw = Double.Parse(line) ' Konvertieren in einen Double
                    c_Markt.Schwankung(sw)
                    feDaten1(x) = sw
                    Einlesen(x)
                    x += 1
                Next
                watch.Stop()
                Console.WriteLine("Einlesen: {0} ms", watch.ElapsedMilliseconds)
            Catch ex As Exception
    
            End Try
    

    Dabei wird der Wert (bei Option Strict On Pflicht) einmalig in einen Double konvertiert. Sollte es sich bei feDaten1 um ein Array handeln, so könnte eine List(Of T) günstiger sein (und x als Zähler wäre nicht notwendig). Ob man etwas bei Einlesen "verbessern" kann kann ich nicht sehen.

    Messen sollte man besser mit einer Stopwatch, wie oben gezeigt, die ist genauer. Beachte, dass beim ersten Durchlauf auch die Zeit für die JIT Kompilierung einfließt. Messen sollte man eher beim zweiten oder dritten Male.

    P.S.: Grundsätzlich kann man so etwas auch mit SQL machen, nur braucht man dazu eine SQL-fähige Datenbank. Mit einer Textdatei geht das nicht (direkt). Wobei i. a. die lesende Verarbeitung einer Textdatei schneller ist, solange die Verarbeitung nur einmalig erfolgt (wie es oben zu vermuten ist).

    Solange man das nur gelegentlich macht, sollte man sich aber nicht zuviel Gedanken darüber machen - und weniger als 30 Sekunden für die Datenmenge ist IMHO noch akzeptabel.

    Gruß Elmar

    Dienstag, 5. August 2014 09:55
    Beantworter

Alle Antworten

  • Hallo Olaf,

    grundsätzlich solltest Du Deinen Code mit Option Strict On schreiben. Das erlaubt Visual Basic weniger Konvertierungen führt oft aber zu schnellerer Ausführung. Oben hast Du versehentlich einige Stolpersteine eingebaut wie:

    Private doHoch = 0, doTief As Double = 0
    Private doAHoch = 0, doATief As Double = 0
    
    ' sollte sein:
    Private doHoch As Double = 0, doTief As Double = 0
    ' oder besser (sinnvoller)
    Private doAHoch, doATief As Double
    

    Das würde durch Option Strict On angemäkelt. Durch die Initialisierung mit 0 müsstest Du bei jeder Deklaration As Double schreiben. Da aber ohnehin jede Variable mit 0 (bzw. hier richtiger 0.0) initialisiert wird, kann man die Zuweisung ganz weglassen. (Entsprechendes gilt für die Boolean Variablen)

    Dann könnte man, wie in der zweiten Variante gezeigt, beide Variablen mit einer Deklaration versehen. Wobei ich der Lesbarkeit darauf verzichten würde und jeder Variable eine eigene Zeile spendieren würde  - ebenso wird der Code lesbarer (wenn auch nicht schneller), wenn man auf ":" verzichtet - wie Du es in Schwankung praktizierst.

    Die Einlese-Schleife kann man (.NET 4.0 vorausgesetzt) mit File.ReadLines etwas effizienter schreiben:

            Dim Datei As String = "test.txt"
            Try
                Dim watch = System.Diagnostics.Stopwatch.StartNew()
    
                For Each line In System.IO.File.ReadLines(System.IO.Path.Combine("d:\Marktdaten", Datei))
                    Dim sw = Double.Parse(line) ' Konvertieren in einen Double
                    c_Markt.Schwankung(sw)
                    feDaten1(x) = sw
                    Einlesen(x)
                    x += 1
                Next
                watch.Stop()
                Console.WriteLine("Einlesen: {0} ms", watch.ElapsedMilliseconds)
            Catch ex As Exception
    
            End Try
    

    Dabei wird der Wert (bei Option Strict On Pflicht) einmalig in einen Double konvertiert. Sollte es sich bei feDaten1 um ein Array handeln, so könnte eine List(Of T) günstiger sein (und x als Zähler wäre nicht notwendig). Ob man etwas bei Einlesen "verbessern" kann kann ich nicht sehen.

    Messen sollte man besser mit einer Stopwatch, wie oben gezeigt, die ist genauer. Beachte, dass beim ersten Durchlauf auch die Zeit für die JIT Kompilierung einfließt. Messen sollte man eher beim zweiten oder dritten Male.

    P.S.: Grundsätzlich kann man so etwas auch mit SQL machen, nur braucht man dazu eine SQL-fähige Datenbank. Mit einer Textdatei geht das nicht (direkt). Wobei i. a. die lesende Verarbeitung einer Textdatei schneller ist, solange die Verarbeitung nur einmalig erfolgt (wie es oben zu vermuten ist).

    Solange man das nur gelegentlich macht, sollte man sich aber nicht zuviel Gedanken darüber machen - und weniger als 30 Sekunden für die Datenmenge ist IMHO noch akzeptabel.

    Gruß Elmar

    Dienstag, 5. August 2014 09:55
    Beantworter
  • Hallo Elmar,

    allein das Option Strice On hat geholfen.
    Dann noch den Code mit deinem File.Reader und wir sind bei der gleichen Datenmenge bei 6.761 Sek.
    Prima. Vielen Dank.

    Ich werde das alles ohne DB machen. Jetzt geht es ja auch mit Textdateien.

    Nochmals vielen Dank.

    Gruß Olaf 

    Dienstag, 5. August 2014 11:30
  • Die List(Of T) ist ja genial.
    Keinerlei Dimensionierungen oder sonstige Klimmzüge. 

    Dienstag, 5. August 2014 16:20