El mayor portal de MU Online de Brasil — desde 2003
Tutorial Avanzado Infraestructura

Cómo configurar índices y mantenimiento de la base de datos en MU Online

Crea los índices correctos en las tablas de MuOnline y arma una rutina de mantenimiento (rebuild, reorganize, update statistics) para que la base de datos siga rápida incluso con el servidor lleno durante meses.

BR Bruno · Actualizado el 10 jul 2026 · ⏱ 23 min de lectura
Respuesta rápida

Una base MuOnline recién restaurada es rápida. La misma base después de tres meses de servidor lleno —millones de guardados de posición, inventarios modificados todo el día, logs de eventos acumulados— se vuelve lenta si nadie cuida los índices. Las tablas se fragmentan, las estadísticas envejecen y

Una base MuOnline recién restaurada es rápida. La misma base después de tres meses de servidor lleno —millones de guardados de posición, inventarios modificados todo el día, logs de eventos acumulados— se vuelve lenta si nadie cuida los índices. Las tablas se fragmentan, las estadísticas envejecen y consultas que antes volaban empiezan a recorrer la tabla entera. El resultado es ese login que tarda y el guardado que se atrasa incluso con el VPS holgado de CPU. La solución tiene dos frentes: crear los índices correctos en las tablas que MU consulta a cada momento y armar una rutina de mantenimiento que reconstruya índices y actualice estadísticas automáticamente. Esta guía cubre ambos. Los nombres de tabla, columnas y límites numéricos aquí son ejemplos que varían según la versión del MuServer y del SQL: el método es el mismo.

Nota: Si todavía estás armando el servidor, empieza por cómo crear un servidor de MU Online. Los índices y el mantenimiento son pasos de refinamiento para cuando la base ya está de pie y recibiendo jugadores.

Requisitos previos

  • Base MuOnline restaurada y en producción (o un clon de prueba para practicar);
  • SQL Server Management Studio (SSMS) y un login con permiso db_owner o sysadmin;
  • Backup completo y reciente antes de tocar los índices;
  • Una ventana de mantenimiento definida (horario de menor movimiento del servidor);
  • Noción de qué consultas hace más tu servidor (login, ranking, guardado): eso guía qué índices crear.

Antes de crear cualquier índice, entiende las tablas centrales de la base MuOnline. Las más consultadas suelen ser:

Tabla (ejemplo)Consulta típicaColumna clave de búsqueda
MEMB_INFOLogin por cuentamemb___id (login)
CharacterCargar personajeName, AccountID
Guild / GuildMemberArmar el guild al loguearG_Name, Name
warehouse / InventoryBaúl e ítemsAccountID / Name
Tablas de ranking/eventoRanking del sitiocolumnas de puntuación
Atenção: No te pongas a crear un índice en cada columna. Cada índice extra vuelve más lentas las escrituras, y MU escribe mucho. El objetivo son las columnas usadas en WHERE, JOIN y ORDER BY de las consultas más frecuentes, no todas las columnas.

Paso 1 — Medir la fragmentación actual

Empieza diagnosticando. La consulta de abajo lista los índices de la base y cuánto está fragmentado cada uno: es lo que decide si vas a hacer rebuild, reorganize o nada:

USE MuOnline;

SELECT
    OBJECT_NAME(ips.object_id) AS Tabla,
    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;

La columna FragPct guía la acción. Los índices con pocas páginas (tablas pequeñas) no valen el mantenimiento: la reconstrucción no cambia nada perceptible. Concéntrate en las tablas grandes y volátiles.

Fragmentación (FragPct)Acción recomendada
Por debajo de ~10%No hacer nada
Entre ~10% y ~30%REORGANIZE (ligero, online)
Por encima de ~30%REBUILD (pesado, reconstruye)
Dica: Estos límites (10% y 30%) son la recomendación clásica y sirven como punto de partida. Los servidores muy grandes a veces los ajustan, pero empieza por ellos: funcionan bien para la mayoría de las bases de MU.

Paso 2 — Identificar índices que faltan

SQL Server registra sugerencias de índices que habrían ayudado a consultas recientes. Son un excelente punto de partida para saber dónde crearlos:

SELECT TOP 15
    OBJECT_NAME(mid.object_id) AS Tabla,
    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;

Prioriza las sugerencias con alto impacto Y muchos usos: un índice que ayudaría al 90% pero nunca se usa no vale el costo de escritura. Trata las sugerencias como una pista, no como una orden: SQL a veces sugiere índices superpuestos.

Atenção: Estas estadísticas de índices ausentes se resetean cuando el servicio SQL reinicia. Recógelas después de que el servidor haya corrido bajo carga real por un tiempo (algunas horas de movimiento), no justo después de reiniciar.

Paso 3 — Crear índices con criterio

Con el diagnóstico en mano, crea índices en las columnas que MU realmente busca. Ejemplos comunes (los nombres de tabla/columna varían según la versión):

-- Login: búsqueda por cuenta en MEMB_INFO
CREATE NONCLUSTERED INDEX IX_MEMB_INFO_id
ON MEMB_INFO (memb___id);

-- Cargar personajes de una cuenta
CREATE NONCLUSTERED INDEX IX_Character_Account
ON Character (AccountID)
INCLUDE (Name, cLevel, Class);   -- las columnas incluidas evitan volver a la tabla

-- Buscar personaje por nombre (usado en comandos y ranking)
CREATE NONCLUSTERED INDEX IX_Character_Name
ON Character (Name);

-- Miembros de un guild
CREATE NONCLUSTERED INDEX IX_GuildMember_Guild
ON GuildMember (G_Name);

El INCLUDE es una técnica poderosa: guarda columnas extra en el índice para que la consulta responda sin volver a la tabla principal (un "covering index"). Úsalo en las columnas que la consulta devuelve pero no filtra.

Dica: Antes de crear, verifica que no exista ya un índice parecido. Los índices duplicados solo pesan en la escritura. Lista los existentes con: 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');

Paso 4 — Reorganizar y reconstruir índices

Ahora el mantenimiento en sí. REORGANIZE desfragmenta suavemente y siempre es online (no bloquea). REBUILD reconstruye desde cero: más eficaz, pero más pesado y, en las ediciones Standard/Express, bloquea la tabla mientras corre.

-- REORGANIZE: fragmentación moderada (~10% a 30%)
ALTER INDEX IX_Character_Account ON Character REORGANIZE;

-- REBUILD: fragmentación alta (>30%)
ALTER INDEX IX_Character_Account ON Character REBUILD;

-- REBUILD de TODOS los índices de una tabla
ALTER INDEX ALL ON Character REBUILD;

-- REBUILD ONLINE (solo Enterprise/Developer; no bloquea la tabla)
ALTER INDEX ALL ON Character REBUILD WITH (ONLINE = ON);

Tras un REBUILD, las estadísticas de ese índice ya quedan actualizadas. Tras un REORGANIZE, no: por eso el siguiente paso (actualizar estadísticas) es parte obligatoria de la rutina.

Atenção: El REBUILD offline bloquea la tabla durante la operación. Ejecutar eso en Character con el servidor lleno congela el login y el guardado de todo el mundo. Hazlo siempre en una ventana de mantenimiento, con el servidor vacío o con aviso.

Paso 5 — Actualizar estadísticas

Las estadísticas le dicen al optimizador cómo están distribuidos los datos. Si están viejas, llevan a SQL a planes malos incluso con índices perfectos. Actualízalas en la misma ventana de mantenimiento:

-- Actualizar estadísticas de toda la base
USE MuOnline;
EXEC sp_updatestats;

-- O de una tabla específica, con recorrido completo (más preciso)
UPDATE STATISTICS Character WITH FULLSCAN;

sp_updatestats es práctico para la rutina general; WITH FULLSCAN en una tabla crítica da la estadística más precisa al costo de leerlo todo. Combina: rutina general con sp_updatestats, más FULLSCAN en las dos o tres tablas más consultadas.

Paso 6 — Armar un script de mantenimiento inteligente

Ejecutar rebuild en todo, siempre, es un desperdicio y bloquea demasiado. Lo ideal es un script que decida por índice según la fragmentación. Este cursor hace exactamente eso:

-- Mantenimiento inteligente: reorganize o rebuild según la fragmentación
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 lo que se va a ejecutar
    EXEC sp_executesql @sql;
    FETCH NEXT FROM cur INTO @tabela, @indice, @frag;
END
CLOSE cur; DEALLOCATE cur;

-- Cierra con la actualización de estadísticas
EXEC sp_updatestats;

Este script solo toca lo que pasa del 10% de fragmentación, elige reorganize o rebuild por índice y finaliza actualizando estadísticas. Es la base de tu rutina automática.

Paso 7 — Agendar el mantenimiento con el SQL Server Agent

Pon el script a correr solo en la ventana de menor movimiento (la madrugada). En SSMS:

  1. Expande SQL Server Agent → Jobs, clic derecho → New Job...;
  2. Pestaña General: nombre Manutencao Indices MuOnline;
  3. Pestaña StepsNew...: type Transact-SQL, database MuOnline, pega el script del paso anterior;
  4. Pestaña SchedulesNew...: Recurring, Weekly, en un día y hora de bajo movimiento (ej.: domingo 05:00);
  5. Pestaña Notifications: marca el email en caso de falla, si está configurado;
  6. OK para guardar.
Nota: El SQL Server Agent no existe en la edición Express. En ese caso, usa un script .sql invocado por sqlcmd dentro de un .bat, agendado con el Programador de Tareas de Windows: el mismo principio de los backups automáticos.

Paso 8 — Verificar la integridad de la base (DBCC CHECKDB)

El mantenimiento de índices no detecta corrupción. Ejecuta DBCC CHECKDB periódicamente para garantizar que la base está físicamente sana: de nada sirve un índice perfecto en una base corrupta:

-- Verificación completa de integridad (ejecutar en mantenimiento, es pesado)
DBCC CHECKDB('MuOnline') WITH NO_INFOMSGS, ALL_ERRORMSGS;
-- Esperado: "CHECKDB found 0 allocation errors and 0 consistency errors"

Si aparecen errores de consistencia, no te pongas a usar REPAIR_ALLOW_DATA_LOSS por impulso: puede borrar datos. Restaura primero desde un backup íntegro; la reparación destructiva es el último recurso.

Paso 9 — Controlar el crecimiento de las tablas de log

Muchas bases de MU acumulan tablas de log de eventos, cash, comandos, que solo crecen. Inflan la base, el mantenimiento y el backup. Define una política de purga:

-- Ejemplo: borrar logs de evento con más de 90 días (el nombre varía según la versión)
DELETE FROM T_Event_Log WHERE LogDate < DATEADD(DAY, -90, GETDATE());

Agrega una purga así a la rutina semanal (con cuidado y backup previo), para que la base no crezca indefinidamente solo por historial.

Errores comunes y soluciones

SíntomaCausa probableSolución
Consultas lentas aun con CPU holgadaÍndices fragmentados / estadísticas viejasEjecutar la rutina de rebuild/reorganize + sp_updatestats
El login se trabó durante la madrugadaREBUILD offline en el horario equivocadoAgendar para la ventana vacía o usar REBUILD ONLINE
La escritura (guardado) se volvió más lenta tras optimizarDemasiados índices o duplicadosEliminar índices redundantes; mantener solo los útiles
Sugerencias de índice en ceroSQL reinició recientementeRecoger tras horas de carga real
El rebuild no mejoró nadaÍndice pequeño / el problema es otroEnfocar tablas grandes; investigar la consulta específica
La base crece sin pararTablas de log acumulándosePolítica de purga periódica de los logs
Error de consistencia en CHECKDBCorrupción físicaRestaurar desde backup íntegro, no reparar de forma destructiva

Lista de verificación de lanzamiento

  • Backup completo hecho antes de tocar los índices
  • Fragmentación actual medida con dm_db_index_physical_stats
  • Índices ausentes sugeridos, recogidos tras carga real y evaluados por impacto y uso
  • Índices creados en las columnas de login, carga de personaje, guild y ranking
  • Índices duplicados/redundantes verificados y eliminados
  • Script inteligente (reorganize vs rebuild por fragmentación) probado en el clon
  • Job semanal de mantenimiento agendado en el SQL Server Agent (o .bat vía Programador en Express)
  • Actualización de estadísticas incluida al final de la rutina
  • DBCC CHECKDB agendado y devolviendo 0 errores
  • Política de purga de las tablas de log definida
  • Mantenimiento pesado confinado a la ventana de menor movimiento
  • Ganancia de rendimiento validada comparando antes/después en una consulta real

Con índices bien elegidos y una rutina de mantenimiento corriendo sola cada semana, la base MuOnline se mantiene rápida mes tras mes, incluso con el servidor lleno y millones de operaciones acumuladas. Junto con el tuning de memoria y tempdb y una buena política de backup, cierras el trípode que sostiene un servidor estable y veloz desde el lanzamiento en adelante.

Preguntas frecuentes

¿Qué es un índice en SQL Server?

Es una estructura auxiliar que acelera las búsquedas, como el índice de un libro. En lugar de recorrer toda la tabla para encontrar una cuenta o un personaje, SQL va directo al registro. Sin un índice adecuado, cada login lee la tabla entera, lo que se vuelve lento a medida que crece la base.

¿Tener demasiados índices es malo?

Sí. Cada índice acelera la lectura pero pesa en la escritura, porque toda inserción o actualización necesita mantener todos los índices. En una base de MU, que escribe mucho (guardado de posición, inventario), los índices en exceso o duplicados estorban. Crea solo los que realmente ayudan a consultas frecuentes.

¿Rebuild o reorganize, cuál usar?

Depende de la fragmentación. Como regla práctica, por debajo de ~10% no hagas nada, entre ~10% y 30% usa REORGANIZE (más ligero, online), por encima de 30% usa REBUILD (más pesado, reconstruye el índice). Los límites exactos varían según la versión y el tamaño de la tabla.

¿Con qué frecuencia ejecutar el mantenimiento de índices?

Para servidores activos, una rutina semanal en horario de bajo movimiento suele bastar, sumada a una actualización de estadísticas más frecuente. Las tablas muy volátiles pueden requerir mantenimiento más seguido. Lo ideal varía según el volumen de escritura del servidor.

¿El mantenimiento de índices puede tumbar el servidor?

El REBUILD offline bloquea la tabla durante la operación, lo que puede trabar el login y el guardado si se ejecuta en el pico. Hazlo en una ventana de mantenimiento, con el servidor vacío o avisado, o usa REBUILD con la opción ONLINE en las ediciones que lo soportan.

BR
Editor de eventos, mapas e ítems

Bruno es especialista en eventos, mapas, bosses y economía de ítems de MU Online. Documenta cada detalle basándose en el juego real.

Sigue leyendo

Artículos relacionados