Diskussion zum Artikel "SQLite-Fähigkeiten in MQL5: Beispiel für ein Dashboard mit Handelsstatistiken nach Symbolen und magischen Zahlen" - Seite 2

 
SQLite: нативная работа с базами данных на SQL в MQL5
SQLite: нативная работа с базами данных на SQL в MQL5
  • 2020.02.18
  • www.mql5.com
Разработка торговых стратегий связана с обработкой больших объемов данных. Теперь прямо в MQL5 вы можете работать с базами данных с помощью SQL-запросов на основе SQLite. Важным преимуществом данного движка является то, что вся база данных содержится в единственном файле, который находится на компьютере пользователя.
 
Ich habe voreilige Schlüsse gezogen, ohne mich eingehend mit der Sache auseinanderzusetzen. Entschuldigung – mit der Bezeichnung „Spielzeug für Studenten“ habe ich übertrieben, SQLite hat das nicht verdient.

Ich habe mich eingehender damit befasst (mithilfe von KI, Opus 5 – ich habe einen Teststand aufgebaut, synthetische Daten für 500.000 Transaktionen, 20 Symbole und 20 Magiker generiert und die Messungen durchgeführt). Hier ist die Zusammenfassung.

1) Fünf Minuten bei fxsaber – das ist mit ziemlicher Sicherheit NICHT SQLite.

Ein einzelner INSERT-Befehl pro Transaktion mit automatischem Commit: ~245 Sekunden für 500.000 Transaktionen.
Dieselben Daten als Batch innerhalb einer einzigen Transaktion: 2,35 Sekunden.

Ein Unterschied um das 104-Fache. 245 Sekunden – das sind genau diese „fünf Minuten“. Jeder Eintrag = separate Transaktion mit fsync. Das lässt sich mit zwei Zeilen beheben: DatabaseTransactionBegin() / DatabaseTransactionCommit(). Alles andere in dieser Diskussion ist angesichts dieser Zahl nebensächlich.

2) Maxim hat Recht, was Indizes angeht, aber nicht in Bezug auf diese Indizes.

Abfrage aus dem Artikel, Schema ohne Indizes: 395 ms.
Dieselbe Abfrage + gewöhnlicher Index (MAGIC, ENTRY): 427 ms. Das heißt, es hilft überhaupt NICHT.
Derselbe + ein Abdeckindex (MAGIC, ENTRY, PROFIT, SWAP, COMMISSION): 80 ms.

Für ein vollständiges GROUP BY ist ein gewöhnlicher Index nutzlos – die Tabelle wird ohnehin vollständig gelesen, der Plan SCAN … USING INDEX entspricht einem Scan. Es ist erforderlich, dass ALLE Spalten der Abfrage im Index enthalten sind; dann wird der Plan zu SEARCH … USING COVERING INDEX, und es kommt gar nicht erst zum Lesen der Tabellenzeilen. Dann ergibt sich eine 5-fache Beschleunigung.

Wo der Index jedoch wirklich hilft, sind Abfragen nach einzelnen Symbolen, die das Bedienfeld bei jedem Neuzeichnen durchführt: 20 Abfragen WHERE SYMBOL=? AND ENTRY=1 – 711 ms ohne Index gegenüber 208 ms mit Index.

3) Zum Array von Strukturen. Im Grunde habe ich recht, aber nur, wenn man eine eigene Wrapper-Klasse mit den erforderlichen Indizes und Methoden schreibt. SQLite verkürzt natürlich die Entwicklungszeit auf Kosten der Leistung und des Ressourcenverbrauchs.

Das Einlesen der gesamten 45,8 MB großen Binärdatei: 25 ms.
Ein Durchlauf, Aggregationen nach Mag-Werten und nach Zeichen gleichzeitig: 7 ms.
Zum Vergleich – das Auslesen derselben 500.000 Zeilen aus SQLite in ein Struktur-Array ( DatabaseReadBind-Zyklus): 220 ms.

Der Geschwindigkeitsvorteil ist real – je nach Operation um das 4- bis 18-Fache. Und die Zahlen 220 ms gegenüber 25 ms sprechen für sich: Wenn die Statistik ohnehin in MQL5 ausgewertet wird, fungiert die Datenbank in diesem Szenario lediglich als langsames Dateiformat.

Aber die Datenbank auf der Festplatte belegt 84 MB gegenüber 46 MB für die Binärdatei – und für diese zusätzlichen 38 MB erhalten Sie beliebige Filter, Sortierungen, Paginierung und beliebige neue Berichte kostenlos. In einem Array von Strukturen gibt es diese Funktionen nicht, solange Sie sie nicht selbst programmieren. Die Aussage „Man braucht keine Datenbank“ trifft also genau so lange zu, bis eine Abfrage erforderlich wird, die Sie nicht im Voraus vorgesehen haben. Enrique hat hier recht: Wenn Daten ABGEFRAGT werden müssen und nicht nur geladen werden – da ist SQL unschlagbar.

4) Was PostgreSQL betrifft, nehme ich meine Worte zurück.

Es handelt sich um ein Client-Server-System, das sich nicht integrieren lässt: separater Prozess, Installation, Ports, Administratoraufgaben. Für ein Einzelbenutzer-Terminal in der Sandbox passt das architektonisch nicht. Und für lokale Analysen ist SQLite oft sogar noch schneller – es gibt kein IPC und keine Roundtrips. Das Argument bezüglich JSONB ist ebenfalls hinfällig: JSONB ist in SQLite seit Version 3.45 vorhanden, und für den Transaktionsverlauf wird JSON überhaupt nicht benötigt, da dort streng typisierte Spalten verwendet werden.

Fazit

Der Hauptkritikpunkt am Artikel betrifft das Schema und den Code, nicht die Engine. Die Kluft zwischen „SQLite wie im Artikel“ und „richtig eingesetztem SQLite“ beträgt das Hundertfache. Die Kluft zwischen richtig eingesetztem SQLite und einem Array von Strukturen beträgt nur das Einfache.

Und das Sinnvollste in diesem Thread hat 92746290 gesagt: Man sollte nicht den gesamten Verlauf neu laden, sondern ab der zuletzt registrierten Transaktion nachladen. Das behebt das Problem unabhängig davon, ob Sie eine Binärdatei oder eine Datenbank verwenden.

Das Schema mit überlappenden Indizes, Batch-Einfügung und inkrementellem `Sync()` sowie die Version mit einem Array von Strukturen kann ich gerne bereitstellen, falls Interesse besteht.

Ich wiederhole: Ich selbst verwende natürlich leichtgewichtige Klassen mit Indizes und den erforderlichen Methoden ohne jegliche Datenbanken, was einen deutlichen Vorteil hinsichtlich Ressourcenverbrauch und Leistung bietet.
 
Nikolai Semko #:
Ich habe voreilige Schlüsse gezogen, ohne mich eingehend mit dem Thema zu befassen. Entschuldigung – mit der Bezeichnung „Spielzeug für Studenten“ habe ich übertrieben, SQLite hat das nicht verdient.

Wahrscheinlich nicht für Studenten, aber dennoch ein Spielzeug. Denn bevor man SQLite nutzen kann, muss man den gesamten Verlauf „durchforsten“ und elementweise in die Tabelle eintragen. Und das kostet eine Menge Zeit. Wenn man das schon an MQL5 anbinden will, dann muss man auch das Auslesen der Order- und Transaktionshistorie direkt in die Tabelle vornehmen… IMHO

 
Nikolai Semko #:
Ich habe etwas tiefer gegraben (mithilfe von KI, Opus 5 – habe einen Teststand aufgebaut, synthetische Daten für 500.000 Transaktionen, 20 Symbole und 20 Magics generiert und die Messungen durchgeführt).

Allgemein: Ein Vergleich mit MonetDB/e wäre interessant. Es handelt sich um eine ebenso eingebettete, serverlose Datenbank wie SQLite, sollte aber aus verschiedenen Gründen bei komplexen Abfragen deutlich schneller sein. Natürlich vorausgesetzt, das Schema ist sinnvoll :-)

 
Maxim Kuznetsov #:

Allgemein gesprochen: Ein Vergleich mit MonetDB/e wäre interessant. Es handelt sich um eine ebenso eingebettete, serverlose Datenbank wie SQLite, sollte aber aus verschiedenen Gründen bei komplexen Abfragen deutlich schneller sein. Natürlich vorausgesetzt, das Schema ist sinnvoll gestaltet :-)

Möglicherweise
Darüber habe ich auch schon nachgedacht
Für Arrays ist NoSQL besser geeignet
Das muss man mal ausprobieren. Mit KI lässt sich das jetzt schnell überprüfen