Meu primeiro dicionário me deu um susto: o painel do D1 marcou 4 bilhões de linhas lidas em um único dia. Até então, eu prestava mais atenção às tabelas e aos índices sugeridos pela IA do que ao caminho que cada consulta fazia pelo banco. Quando montei o Aprender Palavras com 48 idiomas, a URL precisava chegar à mesma palavra mesmo quando a tradução mudava.
A IA ajuda a montar o banco; a consulta ainda precisa ser medida
Eu gosto de criar sites com IA porque consigo desenhar o banco SQL do jeito que o projeto pede: escolher tabelas, colunas e índices. A IA também sugere caminhos, mas isso não garante que a consulta vá ler pouco. No meu primeiro dicionário, buscas e paginação examinavam muito mais registros do que eu esperava, mesmo com uma estrutura que parecia bem montada.
A cobrança considera as linhas que a consulta examina, mesmo quando devolve só uma ou duas. Uma busca sem índice adequado pode percorrer a tabela inteira para encontrar um termo. Foi aí que percebi que revisar o desenho das tabelas não bastava: eu precisava conferir as consultas e observar as leituras no painel.
Os limites também ajudam a colocar o número em perspectiva. Na tabela atual do D1, o Workers Free inclui 5 milhões de linhas lidas por dia; no Workers Paid, os primeiros 25 bilhões por mês estão incluídos e o excedente custa US$ 0,001 por milhão de linhas. Nesse preço, outras 25 bilhões de leituras custariam US$ 25. A tabela pode mudar, então confira os valores publicados antes de estimar o gasto do seu projeto.
Na busca, troquei varreduras por uma chave que eu conhecia
No padrão daquele primeiro projeto, eu parei de usar `LIKE` para encontrar uma palavra e `OFFSET` para avançar em listas compridas. Uma busca textual com curinga pode examinar muitos registros; o `OFFSET` faz o banco percorrer e descartar resultados anteriores à página pedida. Para a palavra exata que eu conheço, preferi consultar pelo ID ou por igualdade numa coluna indexada.
A recomendação vale para o tipo de busca que eu estava construindo. Se o leitor precisa procurar um trecho no meio de uma palavra ou pular páginas grandes de resultados, é melhor medir o plano da consulta do que copiar uma regra sem olhar para o caso concreto. No D1, dá para usar `EXPLAIN QUERY PLAN` para ver se a busca aproveita o índice que deveria.
O mesmo ID encontra o verbete em qualquer idioma
O Aprender Palavras reúne 48 idiomas, inclusive Klingon, alternativas de tradução, frases e pronúncia feita pela voz disponível no navegador. A interface usa o idioma selecionado para decidir qual versão mostrar como principal. Uma palavra pode mudar completamente de escrita entre dois idiomas, então a tradução da URL não é uma chave confiável para localizar a entrada.
Eu coloquei o ID do verbete no endereço junto do texto legível. A consulta encontra a linha pelo ID, e o idioma da página determina qual coluna exibir como tradução principal. Se o trecho da palavra no endereço variar, a busca continua chegando ao mesmo registro. Para cada verbete, mantive as traduções na mesma linha em vez de cadastrar 48 linhas separadas.
A tabela de palavras guarda essas versões; frases ficam numa tabela própria. São duas tabelas principais. A linha de uma palavra acabou com mais de 50 colunas, mas isso não multiplica as linhas lidas: o contador do D1 mede os registros examinados, não uma leitura separada para cada coluna. Ainda é preciso considerar tamanho armazenado e manutenção; a estrutura larga fazia sentido para as palavras curtas daquele dicionário, não como receita para qualquer banco.
As palavras relacionadas consultam outros IDs
Eu não criei uma terceira tabela só para as ligações. Na própria linha da palavra, guardei os IDs das palavras relacionadas e das frases relacionadas, separados por vírgula. Ao abrir a página, o site lê esses IDs e busca cada registro diretamente. As relações fazem consultas extras, mas não precisam vasculhar todas as traduções para descobrir quais palavras mostrar.
Naquele momento, o dicionário tinha por volta de 500 ou 600 palavras. Essa lista simples resolvia o caso e me deixava trabalhar com as duas tabelas que eu já tinha. Se as relações aumentarem muito ou precisarem ser alteradas com frequência, uma tabela de ligação pode ser mais fácil de manter do que uma lista de IDs separada por vírgulas. Eu aceito essa troca porque o catálogo ainda era pequeno.
A consulta principal lê uma linha; a página inteira soma outras
Quando conferi as últimas 24 horas no painel, o banco tinha lido perto de 1 milhão de linhas para 21 mil solicitações. Dividindo os números, dá cerca de 47 linhas lidas por solicitação. A consulta principal busca o verbete pelo ID e encontra uma linha; as relações puxam outras palavras e frases. Por isso, uma leitura na busca principal não significa que toda a página faz apenas uma leitura.
O volume ainda estava muito longe dos 4 bilhões do meu primeiro dicionário, mas o Aprender Palavras também tinha poucas centenas de entradas e pouco tráfego. Esses dados descrevem aquele catálogo naquele momento. Eles me ajudaram a ver o que cada visita fazia com o banco; não são uma previsão para milhões de palavras ou para um site com muito mais acessos.
Escolhi o D1 para cuidar do banco junto com o site
Eu preferi manter o site e o D1 na Cloudflare e acessar o banco pelo Wrangler. Assim, não precisei configurar uma VPS, instalar um painel como o phpMyAdmin nem cuidar de uma hospedagem separada só para esse banco. Para mim, já era mais simples administrar as ferramentas do projeto no mesmo lugar.
Se você preferir um servidor próprio, pode escolher outro banco e cuidar da infraestrutura diretamente. No meu caso, a estrutura do dicionário foi uma decisão bem específica: uma linha por palavra, todas as traduções juntas, IDs para encontrar o registro e relações simples enquanto o catálogo era pequeno. O aprendizado que eu levo para outro projeto é medir a consulta real, porque a sugestão inicial da IA não me protegeu daqueles 4 bilhões de leituras.