Discussão do artigo "Recursos do SQLite em MQL5: Exemplo de painel interativo com estatísticas de trading por símbolo e magic" - página 2

 
SQLite: нативная работа с базами данных на SQL в MQL5
SQLite: нативная работа с базами данных на SQL в MQL5
  • 2020.02.18
  • www.mql5.com
Разработка торговых стратегий связана с обработкой больших объемов данных. Теперь прямо в MQL5 вы можете работать с базами данных с помощью SQL-запросов на основе SQLite. Важным преимуществом данного движка является то, что вся база данных содержится в единственном файле, который находится на компьютере пользователя.
 
Me precipitei nos julgamentos, sem aprofundar na essência da questão. Peço desculpas — exagerei ao chamar o SQLite de “brinquedo para estudantes”; ele não merecia isso.

Fui mais a fundo (com a ajuda de IA, o Opus 5 — montei um ambiente de teste, gerei dados sintéticos para 500 mil transações, 20 símbolos, 20 indicadores, e executei as medições). Eis o que se conclui.

1) Cinco minutos no fxsaber — isso quase com certeza NÃO é o SQLite.

INSERT de uma transação por vez com autocommit: ~245 segundos para 500 mil.
Os mesmos dados em lote dentro de uma única transação: 2,35 segundos.

Uma diferença de 104 vezes. 245 segundos — são exatamente esses mesmos “cinco minutos”. Cada inserção = uma transação separada com fsync. Resolve-se com duas linhas: DatabaseTransactionBegin() / DatabaseTransactionCommit(). Todo o resto nessa discussão, diante desse número, são pormenores.

2) Maxim está certo sobre os índices, mas não sobre esses índices.

Consulta do artigo, esquema sem índices: 395 ms.
A mesma consulta + um índice comum (MAGIC, ENTRY): 427 ms. Ou seja, NÃO ajuda em nada.
O mesmo + índice abrangente (MAGIC, ENTRY, PROFIT, SWAP, COMMISSION): 80 ms.

Para um GROUP BY completo, o índice comum é inútil — a tabela ainda é lida na íntegra; o plano SCAN ... USING INDEX é o mesmo que uma varredura. É preciso que TODAS as colunas da consulta estejam no índice; só assim o plano se torna SEARCH ... USING COVERING INDEX e não chega a acessar as linhas da tabela. Aí sim, a velocidade aumenta em 5 vezes.

E onde o índice realmente faz a diferença — são as consultas por um único símbolo, que o painel atualiza a cada redesenho: 20 consultas WHERE SYMBOL=? AND ENTRY=1 — 711 ms sem índice contra 208 ms com índice.

3) Sobre o array de estruturas. No fundo, estou certo, mas se for escrever sua própria classe de interface com os índices e métodos necessários. O SQLite, é claro, reduzirá o tempo de desenvolvimento em detrimento do desempenho e do consumo de recursos.

Leitura de 45,8 MB do arquivo binário inteiro: 25 ms.
Uma única passagem, agregados por valores mágicos e por caracteres simultaneamente: 7 ms.
Para comparação — exportação das mesmas 500 mil linhas do SQLite para um array de estruturas (ciclo DatabaseReadBind): 220 ms.

A vantagem é real — de 4 a 18 vezes, dependendo da operação. E o número de 220 ms contra 25 ms é revelador: se as estatísticas forem calculadas no MQL5 de qualquer maneira, o banco de dados, nesse cenário, funciona simplesmente como um formato de arquivo lento.

Mas o banco de dados no disco ocupa 84 MB contra os 46 MB do arquivo binário — e, por esses 38 MB a mais, você obtém filtros arbitrários, ordenações, paginação e quaisquer novos relatórios sem custo adicional. No array de estruturas, esses recursos não existem, a menos que você os escreva manualmente. Portanto, a afirmação de que “não é necessário nenhum banco de dados” é verdadeira exatamente até o momento em que surge uma consulta que você não previu com antecedência. Enrique está certo: se for preciso CONSULTAR os dados, e não apenas carregá-los — o SQL não tem concorrência.

4) Retiro o que disse sobre o PostgreSQL.

Ele é cliente-servidor, não dá para integrá-lo: processo separado, instalação, portas, administração. Para um terminal de usuário único na sandbox, isso não se encaixa arquitetonicamente. E para análises locais, o SQLite costuma ser ainda mais rápido — sem IPC e sem round-trips. O argumento sobre o JSONB também não se sustenta: o JSONB está presente no SQLite desde a versão 3.45, e para o histórico de transações o JSON nem é necessário, pois lá as colunas são estritamente tipadas.

Conclusão

A principal crítica ao artigo é em relação ao esquema e ao código, e não ao mecanismo. A diferença entre o “SQLite como no artigo” e o “SQLite feito corretamente” é de centenas de vezes. A diferença entre o SQLite correto e um array de estruturas é de apenas algumas vezes.

E a observação mais pertinente no tópico foi feita por 92746290: não recarregar o histórico inteiro, mas sim carregar a partir da última transação registrada. Isso resolve o problema, independentemente de você estar usando um binário ou um banco de dados.

Posso compartilhar o esquema com índices de cobertura, inserção em lote e Sync() incremental, além da versão com matriz de estruturas, se houver interesse.

Repito: eu mesmo, é claro, uso classes leves com índices e métodos necessários, sem nenhum banco de dados, o que oferece uma vantagem clara em termos de consumo de recursos e desempenho.
 
Nikolai Semko #:
Me precipitei nos julgamentos, sem aprofundar na essência da questão. Peço desculpas — exagerei ao chamar o SQLite de “brinquedo para estudantes”; ele não merecia isso.

Talvez não seja para estudantes, mas ainda assim é um brinquedo. Afinal, antes de usar o SQLite, é preciso “revisar” todo o histórico e inserir os dados na tabela, um por um. E isso vai levar um tempão. Se já for integrar isso ao MQL5, então a leitura do histórico de ordens e transações também precisa ser feita diretamente na tabela… Na minha opinião

 
Nikolai Semko #:
Fiz uma análise mais aprofundada (com a ajuda da IA, Opus 5 — montei um ambiente de teste, gerei dados sintéticos para 500.000 transações, 20 símbolos, 20 indicadores, e executei os testes de desempenho).

Em termos gerais: seria interessante uma comparação com o MonetDB/e. É um banco de dados embutido sem servidor, assim como o SQLite, mas, por uma série de razões, deve ser significativamente mais rápido em consultas complexas. Claro, desde que o esquema seja razoável :-)

 
Maxim Kuznetsov #:

A título de reflexão: seria interessante fazer uma comparação com o MonetDB/e. É um banco de dados incorporado sem servidor, assim como o SQLite, mas, por uma série de motivos, deve ser significativamente mais rápido em consultas complexas. É claro, desde que o esquema seja bem projetado :-)

Talvez
Também pensei nisso
Para matrizes, o NoSQL é mais adequado
Vale a pena experimentar. Com IA, hoje em dia dá para verificar isso rapidamente