Seite 1 von 1

SQLIte zu Langsamm, mit IMMEDIATE funktioniert es nicht !!!!

Verfasst: Donnerstag 23. August 2007, 22:45
von Zandi178
Moin
Also ich habe das Problem, das ich eine Menge von einzelnen Zeichenketten in eine Datenbank eintragen muss.
Ich habe es wie folgt die Verbindung der Datenbank angelegt, und die Tabelle erstellt.

Code: Alles auswählen

                self.mycon = sqlite.connect(datenbank), isolation_level = None)
                self.cursor = self.mycon.cursor()
                try:
                    self.cursor.execute ("""CREATE TABLE csv (
                                             Nummer varchar (10),
                                             Typ varchar (2),
                                             Anlage varchar(10),
                                             AnlageNr varchar(2),
                                             FGName varchar(15),
                                             Operand varchar(15),
                                             Kommentar varchar(60),
                                             Pult varchar(2),
                                             Station varchar(2),
                                             Kommt varchar(20),
                                             Geht varcahr(20),
                                             Dauer varchar (10))""")
durch self.cursor kann ich später in einem Unterprogramm mein sqlstring schreiben das sieht wie folgt aus

Code: Alles auswählen

self.cursor.execute(self.sqlstr)
Bei einem Eintrag von 12 Spalten und ca. 1300 Zeilen
Brauche ich mehr als 60 Sekunden für den ganzen Vorgang.
Nun habe ich gelesen das ich bei beim Connecten zur Datenbank beim

Code: Alles auswählen

isolation_level = None

dieses zu

Code: Alles auswählen

isolation_level = 'IMMEDIATE'

Ändern kann um eine schnellere Verbindung zu haben.

Und wau, auf einmal dauert es nur noch 0,35sekunden und er sagt mir er hat alle Datensätze in die Datenbank geschrieben (woher ich dieses weiß, es läuft ein Zähler mit *g*). Ganz stolz öffne ich jetzt die Datenbank wo mich aber schon die Größe erstaunen läst sonst immer gute 180000kb jetzt nur noch 2400kb, also wird da irgend was nicht stimmen. Nun öffne ich die Datenbank mit der Hilfe von SQLIteSpy, da es sich um eine .db3 datenbank handelt.
Er behauptet zwar er hat alles geschrieben, aber was er wirklich nur geschrieben hat Ist die Datenbank selbst mit den Spaltennamen. Aber kein Eintrag in die Datenbank selbst, was er aber behauptet.

Nun habe ich halt die Frage an euch!!
Habe ich irgendwas vergessen, wenn ich dieses 'IMMEDIATE' benutzten will, muss ich irgendwo anders noch was hinschreiben damit, dieses richtig funktioniert ???

Mfg Zandi

ps: Rechtschreibfehler dürfen behalten werden.
bemüh mich ja auch, aber als Legastheniker ist das nicht so einfach ;)

Verfasst: Donnerstag 23. August 2007, 23:10
von BlackJack
Versuch's doch einfach mal ohne explizite Angabe, mit `executemany()` statt `execute()` und vergiss das `commit()` am Ende nicht. Bei `None` wird "auto commit" benutzt, das ist natürlich langsam.

Verfasst: Donnerstag 23. August 2007, 23:37
von Zandi178
Oh shcnell antowort;)

Also ich habe es dann wiefolgt eingeben nun, hoffe es ist richtig.
Normal bei None brauch ich bei meiner Test Datei zum vergleichen 30 sekunden und nun wie ich esjertzt eigenben habe.
Wenn ich das Commit() so wie gleich imquelltest zu sehen eingebe bruache ich auhc 30 sekunden ( isolation level ist immediate) somit kam da keine verbesserung
edigt: Immerhin erstellt er nun auch den Inhalt für die Datenbank aber die geschwindigkeit bleibt gleich

Code: Alles auswählen

        
        while True:
            self.logline = self.fr.readline()
            if not self.logline: break
            self.__formatiereZeile()
            if not self.sqlstr:
                pass
            else:
                self.cursor.execute(self.sqlstr)
                self.mycon.commit()
            self.zaehler += 1
        self.cursor.close()
        self.mycon.close()
bei eingabe anstatt von execute executemany bekomm ich ein fehler

" function tkaes exactly 2 arguments 1given

Re: SQLIte zu Langsamm, mit IMMEDIATE funktioniert es nicht

Verfasst: Donnerstag 23. August 2007, 23:37
von veers
Zandi178 hat geschrieben:ps: Rechtschreibfehler dürfen behalten werden.
bemüh mich ja auch, aber als Legastheniker ist das nicht so einfach ;)
Spellchecker ;)
Wobei ich den Post jetzt ganz ok fand ;)

Das mit dem commit() hat Blackjack ja schon erwähnt.

Re: SQLIte zu Langsamm, mit IMMEDIATE funktioniert es nicht

Verfasst: Donnerstag 23. August 2007, 23:40
von Zandi178
veers hat geschrieben:
Zandi178 hat geschrieben:ps: Rechtschreibfehler dürfen behalten werden.
bemüh mich ja auch, aber als Legastheniker ist das nicht so einfach ;)
Spellchecker ;)
Wobei ich den Post jetzt ganz ok fand ;)

Das mit dem commit() hat Blackjack ja schon erwähnt.
gebe mir ja mühe ;)
Ja wie gesagt mit Commit()

Code: Alles auswählen

        while True:
            self.logline = self.fr.readline()
            if not self.logline: break
            self.__formatiereZeile()
            if not self.sqlstr:
                pass
            else:
                self.cursor.execute(self.sqlstr)
                self.mycon.commit()
            self.zaehler += 1
        self.cursor.close()
        self.mycon.close()
funktioniert das eintragen mit immediate aber, es gibt keine geschwindikeit verbesserung

Verfasst: Freitag 24. August 2007, 00:22
von BlackJack
Gnarf. Jetzt machst Du nach jedem Datensatz selbst ein `commit()`, dann kannst Du auch bei "auto commit" bleiben.

Also nochmal: Erst einmal gar kein Isolationslevel angeben, damit bleibst Du kompatibel mit anderen Datenbanken. Dann `executemany()` benutzen. Natürlich *richtig* benutzen, es gibt so etwas wie Dokumentation. Und das `commit()` nachdem alle Daten geschrieben wurden.

Der Quelltextschnippsel sieht auch etwas unübersichtlich aus. Warum passiert die Übergabe über Objektattribute und nicht über Argumente?

Wie wird `self.sqlstr` erstellt? Man sollte die Daten nicht selbst in SQL hineinformatieren sondern das dem Datenbankmodul überlassen.

Die While-Schleife solltest Du durch eine ``for``-Schleife über `self.fr` ersetzen. Zusammen mit `enumerate()` falls der `zaehler` wichtig ist. Der Name `fr` ist ein wenig zu kurz und nichtssagend.

Wenn nur ``pass`` in einem Zweig bei ``if``/``else`` steht, dann hat man etwas falsch gemacht. Diesen Zweig kann man immer eliminieren. Ungetestet:

Code: Alles auswählen

    SQL = 'INSERT table_name (a, b, c) VALUES (?, ?, ?)'
    
    zaehler = 0
    for zaehler, logline in enumerate(self.fr):
        # 
        # `formatiere_zeile()` ist ein schlechter Name, `data` ist muss
        # ein Tupel mit Spaltenwerten sein.
        # 
        data = self.formatiere_zeile(logline)
        if data:
            self.cursor.execute(SQL, data)
    
    self.mycon.commit()
    self.cursor.close()
    self.mycon.close()
Falls Du auf den Zähler verzichten kannst, wird es mit `executemany()` und `itertools.imap()` ein wenig kürzer (ungetestet):

Code: Alles auswählen

    SQL = 'INSERT table_name (a, b, c) VALUES (?, ?, ?)'
    
    # 
    # `formatiere_zeile()` ist ein schlechter Name, `data` ist muss
    # ein Tupel mit Spaltenwerten sein.
    # 
    data = (d for d in imap(self.formatiere_zeile, self.fr) if d)
    self.cursor.executemany(SQL, data)
    
    self.mycon.commit()
    self.cursor.close()
    self.mycon.close()

Verfasst: Freitag 24. August 2007, 00:49
von Zandi178
Hey super dank an dir.

Habe das nun geändertund brauche für die testdatei nur noch 0.25 sekunden ;) :D