Обсуждение статьи "Возможности SQLite в MQL5: Пример интерактивной панели с торговой статистикой в разрезе символов и магиков" - страница 2

 
SQLite: нативная работа с базами данных на SQL в MQL5
SQLite: нативная работа с базами данных на SQL в MQL5
  • 2020.02.18
  • www.mql5.com
Разработка торговых стратегий связана с обработкой больших объемов данных. Теперь прямо в MQL5 вы можете работать с базами данных с помощью SQL-запросов на основе SQLite. Важным преимуществом данного движка является то, что вся база данных содержится в единственном файле, который находится на компьютере пользователя.
 
Поспешил с суждениями, не копнув глубоко в суть. Прошу прощения — про «игрушку для студентов» я загнул, SQLite такого не заслужил.

Копнул поглубже (с помощью ИИ, Opus 5 — собрал стенд, сгенерил синтетику на 500 000 сделок, 20 символов, 20 магиков, прогнал замеры). Вот что резюмируется.

1) Пять минут у fxsaber — это почти наверняка НЕ SQLite.

INSERT по одной сделке в автокоммите: ~245 секунд на 500k.
Те же данные пачкой внутри одной транзакции: 2.35 секунды.

Разница в 104 раза. 245 секунд — это ровно те самые «пять минут». Каждая вставка = отдельная транзакция с fsync. Лечится двумя строчками: DatabaseTransactionBegin() / DatabaseTransactionCommit(). Всё остальное в этом споре на фоне этой цифры — мелочи.

2) Максим прав про индексы, но не про те индексы.

Запрос из статьи, схема без индексов: 395 мс.
Он же + обычный индекс (MAGIC, ENTRY): 427 мс. То есть НЕ помогает вообще.
Он же + покрывающий индекс (MAGIC, ENTRY, PROFIT, SWAP, COMMISSION): 80 мс.

Для полного GROUP BY обычный индекс бесполезен — таблица всё равно читается целиком, план SCAN ... USING INDEX это тот же скан. Нужно, чтобы ВСЕ колонки запроса лежали в индексе, тогда план становится SEARCH ... USING COVERING INDEX и до строк таблицы дело не доходит. Вот тогда ×5.

А где индекс реально спасает — это выборки по одному символу, которые панель дёргает при каждой перерисовке: 20 запросов WHERE SYMBOL=? AND ENTRY=1 — 711 мс без индекса против 208 мс с индексом.

3) Про массив структур. По сути я прав, но если писать свой класс обвязку с нужными индексами и нужными методами. SQLite конечно сократит время разработки в ущерб производительности и ресурсопотребления.

Чтение 45.8 МБ бинарника целиком: 25 мс.
Один проход, агрегаты по магикам И по символам сразу: 7 мс.
Для сравнения — выгрузка тех же 500k строк из SQLite в массив структур (цикл DatabaseReadBind): 220 мс.

Выигрыш реальный — в 4–18 раз в зависимости от операции. И 220 мс против 25 мс цифра показательная: если статистику всё равно считать в MQL5, база в этом сценарии работает просто как медленный формат файла.

Но база на диске 84 МБ против 46 МБ бинарника — и за эти лишние 38 МБ вы получаете произвольные фильтры, сортировки, пагинацию и любые новые отчёты бесплатно. В массиве структур их нет, пока не напишете руками. Так что «не нужна никакая база данных» — верно ровно до того момента, пока не понадобился запрос, которого вы не предусмотрели заранее. Enrique тут прав: если данные нужно ЗАПРАШИВАТЬ, а не просто загрузить — SQL вне конкуренции.

4) Про PostgreSQL забираю слова назад.

Он клиент-серверный, его нельзя встроить: отдельный процесс, установка, порты, админство. Для однопользовательского терминала в песочнице это архитектурно не лезет. А для локальной аналитики SQLite часто ещё и быстрее — нет IPC и round-trip'ов. Аргумент про JsonB тоже протух: JSONB в SQLite есть с 3.45, а для истории сделок JSON вообще не нужен, там строго типизированные колонки.

Итого

Основная претензия к статье — к схеме и коду, а не к движку. Разрыв между «SQLite как в статье» и «SQLite сделанный правильно» — сотня раз. Разрыв между правильным SQLite и массивом структур — единицы раз.

И самое дельное в ветке сказал 92746290: не перезаливать историю целиком, а догружать с последней зарегистрированной сделки. Это чинит проблему независимо от того, бинарник у вас или база.

Схему с покрывающими индексами, батчевой вставкой и инкрементальным Sync() плюс версию на массиве структур могу выложить, если интересно.

Повторюсь: Сам конечно использую легковесные классы с индексами и нужными методами без всяких БД, которые дают явное преимущество в ресурсозатратности и производительности. 
 
Nikolai Semko #:
Поспешил с суждениями, не копнув глубоко в суть. Прошу прощения — про «игрушку для студентов» я загнул, SQLite такого не заслужил.

 Наверное не для студентов, но всё-же игрушка. Ведь перед тем как использовать SQLite надо всю историю «перелопатить» и загнать в таблицу поэлементно. И на это уйдёт уйма времени. Если уж прикручивать это к MQL5, то и чтение истории ордеров и сделок надо делать напрямую в таблицу… ИМХО

 
Nikolai Semko #:
Копнул поглубже (с помощью ИИ, Opus 5 — собрал стенд, сгенерил синтетику на 500 000 сделок, 20 символов, 20 магиков, прогнал замеры).

отвлечённо: интересно было-бы сравнение с MonetDB/e . Такая-же embedded server-less как SQLite, но по ряду причин на сложных запросах должна быть резко быстрее. Конечно при условии разумной схемы :-)

 
Maxim Kuznetsov #:

отвлечённо: интересно было-бы сравнение с MonetDB/e . Такая-же embedded server-less как SQLite, но по ряду причин на сложных запросах должна быть резко быстрее. Конечно при условии разумной схемы :-)

Возможно
Тоже об этом думал
Для массивов NOSQL лучше заточены
Надо попробовать. С ИИ сейчас это можно быстро проверить