Otimizando consultas com dbQuery assíncrono
Um dos motivos mais comuns de "congelamentos" em servidores de MTA é o banco de dados sendo consultado de forma síncrona. Enquanto o servidor espera a resposta, o jogo inteiro para.
O problema: dbPoll com -1
-- trava o servidor até a consulta terminar
local qh = dbQuery(db, "SELECT * FROM contas WHERE usuario = ?", usuario)
local resultado = dbPoll(qh, -1)
O -1 faz o servidor esperar pelo resultado. Com o banco rápido e pouca gente, passa despercebido. Com muitos jogadores ou uma consulta lenta, gera picos de lag para todos.
A solução: callback
dbQuery(function(qh, jogador)
local resultado = dbPoll(qh, 0)
if not isElement(jogador) then return end -- jogador saiu enquanto esperava
if not resultado then
return outputDebugString("Erro na consulta de login", 1)
end
processarLogin(jogador, resultado[1])
end, {jogador}, db, "SELECT * FROM contas WHERE usuario = ?", usuario)
- O servidor continua rodando enquanto a consulta acontece;
- Quando termina, a função é chamada com o resultado;
- Argumentos extras (como o jogador) são passados em uma tabela;
- Sempre verifique se o jogador ainda existe no callback.
Escritas sem resposta: dbExec
Para INSERT, UPDATE e DELETE em que você não precisa do retorno:
dbExec(db, "UPDATE personagens SET dinheiro = ? WHERE id = ?", dinheiro, id)
Índices
Consultas lentas geralmente são falta de índice. Se você busca por usuario, conta_id ou dono, essas colunas precisam de índice:
CREATE INDEX idx_veiculos_dono ON veiculos (dono);
Busque só o necessário
-- ruim
SELECT * FROM personagens;
-- bom
SELECT id, nome, dinheiro FROM personagens WHERE conta_id = ?;
Use LIMIT em listagens e rankings.
Evite consultas em loop
-- ruim: uma consulta por jogador
for _, jogador in ipairs(getElementsByType("player")) do
dbExec(db, "UPDATE ... WHERE id = ?", ...)
end
Prefira:
- Dados em memória, salvos periodicamente;
- Consultas agrupadas quando possível;
- Espalhar salvamentos ao longo do tempo (não todos no mesmo segundo).
Cache
Dados que mudam pouco (preços de lojas, configurações, lista de casas) podem ser carregados uma vez no início do resource e mantidos em memória.
Hospede seu servidor com a VittHost
Todos os planos MTASA-BR da VittHost incluem 1 banco MySQL. Servidores no Brasil, painel Pterodactyl, proteção DDoS, downloads acelerados por nginx dedicado e teste grátis de 3 dias.