Jump to content

Leaderboard


Popular Content

Showing most liked content since 12/24/2019 in all areas

  1. 1 point
    @Manimal testei usano o comando "VACUUM INTO" e melhorou demais a velcidade para criar o banco de dados, obrigado mais uma vez!
  2. 1 point
    Buenas! Sempre que falamos em clonar um banco em memória, nosso objetivo é melhorar o tempo de resposta para funções de massa, como grandes e complexas consultas por exemplo, que talvez ao serem efetuadas a partir do disco (BD original) possam resultar bem mais lentas para apresentar os resultados. Grandes alterações no banco como inserção em massa de dados, alterações ou exclusões também podem ocorrer. Então, ao clonarmos o BD para a memória, temos que ter em mente que eventuais alterações feitas na memória podem ter 2 (dois) destinos: são ignoradas, ou seja o BD serve apenas para SELECTs e o que vale é o BD em disco; precisam ser salvas, ou seja, em algum momento, precisam ser descarregadas/efetivadas/replicadas em disco. Na opção 1, o problema está resolvido. Ignora-se o BD em memória e tudo bem! Na opção 2 o buraco é bem mais embaixo. Aqui temos novamente 2 (duas) possibilidades: efetivamos as alterações à medida que acontecem! Pessoalmente é a que eu utilizo por algumas razões: mantenho o BD em memória igual ao BD no disco (sincronização); caso ocorra alguma falha no equipamento (reset, falta de luz, travamento, etc) as alterações estão seguras; ao iniciar o script, carrego novamente o BD em memória, sabendo que é a última versão das informações e parto disto; não preciso me preocupar em descarregar as alterações posteriormente (no final do programa ou em algum ponto definido) e neste momento qualquer ganho de tempo que eu tive, foi por água abaixo, pois o tempo de gravação em disco de todas as alterações é enorme. Como fazemos isso? Após a clonagem do BD em memória, qualquer alteração ao ser executada, deve ser feita tanto em memória como em disco. #include <Sqlite.au3> ; incializa SQLite _SQLite_Startup() ; Abre BD em mmória Local $hBD_Mem = _SQLite_Open() ; Abre BD em disco Local $hBD_Disco = _SQLite_Open(@ScriptDir & "\BancoDeDados.db") ; ... ; Faz a clonagem conforme as técnicas explicadas em post anterior ; ... ; faz as eventuais alterações no BD mem e no BD disco _SQLite_Exec($hBD_Mem, "UPDATE Tabela SET Estado = "SC" WHERE Codigo = 425;") _SQLite_Exec($hBD_Disco, "UPDATE Tabela SET Estado = "SC" WHERE Codigo = 425;") ; faz as eventuais alterações no BD mem e no BD disco _SQLite_Exec($hBD_Mem, "DELETE FROM Tabela WHERE Idade < 18;") _SQLite_Exec($hBD_Disco, "DELETE FROM Tabela WHERE Idade < 18;") ; fecha tudo _SQLite_Close() _SQLite_Shutdown() Desta forma, mantemos os dois bancos de dados iguais e atualizados. E quaisquer consultas (SELECTs) devem ser feitos diretamente no BD em memória para obter um ganho considerável de velocidade! A outra possibilidade envolve não manter os 2 (dois) bancos equiparados ou sincronizados, mas fazer as alterações somente em memória e depois de tudo pronto, descarregar o BD da memória em disco. Este procedimento pode ser feito a qualquer momento, mas normalmente é efetivado na saída do programa (final do script). Para tanto, infelizmente não há um comando ou comandos que possam fazer isto rapidamente. Felizmente a partir da versão 3.6.x do SQLite, foi implemntadado a API de Backup, que permite fazer cópia do banco "on-the-fly" (com o banco aberto e operando). No fórum americano, tem um tópico sobre isto (cortesia do Belini que achou) e também tem uma função para fazer o backup: Se quiser ver o tópico original = https://www.autoitscript.com/forum/topic/108151-sqlite-backup-api-wrapper/ Vou anexar aqui uma versão modificada da original, já contendo as alterações sugeridas pelos integrantes do fórum naquele tópico e com algumas modificações minhas também. Para utilizar a função de Backup é bem simples. Segue exemplo: #include <Sqlite.au3> #include "sqlitebackup.au3" ; incializa SQLite _SQLite_Startup() ; Abre BD em mmória Local $hBD_Mem = _SQLite_Open() ; Abre BD em disco Local $hBD_Disco = _SQLite_Open(@ScriptDir & "\BancoDeDados.db") ; ... ; Faz a clonagem conforme as técnicas explicadas em post anterior ; ... ; faz as eventuais alterações SOMENTE na memória _SQLite_Exec($hBD_Mem, "UPDATE Tabela SET Estado = "SC" WHERE Codigo = 425;") ; faz as eventuais alterações SOMENTE na memória _SQLite_Exec($hBD_Mem, "DELETE FROM Tabela WHERE Idade < 18;") ; faz o backup do BD em memória de volta para o disco (recomendado ao final do script) _SQLite_Backup($hBD_Mem, @ScriptDir & "\BancoDeDadosCOPIA.db") ; fecha tudo _SQLite_Close() _SQLite_Shutdown() Mas conversando com um outro colega (meu ex-orientandor de mestrado) que é DBA, ele me comentou que alguns engines DBs aproveitam comandos de manutenção do banco (que exigem controle total sobre o mesmo) para efetivar algum tipo de cópia. Assim, fui pesquisar na documentação do SQLite e o comando VACUUM, que serve para fazer uma lmpeza interna do banco, a partir da versão 3.27 possui uma cláusula INTO que faz exatamente isto! Agora temos 2 (duas) opções de salvar o banco de dados da memória em disco. Faca os testes e veja qual a melhor (ou a mais rápida) que serve para o seu caso. A vantagem é que não precisa de uma função externa. #include <Sqlite.au3> ; incializa SQLite _SQLite_Startup() ; Abre BD em mmória Local $hBD_Mem = _SQLite_Open() ; Abre BD em disco Local $hBD_Disco = _SQLite_Open(@ScriptDir & "\BancoDeDados.db") ; ... ; Faz a clonagem conforme as técnicas explicadas em post anterior ; ... ; faz as eventuais alterações SOMENTE na memória _SQLite_Exec($hBD_Mem, "UPDATE Tabela SET Estado = "SC" WHERE Codigo = 425;") ; faz as eventuais alterações SOMENTE na memória _SQLite_Exec($hBD_Mem, "DELETE FROM Tabela WHERE Idade < 18;") ; faz o backup do BD em memória de volta para o disco (recomendado ao final do script) aproveitando o comando interno VACUUM _SQLite_Exec($hBD_Mem, "VACUUM INTO '" & @ScriptDir & "\BancoDeDadosCOPIA.db'") ; fecha tudo _SQLite_Close() _SQLite_Shutdown() Quanto à eficiência de gravação de volta em disco, temos que lembrar que estas funções, tanto a do SQLite como a do backup da SQLite, foram desenvolvidas tendo em mente uqe estes bancos estariam abertos, sendo utilizados por mais de 1 (um) usuário, portanto durante o procedimento de fazer a cópia, é possível que haja alterações por parte de outros usuários, sendo assim, a cópia já nasceria desatualizada. A API do Backup prevê isso e se necessário, recomeça a cópia par refletir estas alterações. Porém naturalmente que dependendo da quantidade de usuários conectados ou das alterações que estão sendo feitas, a cópia pode demorar eternamente! Outro ponto interessante a ser verificado é que o 5o (quinto) parâmetro da função de Backup é o tamanho do bloco que deve ser copiado. E por tamanho do bloco, temos que olhar a estrutura interna do banco de dados para entendermos melhor este parâmetro e o porque da fixação dele em 16. Todo banco de dados, internamente, possui as informações gravadas em blocos como se fossem páginas de um livro. Dentro da página tem as várias informações de vários registros. O procedimento de backup faz cópia de "x" folhas por vez (padrão de 16). Assim caso alguma dessas folhas sejam modificadas, ela recopia somente estas folhas que estão no bloco. Em teoria, quanto menor este bloco melhor, pois estaríamos reduzindo a recópia (se necessário), porém ao reduzirmos o tamanho do bloco, também aumentamos o tempo necessário para copiar tudo. Assim, aumentar o tamanho do bloco faz com que a cópia seja mais rápida, mas mais sujeita a recópias. Dependendo da situação, e eu estou imaginando que em 90% (ou mais) dos casos de SQLIte com AutoIt, os bancos são praticamente exclusivos, não tem niguém além do próprio script mexendo e também não há vários scripts rodando simultameamente na rede. Se for este o seu caso, pode aumentar o nro de blocos para 256 para obter uma melhor performance na cópia do banco ou até mesmo colocar o valor de -1, para que seja usada a velocidade máxima. Mas muito cuidado com estes parâmetros. Eles devem ser cuidadosamente considerados em razão do ambiente em que o banco de dados está sendo executado. _SQLite_Backup($hBD_Mem, $sCopiaBD, Default, Default, 256) ou _SQLite_Backup($hBD_Mem, $sCopiaBD, Default, Default, -1) SQLitebackup.au3
×