Como configurar índices e manutenção do banco no MU Online
Crie os índices certos nas tabelas do MuOnline e monte uma rotina de manutenção (rebuild, reorganize, update statistics) para o banco continuar rápido mesmo com o servidor lotado por meses.
Um banco MuOnline recém-restaurado é rápido. O mesmo banco depois de três meses de servidor cheio — milhões de saves de posição, inventários alterados o dia todo, logs de evento acumulados — fica lento se ninguém cuidar dos índices. As tabelas ficam fragmentadas, as estatísticas envelhecem e consult
Um banco MuOnline recém-restaurado é rápido. O mesmo banco depois de três meses de servidor cheio — milhões de saves de posição, inventários alterados o dia todo, logs de evento acumulados — fica lento se ninguém cuidar dos índices. As tabelas ficam fragmentadas, as estatísticas envelhecem e consultas que antes voavam começam a varrer a tabela inteira. O resultado é aquele login que demora e o save que atrasa mesmo com o VPS folgado de CPU. A solução tem duas frentes: criar os índices certos nas tabelas que o MU consulta o tempo todo e montar uma rotina de manutenção que reconstrói índices e atualiza estatísticas automaticamente. Este guia cobre as duas. Nomes de tabela, colunas e limites numéricos aqui são exemplos que variam por versão do MuServer e do SQL — o método é o mesmo.
Pré-requisitos
- Banco
MuOnlinerestaurado e em produção (ou um clone de teste para praticar); - SQL Server Management Studio (SSMS) e login com permissão
db_ownerousysadmin; - Backup completo e recente antes de mexer em índices;
- Uma janela de manutenção definida (horário de menor movimento do servidor);
- Noção de quais consultas o seu servidor mais faz (login, ranking, save) — isso guia quais índices criar.
Antes de criar qualquer índice, entenda as tabelas centrais do banco MuOnline. As mais consultadas costumam ser:
| Tabela (exemplo) | Consulta típica | Coluna-chave de busca |
|---|---|---|
MEMB_INFO | Login por conta | memb___id (login) |
Character | Carregar personagem | Name, AccountID |
Guild / GuildMember | Montar guild ao logar | G_Name, Name |
warehouse / Inventory | Baú e itens | AccountID / Name |
| Tabelas de ranking/evento | Ranking do site | colunas de pontuação |
WHERE, JOIN e ORDER BY das consultas mais frequentes, não todas as colunas.Passo 1 — Medir a fragmentação atual
Comece diagnosticando. A consulta abaixo lista os índices do banco e o quanto cada um está fragmentado — é o que decide se você vai fazer rebuild, reorganize ou nada:
USE MuOnline;
SELECT
OBJECT_NAME(ips.object_id) AS Tabela,
i.name AS Indice,
ips.avg_fragmentation_in_percent AS FragPct,
ips.page_count AS Paginas
FROM sys.dm_db_index_physical_stats(DB_ID('MuOnline'), NULL, NULL, NULL, 'LIMITED') ips
JOIN sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
WHERE ips.page_count > 100 -- ignorar índices minúsculos
AND i.name IS NOT NULL
ORDER BY ips.avg_fragmentation_in_percent DESC;
A coluna FragPct guia a ação. Índices com poucas páginas (tabelas pequenas) não valem manutenção — a reconstrução não muda nada perceptível. Foque nas tabelas grandes e voláteis.
| Fragmentação (FragPct) | Ação recomendada |
|---|---|
| Abaixo de ~10% | Não fazer nada |
| Entre ~10% e ~30% | REORGANIZE (leve, online) |
| Acima de ~30% | REBUILD (pesado, reconstrói) |
Passo 2 — Identificar índices que faltam
O SQL Server registra sugestões de índices que teriam ajudado consultas recentes. Elas são um ótimo ponto de partida para saber onde criar:
SELECT TOP 15
OBJECT_NAME(mid.object_id) AS Tabela,
migs.avg_user_impact AS ImpactoPct,
migs.user_seeks + migs.user_scans AS Usos,
mid.equality_columns AS ColunasIgualdade,
mid.inequality_columns AS ColunasDesigualdade,
mid.included_columns AS ColunasIncluidas
FROM sys.dm_db_missing_index_details mid
JOIN sys.dm_db_missing_index_groups mig ON mid.index_handle = mig.index_handle
JOIN sys.dm_db_missing_index_group_stats migs ON mig.index_group_handle = migs.group_handle
WHERE mid.database_id = DB_ID('MuOnline')
ORDER BY migs.avg_user_impact * (migs.user_seeks + migs.user_scans) DESC;
Priorize sugestões com alto impacto E muitos usos — um índice que ajudaria 90% mas nunca é usado não vale o custo de escrita. Trate as sugestões como pista, não ordem: o SQL às vezes sugere índices sobrepostos.
Passo 3 — Criar índices com critério
Com o diagnóstico em mãos, crie índices nas colunas que o MU realmente busca. Exemplos comuns (nomes de tabela/coluna variam por versão):
-- Login: busca por conta em MEMB_INFO
CREATE NONCLUSTERED INDEX IX_MEMB_INFO_id
ON MEMB_INFO (memb___id);
-- Carregar personagens de uma conta
CREATE NONCLUSTERED INDEX IX_Character_Account
ON Character (AccountID)
INCLUDE (Name, cLevel, Class); -- colunas incluídas evitam voltar à tabela
-- Buscar personagem por nome (usado em comandos e ranking)
CREATE NONCLUSTERED INDEX IX_Character_Name
ON Character (Name);
-- Membros de uma guild
CREATE NONCLUSTERED INDEX IX_GuildMember_Guild
ON GuildMember (G_Name);
O INCLUDE é uma técnica poderosa: ele guarda colunas extras no índice para que a consulta responda sem voltar à tabela principal (um "covering index"). Use nas colunas que a consulta retorna mas não filtra.
SELECT i.name, c.name FROM sys.indexes i JOIN sys.index_columns ic ON i.object_id=ic.object_id AND i.index_id=ic.index_id JOIN sys.columns c ON ic.object_id=c.object_id AND ic.column_id=c.column_id WHERE i.object_id = OBJECT_ID('Character');Passo 4 — Reorganizar e reconstruir índices
Agora a manutenção em si. REORGANIZE desfragmenta suavemente e é sempre online (não bloqueia). REBUILD reconstrói do zero — mais eficaz, porém mais pesado e, nas edições Standard/Express, bloqueia a tabela enquanto roda.
-- REORGANIZE: fragmentação moderada (~10% a 30%)
ALTER INDEX IX_Character_Account ON Character REORGANIZE;
-- REBUILD: fragmentação alta (>30%)
ALTER INDEX IX_Character_Account ON Character REBUILD;
-- REBUILD de TODOS os índices de uma tabela
ALTER INDEX ALL ON Character REBUILD;
-- REBUILD ONLINE (só Enterprise/Developer; não trava a tabela)
ALTER INDEX ALL ON Character REBUILD WITH (ONLINE = ON);
Após REBUILD, as estatísticas daquele índice já saem atualizadas. Após REORGANIZE, não — por isso o próximo passo (atualizar estatísticas) é parte obrigatória da rotina.
Character com o servidor cheio congela login e save de todo mundo. Faça sempre em janela de manutenção, com o servidor vazio ou em aviso.Passo 5 — Atualizar estatísticas
Estatísticas dizem ao otimizador como os dados estão distribuídos. Velhas, elas levam o SQL a planos ruins mesmo com índices perfeitos. Atualize na mesma janela de manutenção:
-- Atualizar estatísticas de todo o banco
USE MuOnline;
EXEC sp_updatestats;
-- Ou de uma tabela específica, com varredura completa (mais preciso)
UPDATE STATISTICS Character WITH FULLSCAN;
sp_updatestats é prático para a rotina geral; WITH FULLSCAN numa tabela crítica dá a estatística mais precisa ao custo de ler tudo. Combine: rotina geral com sp_updatestats, mais FULLSCAN nas duas ou três tabelas mais consultadas.
Passo 6 — Montar um script de manutenção inteligente
Rodar rebuild em tudo, sempre, é desperdício e trava demais. O ideal é um script que decide por índice conforme a fragmentação. Este cursor faz exatamente isso:
-- Manutenção inteligente: reorganize ou rebuild conforme a fragmentação
USE MuOnline;
DECLARE @tabela NVARCHAR(200), @indice NVARCHAR(200), @frag FLOAT, @sql NVARCHAR(MAX);
DECLARE cur CURSOR FOR
SELECT OBJECT_NAME(ips.object_id), i.name, ips.avg_fragmentation_in_percent
FROM sys.dm_db_index_physical_stats(DB_ID('MuOnline'), NULL, NULL, NULL, 'LIMITED') ips
JOIN sys.indexes i ON ips.object_id = i.object_id AND ips.index_id = i.index_id
WHERE ips.page_count > 100 AND i.name IS NOT NULL
AND ips.avg_fragmentation_in_percent > 10;
OPEN cur;
FETCH NEXT FROM cur INTO @tabela, @indice, @frag;
WHILE @@FETCH_STATUS = 0
BEGIN
IF @frag > 30
SET @sql = 'ALTER INDEX [' + @indice + '] ON [' + @tabela + '] REBUILD;';
ELSE
SET @sql = 'ALTER INDEX [' + @indice + '] ON [' + @tabela + '] REORGANIZE;';
PRINT @sql; -- registra o que vai rodar
EXEC sp_executesql @sql;
FETCH NEXT FROM cur INTO @tabela, @indice, @frag;
END
CLOSE cur; DEALLOCATE cur;
-- Fecha com atualização de estatísticas
EXEC sp_updatestats;
Esse script só toca no que passa de 10% de fragmentação, escolhe reorganize ou rebuild por índice e finaliza atualizando estatísticas. É a base da sua rotina automática.
Passo 7 — Agendar a manutenção com o SQL Server Agent
Coloque o script para rodar sozinho na janela de menor movimento (madrugada). No SSMS:
- Expanda SQL Server Agent → Jobs, clique com o direito → New Job...;
- Aba General: nome
Manutencao Indices MuOnline; - Aba Steps → New...: type
Transact-SQL, databaseMuOnline, cole o script do passo anterior; - Aba Schedules → New...:
Recurring,Weekly, num dia e hora de baixo movimento (ex.: domingo 05:00); - Aba Notifications: marque e-mail em caso de falha, se configurado;
- OK para salvar.
.sql chamado por sqlcmd dentro de um .bat, agendado pelo Agendador de Tarefas do Windows — mesmo princípio dos backups automáticos.Passo 8 — Verificar integridade do banco (DBCC CHECKDB)
Manutenção de índice não detecta corrupção. Rode DBCC CHECKDB periodicamente para garantir que o banco está fisicamente saudável — de nada adianta índice perfeito num banco corrompido:
-- Verificação completa de integridade (rodar em manutenção, é pesado)
DBCC CHECKDB('MuOnline') WITH NO_INFOMSGS, ALL_ERRORMSGS;
-- Esperado: "CHECKDB found 0 allocation errors and 0 consistency errors"
Se aparecerem erros de consistência, não saia usando REPAIR_ALLOW_DATA_LOSS por impulso — ele pode apagar dados. Restaure de um backup íntegro primeiro; reparo destrutivo é último recurso.
Passo 9 — Controlar o crescimento das tabelas de log
Muitos bancos de MU acumulam tabelas de log de eventos, cash, comandos, que só crescem. Elas incham o banco, a manutenção e o backup. Defina uma política de expurgo:
-- Exemplo: apagar logs de evento com mais de 90 dias (nome varia por versão)
DELETE FROM T_Event_Log WHERE LogDate < DATEADD(DAY, -90, GETDATE());
Adicione um expurgo assim à rotina semanal (com cuidado e backup antes), para o banco não crescer indefinidamente só de histórico.
Erros comuns e soluções
| Sintoma | Causa provável | Solução |
|---|---|---|
| Consultas lentas mesmo com CPU folgada | Índices fragmentados / estatísticas velhas | Rodar rotina de rebuild/reorganize + sp_updatestats |
| Login travou durante a madrugada | REBUILD offline no horário errado | Agendar para janela vazia ou usar REBUILD ONLINE |
| Escrita (save) ficou mais lenta após otimizar | Índices demais ou duplicados | Remover índices redundantes; manter só os úteis |
| Sugestões de índice zeradas | SQL reiniciou recentemente | Coletar após horas de carga real |
| Rebuild não melhorou nada | Índice pequeno / problema é outro | Focar tabelas grandes; investigar consulta específica |
| Banco crescendo sem parar | Tabelas de log acumulando | Política de expurgo periódico dos logs |
| Erro de consistência no CHECKDB | Corrupção física | Restaurar de backup íntegro, não reparar destrutivamente |
Checklist de lançamento
- Backup completo feito antes de mexer em índices
- Fragmentação atual medida com
dm_db_index_physical_stats - Índices ausentes sugeridos coletados após carga real e avaliados por impacto e uso
- Índices criados nas colunas de login, carga de personagem, guild e ranking
- Índices duplicados/redundantes verificados e removidos
- Script inteligente (reorganize vs rebuild por fragmentação) testado no clone
- Job semanal de manutenção agendado no SQL Server Agent (ou .bat via Agendador no Express)
- Atualização de estatísticas incluída ao fim da rotina
- DBCC CHECKDB agendado e retornando 0 erros
- Política de expurgo das tabelas de log definida
- Manutenção pesada confinada à janela de menor movimento
- Ganho de performance validado comparando antes/depois em consulta real
Com índices bem escolhidos e uma rotina de manutenção rodando sozinha toda semana, o banco MuOnline se mantém rápido mês após mês, mesmo com o servidor lotado e milhões de operações acumuladas. Junto do tuning de memória e tempdb e de uma boa política de backup, você fecha o tripé que sustenta um servidor estável e veloz do lançamento em diante.
Perguntas frequentes
O que é um índice no SQL Server?
É uma estrutura auxiliar que acelera buscas, como o índice de um livro. Em vez de varrer a tabela inteira para achar uma conta ou personagem, o SQL vai direto ao registro. Sem índice adequado, cada login lê a tabela toda — o que fica lento conforme a base cresce.
Índice demais é ruim?
Sim. Cada índice acelera leitura mas pesa na escrita, porque toda inserção/atualização precisa manter todos os índices. Em banco de MU, que escreve muito (save de posição, inventário), índices em excesso ou duplicados atrapalham. Crie só os que realmente ajudam consultas frequentes.
Rebuild ou reorganize, qual usar?
Depende da fragmentação. Como regra prática, abaixo de ~10% não faça nada, entre ~10% e 30% use REORGANIZE (mais leve, online), acima de 30% use REBUILD (mais pesado, reconstrói o índice). Os limites exatos variam por versão e tamanho da tabela.
Com que frequência rodar manutenção de índices?
Para servidores ativos, uma rotina semanal em horário de baixo movimento costuma bastar, somada a update de estatísticas mais frequente. Tabelas muito voláteis podem pedir manutenção mais amiúde. O ideal varia com o volume de escrita do servidor.
Manutenção de índice pode derrubar o servidor?
REBUILD offline bloqueia a tabela durante a operação, o que pode travar login e save se rodar no pico. Faça em janela de manutenção, com o servidor vazio ou avisado, ou use REBUILD com opção ONLINE nas edições que suportam.