Cómo optimizar SQL Server para muchos jugadores en MU Online
Ajusta la memoria, tempdb, el modelo de recuperación y la configuración de SQL Server para que la base MuOnline aguante cientos de jugadores simultáneos sin trabar el login ni el guardado de personaje.
Todo servidor de MU Online funciona fluido con 15 jugadores. El problema aparece en el primer evento lleno, en el lanzamiento, en el momento en que 200 personas intentan loguearse al mismo tiempo: el login se traba, el "guardar personaje" se retrasa, el Castle Siege se atasca. En la abrumadora mayor
Todo servidor de MU Online funciona fluido con 15 jugadores. El problema aparece en el primer evento lleno, en el lanzamiento, en el momento en que 200 personas intentan loguearse al mismo tiempo: el login se traba, el "guardar personaje" se retrasa, el Castle Siege se atasca. En la abrumadora mayoría de los casos el culpable no es el GameServer — es el SQL Server mal configurado. La base MuOnline recibe una avalancha de lecturas y escrituras cortas (login, save de posición, inventario, log de eventos) y, si la memoria, el tempdb y el modelo de recuperación no están ajustados, todo forma fila. Esta guía muestra cómo preparar SQL Server para escalar. Los valores numéricos son ejemplos que varían según la versión de SQL y el tamaño de tu VPS — lo que no varía es el método.
Requisitos previos
- SQL Server instalado (2014, 2017, 2019 o 2022 para servidores modernos; 2008 R2 todavía común en clásico/Season 6) con la base
MuOnlinerestaurada; - SQL Server Management Studio (SSMS) actualizado;
- Acceso
sao un login con permisosysadmin; - Conocimiento de cuánta RAM y cuántos núcleos tiene el VPS (
Task Manager→ Rendimiento, osysteminfo); - De preferencia, disco SSD (NVMe idealmente) para los archivos de datos y log;
- Un backup reciente antes de tocar cualquier configuración.
Releva el escenario actual de tu servidor antes de optimizar:
| Recurso | Dónde verlo | Por qué importa |
|---|---|---|
| RAM total del VPS | Administrador de tareas → Rendimiento | Define cuánto darle a SQL sin ahogar Windows/MuServer |
| Núcleos de CPU | systeminfo o Administrador de tareas | Define el número de archivos de tempdb y el MAXDOP |
| Tipo de disco | Propiedades del disco / panel del VPS | El HDD se vuelve un cuello de botella; el SSD es casi obligatorio |
| Edición de SQL | SELECT @@VERSION | Express limita la RAM (ej.: ~1,4 GB) y los núcleos |
Paso 1 — Fijar la memoria mínima y máxima
Por defecto SQL Server intenta consumir casi toda la RAM disponible, dejando a Windows y al MuServer sin aire — lo que causa paginación en disco y trabas. Fija un tope. Regla de partida: deja RAM suficiente para el SO y el MuServer, y dale el resto a SQL.
-- Ejemplo para un VPS de 16 GB (varía por versión/tamaño)
-- Reserva ~5 GB para Windows + MuServer, da ~11 GB a SQL
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;
EXEC sp_configure 'min server memory (MB)', 4096;
EXEC sp_configure 'max server memory (MB)', 11264;
RECONFIGURE;
Una referencia aproximada de punto de partida:
| RAM total del VPS | Max server memory (SQL) | Sobrante para SO + MuServer |
|---|---|---|
| 8 GB | ~5 GB | ~3 GB |
| 16 GB | ~11 GB | ~5 GB |
| 32 GB | ~24 GB | ~8 GB |
Paso 2 — Elegir el modelo de recuperación
El modelo de recuperación controla cómo se comporta el log de transacciones (.ldf). Para MU Online, Simple suele ser la elección correcta: el log se recicla automáticamente y no crece sin control, siempre que mantengas backups Full/Differential frecuentes.
-- Verificar el modelo actual
SELECT name, recovery_model_desc FROM sys.databases WHERE name = 'MuOnline';
-- Cambiar a Simple (log liviano, sin point-in-time)
ALTER DATABASE MuOnline SET RECOVERY SIMPLE;
Usa Full solo si necesitas recuperación punto a punto (restaurar hasta el minuto exacto antes de un incidente) — y, en ese caso, programa un backup de log frecuente, o el .ldf se traga el disco.
.ldf de decenas de GB casi siempre es síntoma de modelo Full sin backup de log. Si no haces backup de log, no te quedes en Full: tienes el costo del log gigante sin ningún beneficio de recuperación.Paso 3 — Configurar tempdb correctamente
El tempdb es donde SQL hace el "trabajo sucio": ordenamientos, tablas temporales, versionado. Bajo la carga de muchos jugadores, se vuelve un punto de contención. Dos acciones resuelven la mayoría de los problemas: crear varios archivos de datos y predimensionarlos.
-- Ver la configuración actual de tempdb
SELECT name, physical_name, size/128.0 AS SizeMB
FROM sys.master_files WHERE database_id = DB_ID('tempdb');
-- Ajustar el tamaño y el crecimiento del archivo principal (ejemplo)
ALTER DATABASE tempdb MODIFY FILE (NAME = tempdev, SIZE = 512MB, FILEGROWTH = 128MB);
-- Agregar archivos extra: regla práctica = 1 por núcleo, hasta 8, iguales
ALTER DATABASE tempdb ADD FILE (NAME = tempdev2, FILENAME = 'C:\SQLData\tempdb2.ndf', SIZE = 512MB, FILEGROWTH = 128MB);
ALTER DATABASE tempdb ADD FILE (NAME = tempdev3, FILENAME = 'C:\SQLData\tempdb3.ndf', SIZE = 512MB, FILEGROWTH = 128MB);
ALTER DATABASE tempdb ADD FILE (NAME = tempdev4, FILENAME = 'C:\SQLData\tempdb4.ndf', SIZE = 512MB, FILEGROWTH = 128MB);
El número de archivos debe coincidir con los núcleos del VPS (hasta un tope de 8). Todos del mismo tamaño y mismo crecimiento — SQL distribuye la carga entre archivos iguales; archivos de tamaños diferentes desequilibran la asignación. Si es posible, coloca el tempdb en un disco separado o en el SSD más rápido.
Paso 4 — Ajustar MAXDOP y Cost Threshold
MU Online dispara miles de consultas pequeñas (login, save, lectura de inventario). Para ese perfil, dejar que SQL paralelice de más estorba. Ajusta el grado máximo de paralelismo (MAXDOP) y el umbral de costo para paralelismo:
-- MAXDOP: para carga OLTP (muchas consultas pequeñas), limitar ayuda.
-- Regla común: número de núcleos por nodo NUMA, con tope de 8. Ejemplo:
EXEC sp_configure 'max degree of parallelism', 4;
RECONFIGURE;
-- Cost threshold: el valor por defecto 5 es demasiado bajo y hace que consultas triviales
-- paralelicen sin sentido. Subirlo a ~50 es una recomendación clásica.
EXEC sp_configure 'cost threshold for parallelism', 50;
RECONFIGURE;
Estos valores son ejemplos y varían según la versión y el número de núcleos. El principio: las consultas cortas de MU no se benefician de un paralelismo agresivo; dejar el cost threshold en el valor por defecto 5 solo genera overhead.
Paso 5 — Separar datos y log en discos/archivos sanos
El archivo de datos (.mdf) y el de log (.ldf) tienen patrones de I/O diferentes: los datos son lectura/escritura aleatoria, el log es escritura secuencial. Siempre que sea posible, mantenlos en discos distintos y evita el crecimiento en pedacitos:
-- Ver el tamaño y el autogrowth de los archivos de MuOnline
SELECT name, physical_name, size/128.0 AS SizeMB,
growth, is_percent_growth
FROM sys.master_files WHERE database_id = DB_ID('MuOnline');
-- Definir crecimiento en MB fijo (no en %), evitando fragmentación
ALTER DATABASE MuOnline MODIFY FILE (NAME = 'MuOnline_Data', FILEGROWTH = 256MB);
ALTER DATABASE MuOnline MODIFY FILE (NAME = 'MuOnline_Log', FILEGROWTH = 128MB);
Paso 6 — Habilitar Instant File Initialization
Sin esta configuración, cada vez que un archivo de datos crece, Windows pone físicamente el espacio en cero — lo que congela SQL durante la operación. Concediendo el privilegio Perform Volume Maintenance Tasks a la cuenta de servicio de SQL, el crecimiento de los archivos de datos pasa a ser instantáneo:
- Abre
secpol.msc(Directiva de Seguridad Local); - Ve a Directivas Locales → Asignación de Derechos de Usuario;
- Abre Realizar tareas de mantenimiento de volumen;
- Agrega la cuenta de servicio de SQL Server (ej.:
NT SERVICE\MSSQLSERVER); - Reinicia el servicio SQL Server.
Esto acelera el crecimiento de los datos y la restauración de backups. (No afecta al log, que siempre necesita ponerse en cero por diseño.)
Paso 7 — Mantener las estadísticas actualizadas
El optimizador de SQL decide cómo ejecutar cada consulta en base a las estadísticas. Si quedan viejas — lo que pasa rápido en una base de MU con mucha escritura — SQL toma malas decisiones y aparece el login lento. Garantiza la actualización automática y haz un refresh manual periódico:
-- Garantizar actualización automática de estadísticas
ALTER DATABASE MuOnline SET AUTO_UPDATE_STATISTICS ON;
ALTER DATABASE MuOnline SET AUTO_CREATE_STATISTICS ON;
-- Refresh manual de todas las estadísticas (ejecutar en mantenimiento)
USE MuOnline;
EXEC sp_updatestats;
Programa el sp_updatestats para que corra diariamente en la ventana de menor movimiento, junto con el mantenimiento de índices.
Paso 8 — Encontrar los cuellos de botella reales
Antes y después de optimizar, mide. SQL Server tiene vistas de sistema que señalan exactamente dónde sufre la base. Dos consultas valen oro:
-- Consultas más costosas (tiempo de CPU total)
SELECT TOP 10
qs.total_worker_time/qs.execution_count AS AvgCPU,
qs.execution_count,
SUBSTRING(st.text, 1, 120) AS Consulta
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
ORDER BY AvgCPU DESC;
-- Índices que faltan (SQL sugiere lo que crearía)
SELECT TOP 10
mid.statement AS Tabela,
migs.avg_user_impact AS ImpactoPct,
mid.equality_columns, mid.inequality_columns, mid.included_columns
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
ORDER BY migs.avg_user_impact DESC;
La primera muestra qué operaciones consumen CPU (generalmente el save de personaje o una query de ranking mal escrita). La segunda sugiere índices que el propio SQL echa de menos. La creación y el mantenimiento de esos índices es un tema en sí mismo — trátalo con cuidado, porque demasiados índices perjudican la escritura.
Paso 9 — Validar bajo carga simulada
Optimizar en el vacío engaña. Simula el pico antes del lanzamiento:
- Aplica todas las configuraciones anteriores y reinicia el servicio SQL;
- Ejecuta el
sp_updatestatsy el mantenimiento de índices; - Invita a un grupo de prueba (o usa bots controlados) para loguearse en masa;
- Mientras tanto, ejecuta las dos consultas de cuello de botella del paso anterior;
- Observa el uso de CPU y memoria en el Administrador de tareas;
- Ajusta MAXDOP y memoria si ves contención; repite.
Errores comunes y soluciones
| Síntoma | Causa probable | Solución |
|---|---|---|
| El login se traba cuando se llena | Falta de índice / estadísticas viejas / poca RAM a SQL | Crear los índices sugeridos, sp_updatestats, subir max memory |
| Servidor entero lento, disco al 100% | SQL consumiendo demasiada RAM, Windows paginando | Fijar max server memory dejando sobrante para el SO |
.ldf gigante llenando el disco | Modelo Full sin backup de log | Cambiar a Simple o programar backup de log |
| Trabas periódicas al crecer la base | Autogrowth en % / sin Instant File Init | Crecimiento en MB fijo + Perform Volume Maintenance Tasks |
| tempdb como cuello de botella en evento | Un único archivo de tempdb | Crear varios archivos iguales (1 por núcleo, hasta 8) |
| El save de personaje se retrasa | I/O en HDD, disco lento | Migrar datos/log a SSD NVMe |
| Consultas triviales paralelizando | cost threshold en el valor por defecto 5 | Subirlo a ~50 y ajustar MAXDOP |
Lista de verificación de lanzamiento
- Backup completo hecho antes de cualquier cambio
max server memoryfijado dejando RAM para Windows + MuServer + sitio- Modelo de recuperación decidido (Simple en la mayoría de los casos) y coherente con la política de backup
- tempdb con múltiples archivos iguales, predimensionados, de preferencia en SSD
- MAXDOP y cost threshold ajustados al perfil OLTP de MU
- Autogrowth en MB fijo para datos y log, con preasignación
- Instant File Initialization habilitado (Perform Volume Maintenance Tasks)
- AUTO_UPDATE_STATISTICS activado y
sp_updatestatsprogramado - Consultas de cuello de botella (CPU e índices faltantes) ejecutadas y analizadas
- Datos y log en SSD, idealmente en discos separados
- Prueba de carga con login en masa realizada antes de abrir al público
- SQL Server en inicio Automático junto con Windows
Con la memoria fijada, el tempdb multiarchivo, el modelo de recuperación correcto y las estadísticas al día, la base MuOnline deja de ser el cuello de botella del lanzamiento. El siguiente paso lógico es cerrar el ciclo de rendimiento cuidando los índices y el mantenimiento regular de la base — es allí donde las ganancias de largo plazo se consolidan y el servidor sigue rápido semana tras semana.
Preguntas frecuentes
¿Cuánta memoria RAM debo darle a SQL Server?
Reserva memoria fija para SQL, dejando el resto para Windows y el MuServer. Un punto de partida común es darle a SQL alrededor del 60-70% de la RAM total del VPS, nunca el 100%. El valor exacto varía según la versión de SQL y según cuántos jugadores esperes.
¿Modelo de recuperación Full o Simple para MU?
Simple es más liviano y suficiente si haces backups Full/Differential frecuentes, ya que no acumula un log de transacciones gigante. Full permite point-in-time recovery, pero exige un backup de log regular o el .ldf revienta el disco. La mayoría de los servidores de MU usa Simple.
¿Por qué el login se demora cuando el servidor se llena?
Casi siempre es contención en la base: falta de índice en MEMB_INFO/Character, tempdb mal configurado, memoria insuficiente que causa lectura en disco, o estadísticas desactualizadas. El cuello de botella rara vez es el GameServer en sí.
¿Necesito SSD para SQL Server?
Prácticamente obligatorio para servidores con muchos jugadores. SQL hace muchas lecturas y escrituras aleatorias; en HDD, guardar personaje y hacer login se vuelven un cuello de botella apenas la población crece. Un SSD NVMe es lo ideal.
¿Cuántos archivos de tempdb crear?
Una regla práctica es 1 archivo de datos de tempdb por núcleo de CPU, hasta un tope de 8, todos del mismo tamaño. Esto reduce la contención de asignación. El número ideal varía según los núcleos de tu VPS.