Seite 1 von 1

Performance-Verbesserungen von Qt-Datenbankmodels

Verfasst: 20. August 2010 14:28
von philistion
Hallo,

welche Möglichkeiten seht Ihr generell, ein Model-View-System aus einem Datenbankmodel und einem QTableView zu beschleunigen?

Gibt es hier von euch bevorzugte Methoden?

Ich fand ofiziell nur diesen kleinen Absatz: http://doc.qt.nokia.com/4.6/model-view- ... ts-of-data

Die Frage ist, sollte man ein eigenes Model schreiben, welches man dann "von Hand" optimiert und ein Caching-System über fetchMore() etc. implementiert, oder sind die vorhandenen (z.B. QSqlQueryModel) schon an der Grenze des Machbaren?

Ist da noch etwas herauszuholen, oder sollte man bei vielen Daten und mehr Performancebedarf dann einfach auf ein anderes Datenbanksystem umsteigen?

mfG

Verfasst: 20. August 2010 14:47
von upsala
Ein andere Datenbanksystem bringt meist gar nichts, da der Flaschenhals oft der Transfer von der DB zur Anwendung ist, bzw. die Ablage darin.

Eine Möglichkeit für die Darstellung großer Tabellen mit einem Primär-Schlüssel wäre folgende:
Eine QSqlQuery aufsetzen, die von alle gewünschten Datensätzen immer nur den PrimärSchlüssel zurückgibt. Diese Liste in einem QVector speichern. Und wenn jetzt die View Daten anfordert immer nur in der Datenbank die Daten zum jeweiligen PK abholen, puffern und an die View übergeben. Am besten auch noch die Daten, die davor/dahinter liegen.
Allerdings müssen in diesem Falle, wenn man es braucht sort() und match() auch reimplementiert werden, da ansonsten der gesamte Performance-Vorteil dahin ist. Auch Proxy-Modelle können in diesem Falle hinderlich sein.

Verfasst: 20. August 2010 16:56
von philistion
Danke für den Vorschlag, also in meinem Anwendungsfall ändern sich die Daten in der Datenbank regelmäßig, ich muss also etwa im 2 Sekunden Takt schauen ob ein neuer Primärindex, den ich noch nicht in meinem Vektor habe, hinzugekommen ist. Wenn ja kopiere ich ihn in den Vector, dieser reicht erst mal aus um dem Model eine Größe (durch die rowCount) zu geben und alle Daten die benötigt werden lade ich gecached nach.
Klingt gut!

In meinem Fall sind allerdings einfache Filter noch notwendig, da wäre dann wohl einfacher dies direkt im Model mitzuintegrieren als das Model kompatibel zu einem Proxymodel zu machen, oder?

Wie soll man sich so einen Cache konkret vorstellen? Einfach bei jedem Scroll-Signal die nächsten 10 nachladen? Wohl aber nicht immer einfach alle 10 vorher und nachher, sondern je nachdem wie man scrollt oder?
Wenn ich lange nach oben scrolle, kenne ich ja die dahinter liegenden Items schon und muss nur die davor liegenden nachholen. Irgendwann muss ich sie aber auch wieder verwerfen. Gibt es da intelligente Caching-Ansätze oder meint Ihr, ich soll einfach einen simplen 10 davor und 10 danach Buffer einbauen?

Wie sollte man einen Cache konkret abbilden, als std::queue?

Verfasst: 20. August 2010 20:52
von upsala
Wir sind hier bei Qt, also nehmen wir ein QCache.

Und nachgeladen wird einfach das, was data() verlangt +-n Zeilen.

Verfasst: 22. August 2010 10:10
von philistion
Danke, was aber ist mit den Funktionen fetchMore und canFetchMore?

Würdest du die nicht einsetzen, und den Cache von data() aus neu befüllen und das gesuchte Element zurückgeben?

Also ein if cache.contains(index.row()) return cache[index.row()]; und dann beim else die Nachladeprozedur? z.B. gewünschte Zeile + 10?

Verfasst: 22. August 2010 10:36
von upsala
fetchMore bzw. canFetchMore wird von den SqlModels benutzt. Immer wenn du in diesen Models nach unten scrollst, werden weitere Daten nachgeladen. Das ist aber nicht das Konzept, das ich dir vorgeschlagen habe.

Verfasst: 22. August 2010 14:31
von philistion
Danke, nun nur noch eine kleine Frage:

Ich habe in meiner Datenbank alle möglichen Datenspalten, einen Timestamp und eine ID (AUTOINCREMENT) als Primary Key.

Was nun in der data() Funktion bei index.row() zurückkommt, ist ja die Nummer, der gewünschten Spalte, also die "wie vielte" gewünscht ist. Das muss aber nicht immer mit dem Primärschlüssel meiner Datenbank übereinstimmen, oder etwa doch?

Ich lade ja nun in meiner data() Funktion n+-10 Spalten nach, gibt es einen Weg wie ich bei SQL die n-te Spalte suchen kann, ohne mich auf den Primary Key zu stützen? Oder kann ich das hier getrost tun?

// Update: "SELECT * FROM the_table ORDER BY id DESC LIMIT row,10" wäre eine Möglichkeit, aber wird damit nicht erst alles eingelesen, und dann mit Limit rausgefiltert? Oder ist das schon optimiert dass nur die mit Limit angegebenen Datensätze gelesen werden?

Ginge auch "SELECT * FROM the_table LIMIT row,10"?

Verfasst: 23. August 2010 12:53
von RHBaum
Prinzipiell:
LIMIT row,10
Ist nicht Teil der SQL Spec (SQL99) oder irr ich mich ?
Wenn ich mich nicht irre, verlaesst du damit den Pfad des regulaeren SQL und bindest Dich an eine bestimmte RDBMS.

Das kann nen nachteil sein, muss aber nicht. Wenn Du aggressiv optimieren willst, kommst eh ned drumherum, auf deine DB besonders einzugehen.

Deshalb die Frage:
1. Was fuer ein RDBMS hasst Du?
2.
ich muss also etwa im 2 Sekunden Takt schauen ob ein neuer Primärindex, den ich noch nicht in meinem Vektor habe, hinzugekommen ist.
Das klingt eher nicht nach RDBMS ... Datenbanken funktionieren eher anders. Die Frage iss hier auch, Muss es eine DB sein als Backend ? Hasst Du da ueberhaupt Einfluss drauf.
Wenn ja wieviel Zeit und Energie kannst du verwenden um die DB zu eliminieren und durch was praktischeres (eventgenerierendes) zu ersetzen ?

Glaub Dein momentanes Konzept gibt Dir derzeit die Schranken vor ...
Ob sich da viel optimieren laesst, haengt sehr von deinen Randbedingungen ab ...

Ciao ...