Model/View-Optimierung für große Tabellen

Alles rund um die Programmierung mit Qt
Antworten
wijaa
Beiträge: 4
Registriert: 2. Februar 2009 11:20

Model/View-Optimierung für große Tabellen

Beitrag von wijaa »

Hallo!

ich möchte eine Tabellenanwendung mittels Ableitungen der Klassen QTableView und QSqlQueryModel schreiben, die folgendes erfüllen soll:

* die Inhalt der SQLite-Tabelle kommt von einem Join mit 4 Tabellen und enthält viele (> 1000 bis ca. 100.000) Tabellenzeilen. Umgesetzt mit QTableView und QSqlQueryModel benötigt nur die Darstellung der Applikation bereits mehrere Minuten. Ich nehme an, dass das Modell _alle_ Daten aus der SQL-Abfrage lädt und in einer internen Datenstruktur abspeichert. Bei der Datenmenge ist das natürlich ineffizient.
* die Anwendung soll eine schnelle Sortier- und Filterfunktion besitzen.
* die Tabellenzellen sollen editierbar sein.

Es ist mir klar, dass ich ein eigenes Modell werde bauen müssen, da ja QSqlQueryModell nicht schreibbar ist.

Auch sollte die abgeleitete Klasse nur immer die Zeilen aus der DB laden, die vom View gerade gebraucht werden. Ich denke da daran, die Ergebnisse des Select-Statements mit LIMIT und OFFSET zu beschränken.

Wie man jedoch bei so vielen Zeilen effiziente Sortier- und Filtermechanismen einbaut, ist mir noch unklar. Vielleicht ist es der einfachste Weg, über das SQL-Statement zu sortieren (ORDER) und zu filtern (LIKE). Eine andere Möglichkeit wäre es mM, bereits abgefragte Daten im Modell zu cachen bzw. zu versuchen, bspw. über Suchbäume und ähnliche Datenstrukturen, SQL-Abfragen zu sparen oder zu umgehen.

Vielleicht könnt ihr kurze Hinweise geben, wie man dieses Problem konzeptionell am besten angeht. Ich weiß, dass meine Ausführungen sehr vage und oberflächlich sind, aber mehr kann ich dazu leider im Moment nicht schreiben, weil ich nicht weiß, wo ich den Hebel ansetzen soll.
montuno
Beiträge: 1
Registriert: 8. April 2009 16:30

Re: Model/View-Optimierung für große Tabellen

Beitrag von montuno »

Grundsätzlich denke ich gehts hier um zwei Probleme:
1. Performance
2. Technische Umsetzung

Du solltest Dir die folgenden Fragen stellen:

1.1 Müssen immer alle Daten angezeigt werden oder reicht es beispielsweise, wenn nur ein Teil editiert und sortiert würde?
1.2 Wo ist der Vorteil wenn > 1000 Zeilen editiert werden müssen? Wo bleibt die Übersicht?
1.3 Filtern über SQL, Sortieren des Teilresultates über QT wenn das gewünscht wird (ist komfortabler). Dann klappts auch mit der Performance

2.1 QSqlTableModel. Ableiten. Eigene setData Methode
2.2 Man kann festlegen, dass nur die sichtbaren Zeilen geladen werden. Fällt aber weg sobald im UI sortiert oder gefiltert wird.

Bemerkung: Schon nur die Anzeige von bis zu 100 Zeilen überfordert meistens die Benutzer, ein cachen ist demnach eher unnötig, filtern ist die m.M. bessere Methode

Gruss...
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

1. Nur die Primär-Schlüssel laden
2. Datenzeilen nicht einzeln holen, sondern Blockweise und diese auch cachen.
3. Weder LIMIT noch OFFSET sollten in diesem Fall nötig sein.

Rest wurde schon gesagt
wijaa
Beiträge: 4
Registriert: 2. Februar 2009 11:20

QTableView ist schon ein bisschen langsam

Beitrag von wijaa »

Meine Frage hat eigentlich grundsätzlich darauf abgezielt, das QTableView in der Bedienung so schnell wie möglich zu machen und Latenzen zu vermeiden. Meine bisherigen Versuche mit Daten in der Größenordnung von 20.000 Zeilen lassen das QTableView schon merklich langsam werden, dh. scrollen, Tabellenspalten per Maus vergrößern / verkleinern sind auf meinem Rechner schon merklich verzögert und deutlich langsamer als bei vergleichbaren nativen Win32-Programmen.

Wie gut seht ihr die Chancen, die QTableView so schnell wie in einer "normalen" Win32-Applikation hinzubekommen.

Derzeit überlege ich, die Datenbankkomponente wegzulassen und die Daten in einer zweidimensionalen Datenstruktur zu speichern, die Datenbank ist nämlich nicht zwingend notwendig.
CLRS530
Beiträge: 155
Registriert: 8. Oktober 2007 18:00

Beitrag von CLRS530 »

Genau aus diesem Grund haben die anderen dir mitgeteilt, alternative Wege zu suchen, da du keinen großen Geschwindigkeitszuwachserreichen wirst (ob nun mit Datenbankmodell oder ohne).
Du solltest versuchen deine Ergebnismenge einzugrenzen, was auch immer der Übersicht dienen wird.
Über eine Combo Box nur A-G ... oder andere Felder, die du eventuell hast.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Eine TableView ist nicht langsam, egal wieviele Spalten/Zeilen es darstellen soll. Wenn dann ist es das Model, das nicht schnell genug Daten liefern kann.
CLRS530
Beiträge: 155
Registriert: 8. Oktober 2007 18:00

Beitrag von CLRS530 »

Die These halte ich für gewagt. Ich selber habe da bisher keine Erfahrungen gemacht, habe aber schon von genug Problemen gehört. Natürlich mag es meistens an den Daten liegen, die vom Model geholt werden müssen. Aber mehr als alles cachen und zurückgeben kannst du nicht machen. Wenn es dann Verzögerungen und ruckler gibt liegt es doch irgendwie trotzdem an dem View oder zumindestens dem gesamten Konzept.
Ich werde das aber einmal selber mit einem Pseudomodell überprüfen.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Code: Alles auswählen

class TableModel : public QAbstractTableModel
{
Q_OBJECT
public:
  TableModel(QObject *parent=0) : QAbstractTableModel(parent) {}
  ~TableModel() {}

  int columnCount(const QModelIndex &parent=QModelIndex()) const { return 1000000; }
  QVariant data(const QModelIndex & index, int role=Qt::DisplayRole) const
  {
    if (role==Qt::DisplayRole) {
      return QString("%1 - %2").arg(index.row()).arg(index.column());
    }

    return QVariant();
  }

  int rowCount(const QModelIndex &parent=QModelIndex()) const  { return 50000000; };
};

Antworten