El dilema: ¿una consulta gigante o varias pequeñas?

Cuando usas .Include() en EF Core, por defecto se genera una sola consulta SQL con múltiples JOIN. Este enfoque, llamado SingleQuery, funciona bien en estructuras simples. Pero en relaciones complejas, puede provocar una explosión cartesiana que arrastra millones de filas duplicadas.

Para solucionarlo, EF Core introdujo SplitQuery. Este modo divide la carga en múltiples consultas SQL, una por cada relación. ¿El objetivo? Menos duplicación, mejor uso de memoria… pero a costa de más accesos a la base de datos.

Benchmark real con BenchmarkDotNet

Ejecutamos múltiples pruebas con modelos tipo Blog -> Posts -> Comments -> Owners. Comparamos SingleQuery, SplitQuery y una versión optimizada con Raw SQL.

Escenario Método Tiempo Medio Memoria GC Gen0 GC Gen1
1 blog, 1 post, 10 comentarios SingleQuery 885 µs 113 KB 7.8 0
SplitQuery 1,991 µs 120 KB 7.8 0
Raw SQL 663 µs 18 KB 0.9 0
100 blogs, 100 posts, 10 comentarios SingleQuery 22,5 s 283 MB 22k 11k
SplitQuery 25,1 s 243 MB 17k 11k
Raw SQL 4,4 s 124 MB 11k 6k

Resultado clave:

  • Raw SQL fue el más eficiente en todos los escenarios.

  • SplitQuery redujo el uso de memoria en escenarios grandes (~15% menos que SingleQuery).

  • SingleQuery fue más rápido en relaciones pequeñas o poco profundas.

Análisis: ¿Cuándo usar cada uno?

Escenario Recomendación
Relaciones simples (1:1 o pocos Include) SingleQuery
Muchas entidades relacionadas (1:N:N) SplitQuery
Alta concurrencia / consistencia estricta SingleQuery
Poca RAM o GC bajo presión SplitQuery
Red local / baja latencia SplitQuery
Datos estables y consulta intensiva Raw SQL

Consideraciones adicionales

  • Transacciones: SplitQuery no es atómico. Usa transacciones si necesitas consistencia fuerte.

  • Timeouts: más consultas = más riesgo de timeout si la red o BD está lenta.

  • Ordenamientos con Skip/Take: asegúrate de ordenar por campos únicos para evitar resultados incorrectos con SplitQuery.

Conclusión

No hay un ganador absoluto.


La elección entre SingleQuery y SplitQuery debe basarse en el contexto real de tus datos, el diseño de tus entidades y las necesidades de rendimiento o consistencia.

Sin embargo, algo que veo con demasiada frecuencia —especialmente en proyectos donde se copia y pega código sin cuestionar— es que se elige siempre uno u otro sin entender realmente las implicaciones. Rara vez se hace el ejercicio de parar, analizar y pensar críticamente:

¿Qué estoy cargando? ¿Cuál es la estructura? ¿Qué opción se adapta mejor a este caso concreto?

Los datos del benchmark muestran que, en muchos escenarios, un enfoque híbrido (usar SplitQuery cuando hay muchas colecciones y SingleQuery cuando hay pocas) sería óptimo, pero casi nunca se aplica.

Reflexiona antes de codificar. Las decisiones por inercia pueden costarte caro en rendimiento y escalabilidad.