Como um mecanismo de banco de dados SQL geralmente funciona
- Todos os mecanismos de banco de dados SQL funcionam de forma parecida
- Convertem a instrução SQL recebida em uma "prepared statement"
- "Executam" a prepared statement para gerar o resultado
- No SQLite, uma prepared statement é representada como uma instância do objeto
sqlite3_stmt
- Há basicamente duas formas de representar uma prepared statement
- Método de bytecode: usado no SQLite
- Método de árvore de objetos: usado no MySQL e no PostgreSQL
Vantagens do método de bytecode
- É fácil de entender
- Consiste em uma sequência de instruções simples, o que facilita sua exibição
- Ao usar a palavra-chave
EXPLAIN, é possível verificar o bytecode da instrução SQL
- Facilita a depuração
- Separa claramente a etapa de parsing/análise da etapa de execução
- Em builds de depuração, é possível rastrear a execução do bytecode com o comando
PRAGMA vdbe_trace=ON
- Permite execução incremental
- Instruções SQL escritas em bytecode podem ser executadas linha por linha, interrompidas e retomadas
- No método de árvore de objetos, como a árvore inteira é executada de uma vez, a execução incremental é difícil
- Usa menos memória
- O bytecode é menor que uma AST
- Como prepared statements ficam em cache na memória por bastante tempo, o uso de memória é importante
- A velocidade de execução é alta
- Há menos decisões a serem tomadas em cada etapa, então a execução é mais rápida
Vantagens do método de árvore de objetos
- Permite modificar o plano de consulta em tempo de execução
- A árvore de objetos é fácil de alterar mesmo durante a execução
- É possível otimizar dinamicamente de acordo com o progresso da consulta
- É mais fácil de paralelizar
- Cada nó de processamento pode ser atribuído a uma thread separada
- Basta sincronizar apenas a transferência de dados entre os nós
- Isso é vantajoso ao executar consultas analíticas grandes (OLAP) em múltiplos núcleos
Opinião do GN⁺
- Como o principal objetivo do SQLite é o processamento de transações (OLTP) em ambientes de Internet das Coisas, o método de bytecode parece adequado. Isso porque ele pode oferecer desempenho rápido sendo simples e leve.
- Por outro lado, como MySQL e PostgreSQL também são muito usados para análise de grandes volumes de dados, as vantagens do método de árvore de objetos — que permite otimização dinâmica e paralelização do plano de execução da consulta — podem se destacar mais.
- No entanto, o método de árvore de objetos também tem a desvantagem de dificultar depuração e análise de desempenho. Além disso, por causa de fatores como o custo de percorrer a árvore, em consultas simples ele pode até ser mais lento que o bytecode.
- O ponto importante é escolher a abordagem adequada ao uso e ao objetivo. No caso de um RDBMS de uso geral, também vale considerar uma abordagem híbrida que combine os prós e contras dos dois métodos.
1 comentários
Comentário do Hacker News
O fato de o SQLite usar uma máquina virtual (VM) de bytecode em vez de uma árvore de sintaxe abstrata (AST) para executar consultas SQL é uma escolha de projeto interessante para um banco de dados. As vantagens do bytecode em relação à AST são as seguintes:
mallococulto/cabeçalhos de objeto e ponteiros para subexpressões.VMs de bytecode e interpretadores costumam ser associados a linguagens de programação de propósito geral, mas também podem ser surpreendentemente úteis em outros contextos, como:
O Microsoft SQL Server usa internamente árvores de objetos, mas a saída do plano de consulta ainda é em forma de tabela, o que mostra a dificuldade de renderizar árvores de objetos como tabelas.
Muitas vezes, os programadores sabem exatamente quais buscas em índices precisam acontecer dentro de um loop, então, em alguns casos, pode ser vantajoso escrever bytecode diretamente ou usar uma linguagem imperativa de mais alto nível em vez de SQL. Expressar isso em SQL pode ser um fardo.
Se o gargalo não estiver na execução do bytecode (por exemplo, velocidade de memória ou disco), talvez não seja realmente necessário convertê-lo em código nativo via compilação JIT.
Muitas linguagens de programação, como Python, Ruby e Lua, usam internamente bytecode ou AST. Devido a decisões de projeto de bancos de dados, instruções fáceis de analisar podem ser úteis para implementações de bibliotecas de terceiros ou ORMs propensas a erros.