Infra

Búsqueda híbrida en SQL Server: Combinando FULLTEXT y Vectores

Llevamos años viendo aplicaciones que convierten la busqueda de textos en una trituradora de CPU. El usuario escribe tres palabras, la capa de aplicación las trocea como puede, el ORM genera una consulta digna de un informe forense y SQL Server acaba haciendo lo que siempre hace, intentar salvarnos de nuestras propias decisiones. A veces lo consigue. A veces no. Y cuando no lo consigue, alguien abre una incidencia diciendo que “la base de datos va lenta”, como si el motor hubiera decidido por iniciativa propia montar un festival de LIKE ‘%texto%’.

La búsqueda de texto completo ha sido durante mucho tiempo nuestra herramienta principal para resolver este tipo de problemas. Los índices full-text permiten buscar términos dentro de columnas extensas, ordenar por relevancia y evitar que cada búsqueda acabe en un escaneo indecente. Ya hablé de esto con más detalle en el artículo sobre índices de texto completo o full-text indexes, porque siguen siendo una herramienta muy válida cuando necesitamos precisión léxica.

Pero ahora tenemos otro actor en escena: la búsqueda vectorial. SQL Server 2025, Azure SQL Database y SQL Database en Fabric incorporan capacidades nativas para trabajar con vectores, calcular distancias y ejecutar búsquedas aproximadas de vecinos más cercanos mediante VECTOR_SEARCH. En SQL Server 2025 estas capacidades están en vista previa y requieren habilitar PREVIEW_FEATURES. Además, Microsoft documenta que la versión más reciente de los índices vectoriales está disponible actualmente en Azure SQL Database y SQL Database en Microsoft Fabric.

La tentación evidente consiste en pensar que la búsqueda vectorial sustituye al full-text. Es una conclusión cómoda y moderna, pero equivocada. Es muy de presentación ejecutiva, lo que debería hacernos sospechar inmediatamente. La realidad es bastante más interesante, full-text y vectores resuelven problemas distintos, y la búsqueda híbrida aparece precisamente cuando dejamos de tratarlos como enemigos.

Antes de lanzarnos a escribir T-SQL como si no hubiera mañana, conviene dejar claro el problema de fondo.

La búsqueda híbrida no es IA pegada con cinta americana

La búsqueda híbrida combina una búsqueda léxica tradicional con una búsqueda semántica vectorial y fusiona después ambos conjuntos de resultados mediante una técnica de reordenación. La idea parece sencilla, una rama encuentra coincidencias de palabras con full-text indexes, la otra encuentra documentos semánticamente cercanos mediante comparación de embeddings, y una fase final decide qué documentos merecen aparecer arriba.

La clave está en esa última frase. No basta con ejecutar dos consultas y hacer un UNION. Eso no es búsqueda híbrida. Tampoco basta con sumar una puntuación full-text y una distancia vectorial, porque ambas magnitudes viven en universos matemáticos diferentes. SQL Server no va a convertir una escala relativa de relevancia textual y una distancia de coseno en una verdad universal solo porque usemos alias bonitos.

El full-text devuelve señales de relevancia asociadas a coincidencias lingüísticas. CONTAINSTABLE y FREETEXTTABLE devuelven una columna RANK con valores ordinales entre 0 y 1000, pero esos valores indican orden relativo dentro del conjunto devuelto. Microsoft advierte que el valor real no debe tratarse como una puntuación absoluta y puede variar entre ejecuciones.

La búsqueda vectorial, en cambio, devuelve una distancia. Si usamos coseno, valores más bajos indican mayor cercanía cuando trabajamos con VECTOR_DISTANCE o con la columna distance generada por VECTOR_SEARCH. Esa distancia expresa proximidad geométrica entre embeddings, no coincidencia literal de términos. Comparar directamente ambas señales es como comparar páginas leídas con cuanto agua está lloviendo fuera. Puedes hacerlo, pero no significa nada útil.

Por eso la búsqueda híbrida necesita una fase de fusión por rango. No fusionamos puntuaciones brutas, fusionamos posiciones. Y ahí entra Reciprocal Rank Fusion, más conocido como RRF.

Para entender por qué esto importa tanto, primero hay que asumir que full-text sigue siendo necesario.

Full-text: precisión léxica, no comprensión semántica

Un índice full-text sigue siendo una pieza excelente cuando necesitamos encontrar términos, variantes lingüísticas, prefijos, expresiones ponderadas o documentos donde aparecen palabras concretas. No es una tecnología vieja por no llevar “AI” en el nombre. De hecho, suele ser mucho más útil que una demo de embeddings cuando el usuario busca un código, una referencia contractual, un identificador de error o una cláusula exacta.

Imaginemos una base de conocimiento de soporte. Si el usuario busca OOM-802, lo normal es que quiera documentos que contengan OOM-802. No quiere artículos “conceptualmente relacionados con problemas de memoria”. Quiere ese código. Exactamente ese. Si le devolvemos un documento sobre “optimización general de memoria en servidores de aplicaciones” porque está cerca en el espacio vectorial, hemos hecho una búsqueda muy sofisticada y muy inútil. Todo muy moderno, todo muy mal.

Búsqueda de texto completo

Aquí full-text brilla. CONTAINSTABLE permite buscar en una columna indexada y obtener una lista ordenada por relevancia. Además, podemos limitar el volumen con el parámetro top_n_by_rank, algo especialmente importante cuando la condición puede devolver decenas o cientos de miles de filas. La documentación de Microsoft indica que limitar resultados con top_n_by_rank puede mejorar drásticamente el rendimiento, porque SQL Server ordena las coincidencias por rango y devuelve solo las primeras.

Esto no significa que full-text entienda el significado. Si buscamos “vehículo económico”, no podemos asumir que devuelva “coche barato”. Puede haber cierta ayuda lingüística según idioma, tesauro y configuración, pero no estamos ante comprensión semántica general. Full-text trabaja con términos, proximidad, formas lingüísticas y ranking textual. Los embeddings trabajan con representación numérica del significado. Mezclarlos sin entender esta diferencia es una forma estupenda de construir una solución que falle justo cuando el usuario la necesite.

En artículos anteriores del blog ya traté los índices de texto completo desde la perspectiva del DBA. Esa base sigue siendo necesaria. La búsqueda híbrida no elimina el conocimiento de full-text, lo potencia. Si alguien quiere saltar directamente a vectores sin entender CONTAINS, FREETEXT, CONTAINSTABLE, catálogos full-text, stopwords y ranking, adelante. Pero luego no vale llorar.

La otra mitad del problema está en la búsqueda semántica.

Vectores: significado aproximado, no magia contractual

Un embedding representa un texto como un vector numérico. La idea práctica es que textos con significado parecido generen vectores cercanos. A partir de ahí, podemos medir distancias mediante coseno, producto escalar o distancia euclídea, y recuperar los documentos más cercanos al vector de consulta. SQL Server permite realizar búsquedas exactas con VECTOR_DISTANCE, calculando la distancia entre el vector de búsqueda y los vectores almacenados. Microsoft describe este enfoque exacto como un cálculo exhaustivo que garantiza recuperar los vecinos más cercanos, aunque puede resultar costoso en conjuntos grandes.

La búsqueda exacta tiene una ventaja fundamental, no aproxima. Calcula. Si filtramos primero por cliente, estado, idioma, producto o fecha, y después aplicamos VECTOR_DISTANCE sobre un conjunto pequeño, podemos obtener resultados muy buenos sin necesidad de crear un índice vectorial. Esta estrategia suele ser más sensata de lo que parece, sobre todo en tablas medianas o en escenarios donde los filtros relacionales reducen mucho el número de candidatos.

La búsqueda aproximada, por su parte, usa estructuras especializadas para evitar comparar contra todos los vectores. En SQL Server y Azure SQL hablamos de VECTOR_SEARCH, que busca vectores similares mediante un algoritmo aproximado de vecinos más cercanos. Con la versión más reciente de los índices vectoriales, la sintaxis recomendada usa SELECT TOP (N) WITH APPROXIMATE y deja atrás el antiguo parámetro TOP_N, que Microsoft marca como obsoleto para índices recientes.

Índices vectoriales: grafos de embeddings

Aquí aparece DiskANN. Un índice vectorial de tipo DiskANN acelera la recuperación aproximada navegando una estructura de grafo pensada para localizar vecinos cercanos sin recorrer todo el conjunto. Eso tiene un coste. Hay mantenimiento, requisitos, restricciones y decisiones de diseño. No creamos un índice vectorial porque la palabra “vector” aparezca en una reunión. Lo creamos cuando el volumen, la latencia esperada y el patrón de consulta lo justifican.

En el artículo sobre DiskANN y búsqueda vectorial en SQL Server 2025 ya expliqué por qué no conviene indexar vectores en cualquier tabla. Esta recomendación sigue siendo válida. Si tienes 3.000 filas y filtros buenos, probablemente VECTOR_DISTANCE con búsqueda exacta te dé una solución más simple, más predecible y más fácil de razonar. La complejidad innecesaria siempre encuentra la forma de facturarse más tarde.

Como véis, la búsqueda semántica resuelve muy bien consultas ambiguas. “Portátil ligero para viajar”, “incidencia parecida a error de memoria”, “cliente molesto por retrasos recurrentes” o “documentación sobre migración sin parada” son ejemplos donde la coincidencia literal se queda corta. Pero esa misma flexibilidad puede volverse peligrosa cuando la consulta contiene un literal crítico.

Por eso necesitamos una arquitectura híbrida.

El patrón correcto: recuperar candidatos y fusionar rangos

La búsqueda híbrida no debería ejecutar una búsqueda vectorial contra toda la tabla y otra full-text sin límite para después cruzar todo alegremente. Eso solo consumiría recursos a lo loco. El patrón correcto consiste en recuperar un número razonable de candidatos por cada rama y fusionar después esos candidatos mediante un ranking controlado.

La rama léxica puede usar CONTAINSTABLE o FREETEXTTABLE, según queramos una búsqueda más precisa o más lingüística. Para códigos, identificadores, términos técnicos y mensajes de error, normalmente prefiero CONTAINSTABLE. Para búsquedas más naturales o descriptivas, FREETEXTTABLE puede encajar mejor. No son intercambiables, aunque en muchas aplicaciones se usen como si lo fueran. Luego nos extraña que el buscador parezca tener resaca.

La rama semántica puede usar VECTOR_DISTANCE o VECTOR_SEARCH. Si queremos una búsqueda exacta sobre pocos candidatos, VECTOR_DISTANCE es una buena opción. Si tenemos cientos de miles o millones de embeddings, baja tolerancia a latencia y un índice vectorial adecuado, VECTOR_SEARCH pasa a tener sentido. Microsoft también documenta que los índices vectoriales recientes aplican predicados de WHERE durante el proceso de búsqueda vectorial mediante filtrado iterativo, no simplemente después de recuperar vecinos, pero eso, de momento solo está en Azure.

Unir resultados 

La fase final no debe sumar RANK full-text con distancia vectorial. Debe convertir cada lista en posiciones ordinales y aplicar RRF. La fórmula general es sencilla:

score(d) = Σ 1 / (k + rank_i(d))

Donde rank_i(d) es la posición del documento d en la lista i, y k es una constante de suavizado. Si un documento no aparece en una rama, esa rama aporta cero. No aporta un rango inventado de diez mil, salvo que queramos aplicar una penalización heurística deliberada. RRF canónico suma contribuciones de listas donde el documento existe, lo demás ya es cocina propia.

El valor k = 60 aparece a menudo como constante práctica. No es una ley divina, ni una recomendación que debamos tatuarnos pero si podríamos decir que es un estándar del mercado. Un k más bajo da más peso a las primeras posiciones; un k más alto suaviza la diferencia entre posiciones. En buscadores internos suelo empezar con 60, medir, revisar consultas reales y ajustar. Sí, medir. Esa costumbre extravagante que a veces evita reuniones.

Vamos a bajarlo a código.

Modelo de datos para un escenario realista

Supongamos una tabla de tickets de soporte. Cada ticket tiene una descripción textual, metadatos relacionales y un embedding generado a partir del contenido que queremos buscar. No voy a centrarme aquí en la generación del embedding porque ya traté las búsquedas semánticas con IA en SQL Server 2025 en otro artículo, y además dejé ejemplos prácticos en YouTube para quien quiera ver el flujo completo con más calma.

La tabla podría tener esta forma simplificada:

El índice relacional no es decorativo. En una arquitectura híbrida seria, los filtros siguen importando. Si buscamos tickets de un cliente concreto, de un producto concreto o de un rango temporal, no queremos que la parte vectorial se comporte como un turista perdido recorriendo toda la ciudad. Queremos acotar el problema antes de calcular distancias.

El índice full-text iría sobre las columnas textuales relevantes. En producción hay que cuidar idioma, catálogos, stoplists y fragmentación del índice full-text, pero el esqueleto sería este:

El LANGUAGE 3082 corresponde al español. En entornos multidioma, este detalle se complica bastante. Un catálogo global con textos mezclados en cinco idiomas y una sola configuración lingüística no es internacionalización; es una ruleta. Si el negocio necesita búsquedas multidioma, hay que diseñar para ello, no rezar para que el motor “lo entienda”.

Para la parte vectorial, un índice DiskANN puede crearse así cuando el volumen lo justifique:

Los índices vectoriales recientes exigen al menos 100 filas con vectores no nulos antes de poder crearse, requieren una clave primaria clustered y tienen limitaciones actuales como ausencia de particionado, restricciones con TRUNCATE TABLE, no replicarse a suscriptores y problemas de despliegue directo con DacPac o BACPAC porque el índice se crea antes de cargar datos.

Esto ya nos da una pista importante: no hablamos de un índice cualquiera. No es un IX_Tabla_Campo que añadimos a las tres de la tarde para callar una alerta. Un índice vectorial afecta al ciclo de vida de la tabla, al despliegue, al mantenimiento y a los procesos de carga. Si el plan de despliegue de tu base de datos ignora esto, no tienes un plan; tienes un problema.

Ahora sí, veamos una búsqueda híbrida exacta.

Búsqueda híbrida exacta con VECTOR_DISTANCE

El primer patrón usa VECTOR_DISTANCE. Es el más fácil de razonar porque calcula distancias reales contra los candidatos considerados. Conviene usarlo cuando el conjunto final no es enorme, cuando los filtros relacionales son selectivos o cuando la precisión importa más que la latencia extrema.

El siguiente ejemplo recibe una consulta textual, genera su embedding y combina la rama semántica con la rama full-text. Limitamos ambas ramas para no fusionar medio millón de filas, es la forma de decirle a SQL “no hagas barbaridades”.

Hay varias decisiones intencionadas aquí. La rama semántica no calcula distancia contra toda la tabla, sino contra CandidatosFiltrados. Esto permite que el optimizador use índices relacionales antes de aplicar la parte matemática. Si el cliente tiene 4.000 tickets abiertos del producto, calcular 4.000 distancias puede ser razonable. Si tiene 40 millones, probablemente estamos diseñando otra cosa.

La rama léxica usa CONTAINSTABLE con top_n_by_rank. Ese cuarto parámetro limita el número de resultados full-text devueltos. No quiero traer todos los tickets que contengan “memoria” para después descubrir que el usuario solo verá 20 filas. Esa es la diferencia entre una consulta y un castigo.

La fusión usa FULL OUTER JOIN porque un documento puede aparecer solo en la rama semántica o solo en la rama léxica. Después, COALESCE(1.0 / (@rrf_k + rango), 0.0) suma cero cuando el documento no aparece en una rama. Esto es importante, no inventamos rangos artificiales. Si queremos penalizar más o menos los resultados huérfanos, podemos hacerlo, pero entonces debemos reconocer que estamos introduciendo una heurística adicional.

También ordeno por criterios secundarios. En producción, los empates ocurren. Si no defines desempates, el motor puede devolverte órdenes distintos entre ejecuciones. Y cuando el usuario dice “ayer salía primero”, a nadie le divierte explicar que una ordenación parcial no garantiza estabilidad. Bueno, a nadie normal, que yo estoy aquí preparando el artículo más largo de todos los que he escrito para explicaros eso.

Este patrón exacto es muy útil cuando trabajamos con filtros fuertes. Pero si el volumen semántico es grande y necesitamos latencia baja, toca pasar a búsqueda aproximada.

Búsqueda híbrida aproximada con VECTOR_SEARCH

VECTOR_SEARCH representa el patrón de búsqueda vectorial aproximada. Con índices vectoriales recientes, la sintaxis exige SELECT TOP (N) WITH APPROXIMATE y ordenación ascendente por la columna distance, que es la única clave de ordenación válida para los resultados aproximados. Si existe un índice ANN compatible con la misma métrica y columna, puede usarse, si no existe, el motor puede recurrir a kNN y emitir una advertencia.

Una versión híbrida aproximada puede quedar así:

Este ejemplo es parecido al anterior, pero cambia la rama semántica. Ahora usamos VECTOR_SEARCH, que devuelve la columna distance. La consulta solicita explícitamente resultados aproximados con WITH APPROXIMATE. Esto no es un adorno sintáctico, en índices recientes, Microsoft separa claramente la búsqueda aproximada de la exacta mediante esta sintaxis.

La presencia del WHERE dentro de la rama semántica también importa. En versiones recientes de índices vectoriales, Microsoft documenta filtrado iterativo, es decir, los predicados se aplican durante el proceso de búsqueda vectorial, no únicamente después. En versiones antiguas, los filtros podían aplicarse solo después de recuperar vecinos, lo que provocaba resultados vacíos o incompletos si los primeros vecinos no cumplían el filtro. Esta diferencia no es teórica, afecta directamente a la calidad del resultado.

Si trabajas con índices vectoriales antiguos, conviene migrarlos. Microsoft indica que los índices creados con estructuras anteriores se mantienen en la versión actual, pero quedarán retirados en una versión futura, y para obtener las capacidades recientes hay que eliminar y recrear el índice. La propia DMV sys.vector_indexes, junto con sys.indexes y sys.tables, permite consultar la versión registrada en los parámetros de construcción.

Esto introduce una responsabilidad nueva para el DBA. Ya no basta con saber si el índice existe. Hay que saber qué versión tiene, qué sintaxis admite, cómo se comporta con filtros y si soporta mantenimiento DML completo. El “tenemos índice vectorial” se parece demasiado al “tenemos backup”: la frase tranquiliza hasta que preguntas cuándo se ha probado.

RRF con pesos: cuando no todas las señales valen lo mismo

RRF básico da el mismo peso a cada rama. Eso suele ser un buen punto de partida, porque evita discusiones prematuras. Pero no todos los dominios tienen la misma necesidad de precisión literal y contexto semántico. En una base de conocimiento técnica, los códigos de error, nombres de procedimiento, versiones y referencias internas suelen pesar mucho. En un catálogo de productos o una búsqueda documental abierta, la semántica puede tener más protagonismo.

Podemos introducir pesos sin romper la estructura:

Esto ya no es RRF puro, sino RRF ponderado. No hay problema, siempre que seamos conscientes de ello. Lo peligroso no es ajustar el algoritmo, lo peligroso es hacerlo sin medir. Si damos demasiado peso a la rama semántica, un literal crítico puede quedar enterrado bajo documentos conceptualmente parecidos. Si damos demasiado peso a la rama léxica, perdemos recall semántico y volvemos al mundo de “no encuentro coche barato porque el documento dice vehículo económico”.

En entornos serios conviene registrar consultas reales, resultados seleccionados, clics, aperturas, tiempo hasta resolver la incidencia y feedback explícito si existe. Después podemos comparar configuraciones de pesos, tamaños de candidatos y valores de k. La relevancia no se calibra en una pizarra. Se calibra con datos y pruebas. Qué concepto tan revolucionario.

También podemos modificar pesos en función de la consulta. Si detectamos patrones de códigos, identificadores, GUIDs, números de versión o referencias internas, podemos favorecer full-text. Si la consulta es larga, descriptiva y sin literales críticos, podemos favorecer semántica. Este tipo de adaptación suele dar mejores resultados que una configuración fija para todos los casos.

La detección no tiene por qué ser perfecta. Basta con aplicar reglas prudentes. Una consulta con OOM-802, SQLSTATE 40001, KB500 o Procedure dbo.X probablemente necesita más precisión léxica. Una consulta como “el agente se queda bloqueado después de actualizar y consume mucha memoria” puede beneficiarse más del vector. El usuario no nos entrega una intención formal; nos entrega una frase. Nuestro trabajo consiste en no destrozarla.

El tamaño de los candidatos importa más de lo que parece

Uno de los errores más comunes en búsqueda híbrida consiste en recuperar pocos candidatos por rama. Si pedimos top 10 semántico y top 10 léxico para devolver top 10 final, apenas damos margen al algoritmo de fusión. RRF necesita espacio para encontrar documentos que quizá no sean número uno en ninguna rama, pero sí sean buenos en ambas.

Un documento que aparece en posición 12 en la rama semántica y posición 8 en la rama léxica puede ser mucho mejor resultado global que otro que aparece en posición 1 semántica y no aparece en léxica. Si solo recuperamos diez candidatos por rama, el primero puede sobrevivir y el segundo puede ni siquiera existir en la fusión. El algoritmo no puede ordenar documentos que nunca le hemos dado.

Por eso suelo trabajar con una ventana de candidatos bastante mayor que el resultado final. Si voy a mostrar 20 resultados, empezar con 100 o 200 por rama suele ser razonable. Luego hay que medir. No es lo mismo una tabla de tickets internos que una base documental de millones de artículos. Tampoco es lo mismo una búsqueda con filtros por cliente que un buscador global público.

El parámetro top_n_by_rank de full-text ayuda en la rama léxica. En la rama vectorial aproximada, TOP (N) WITH APPROXIMATE marca la ventana semántica. En la rama exacta con VECTOR_DISTANCE, TOP (N) limita el cálculo ordenado final, aunque el coste previo depende de cuántas filas sobrevivan a los filtros relacionales.

Aquí conviene vigilar planes de ejecución, memoria concedida, spills, paralelismo y lecturas lógicas. También hay que observar la distribución de distancias. Si todos los documentos tienen distancias muy parecidas, la señal semántica quizá no discrimina bien. Si el full-text devuelve rankings muy planos, la parte léxica quizá necesita mejorar sintaxis, tesauro, stopwords o normalización de contenido.

La búsqueda híbrida no elimina el tuning. Le añade dimensiones nuevas. Por si alguien echaba de menos complicarse la vida.

Exact search frente a ANN: elegir sin postureo

La búsqueda exacta con VECTOR_DISTANCE calcula distancias y ordena. Es simple, precisa y fácil de auditar. Si el conjunto candidato es pequeño, suele ser una gran elección. También es buena para validación, pruebas de calidad y comparación contra la búsqueda aproximada. En escenarios donde la exactitud es crítica, tener un modo exacto ayuda a detectar pérdida de recall introducida por ANN.

La búsqueda aproximada con VECTOR_SEARCH sacrifica exactitud teórica por velocidad. No tiene nada de malo. Muchos sistemas de búsqueda funcionan así porque el usuario necesita respuestas rápidas y suficientemente buenas. El problema aparece cuando alguien vende “aproximado” como si significara “igual pero más rápido”. No. Significa aproximado. La palabra está ahí, generosamente visible.

Microsoft documenta que VECTOR_SEARCH utiliza búsqueda aproximada de vecinos más cercanos, y que con índices recientes el optimizador puede decidir entre usar DiskANN o búsqueda kNN según las características de la consulta. También indica que, si no hay un índice ANN compatible con la métrica y la columna, se genera una advertencia y se usa kNN.

Esto tiene implicaciones operativas. Si una consulta esperada como aproximada cae a kNN por no tener índice compatible, puede cambiar radicalmente su coste. Si alguien crea el índice con métrica DOT y la consulta usa cosine, no esperes milagros. El motor no va a inventar un índice compatible porque el ticket esté marcado como urgente.

La métrica debe estar alineada con el modelo de embeddings y con la normalización aplicada. En muchos modelos textuales se usa coseno, pero no conviene asumirlo por costumbre. Hay que revisar cómo se generaron los embeddings, si están normalizados y qué distancia recomienda el proveedor o el patrón de uso. El DBA no tiene por qué entrenar el modelo, pero sí debe entender qué está almacenando y cómo se consulta.

Además, el índice vectorial no sustituye los índices relacionales. Microsoft recomienda combinar índices vectoriales con índices tradicionales en columnas usadas por filtros, especialmente cuando el filtrado iterativo puede aprovechar predicados selectivos.

Dicho de otra forma, seguimos necesitando buenos índices B-Tree. La IA no ha derogado la selectividad. Qué disgusto para algunos.

DML, versiones de índice y falsas verdades que caducan

Durante las primeras versiones, una de las limitaciones más agresivas de los índices vectoriales era que las tablas quedaban de solo lectura después de crear el índice. Para permitir DML había que aceptar índices obsoletos mediante configuración, con el riesgo de resultados no actualizados. Esa limitación existió y era importante.

Pero no conviene escribir arquitectura en piedra cuando la tecnología está en vista previa y cambia deprisa. Microsoft documenta que los índices vectoriales creados con la versión más reciente eliminan esa restricción: soportan INSERT, UPDATE, DELETE y MERGE, con mantenimiento automático y en tiempo real del índice. Los cambios son visibles para las búsquedas vectoriales después del commit.

Esto no significa que podamos olvidarnos del mantenimiento. Para reemplazos masivos de datos, por ejemplo al regenerar embeddings con otro modelo, Microsoft recomienda considerar eliminar y recrear el índice después de la carga para mantener calidad de búsqueda predecible. La estructura del índice se construyó con una distribución vectorial determinada; si cambiamos casi todos los embeddings, no deberíamos sorprendernos de que la calidad se resienta.

También siguen existiendo restricciones actuales. No hay soporte de particionado para índices vectoriales, la tabla necesita clave primaria clustered, TRUNCATE TABLE no puede ejecutarse directamente sobre tablas con índice vectorial y los despliegues con DacPac o BACPAC requieren cuidado porque el índice necesita datos no nulos existentes al crearse.

Esto cambia bastante el diseño de procesos ETL. Si regeneramos embeddings en bloque, quizá convenga cargar en una tabla staging, validar dimensiones, controlar nulos, medir duplicados y después hacer intercambio lógico. Si trabajamos en Azure SQL o Fabric con índices recientes, no tenemos que congelar la tabla para cada operación DML normal, pero sí debemos diseñar cargas masivas con cabeza.

También hay que monitorizar. La documentación menciona sys.dm_db_vector_indexes para observar salud del índice y tareas de mantenimiento. En sistemas donde el embedding cambia con frecuencia, esa DMV deja de ser curiosidad y pasa a ser parte del cuadro de mando operativo.

La conclusión práctica es sencilla, no repitas limitaciones antiguas sin mirar versión, pero tampoco vendas los índices vectoriales como índices normales. Ambas posturas son malas. Una por anticuada; la otra por ingenua.

Calidad de datos: embeddings duplicados y basura semántica

La búsqueda vectorial amplifica la calidad del contenido. Si generas embeddings sobre textos pobres, duplicados, genéricos o mal normalizados, el índice devolverá resultados pobres, duplicados, genéricos o mal normalizados. No hay misterio. El embedding no convierte documentación basura en conocimiento. Solo la representa numéricamente con mucha dignidad matemática.

Microsoft recomienda evitar conjuntos con alta proporción de embeddings duplicados, porque perjudican la calidad de resultados, desplazan vecinos más útiles y consumen recursos sin aportar valor.

Esto se ve mucho en bases de conocimiento donde múltiples artículos empiezan con la misma plantilla corporativa. “Estimado usuario, este documento describe el procedimiento para resolver incidencias relacionadas con…” Si generamos embeddings sobre todo el texto sin ponderar ni limpiar, la plantilla común puede contaminar la similitud. Después nos preguntamos por qué todos los documentos parecen iguales. Quizá porque hemos metido el mismo ruido en todos. Sorpresón.

Hay que decidir qué texto se embebe. No siempre interesa usar todo el documento. A veces conviene usar título, resumen, etiquetas, producto, síntomas y causa raíz. En otros casos interesa trocear documentos largos en fragmentos y buscar sobre chunks, no sobre documentos completos. Si un artículo de diez páginas contiene una sección relevante en la página ocho, el embedding global puede diluirla.

También hay que versionar el modelo de embeddings. Si hoy generamos vectores con un modelo y mañana con otro, no debemos mezclar ambos alegremente en la misma columna sin saber qué estamos haciendo. Las distancias entre vectores generados por modelos distintos pueden dejar de tener sentido. Como mínimo, guardaría ModeloEmbedding, FechaEmbedding, HashContenido y estado de generación.

Un diseño más serio podría separar documento y fragmentos:

Este modelo permite buscar fragmentos, no solo documentos. Después podemos agregar resultados por DocumentoID, aplicar RRF sobre fragmentos y mostrar el documento con el fragmento más relevante. Es más trabajo, claro. También es más útil. La alternativa es devolver documentos enormes y confiar en que el usuario encuentre el párrafo bueno. Eso no es buscador; es externalizar el problema.

Reordenación por documento cuando trabajamos con fragmentos

Cuando buscamos sobre fragmentos, aparece un problema adicional. Un documento largo puede tener muchos fragmentos y, por tanto, muchas oportunidades de aparecer. Si no controlamos esto, los documentos extensos dominan el ranking simplemente porque tienen más boletos. Es el mismo vicio de siempre, confundir cantidad con relevancia.

Una estrategia razonable consiste en fusionar primero a nivel de fragmento y después colapsar por documento, quedándonos con la mejor puntuación o aplicando una agregación controlada. Por ejemplo:

Aquí MAX(PuntuacionRRF) evita que un documento se dispare solo por tener muchos fragmentos moderadamente relevantes. El contador de fragmentos coincidentes puede servir como desempate suave, pero no debería dominar la ordenación. Si queremos algo más sofisticado, podemos usar una combinación entre mejor fragmento, número de fragmentos relevantes y diversidad de secciones.

En sistemas RAG, este patrón es especialmente útil. El buscador no solo decide qué documento mostrar; decide qué fragmento alimentar al modelo generativo. Si metemos fragmentos malos en el contexto, el modelo responderá con seguridad y poca vergüenza. La seguridad sin fundamento ya la conocemos de algunas reuniones de arquitectura, pero no hace falta automatizarla.

También podemos añadir filtros de seguridad y visibilidad antes de la búsqueda. Si un usuario no tiene permiso sobre un documento, ese documento no debe aparecer ni por semántica ni por full-text. Esto parece obvio hasta que alguien implementa el filtro después de generar el contexto para el modelo. 

Seguridad, permisos y fuga semántica

La búsqueda híbrida no solo afecta al rendimiento. También afecta a la seguridad. Un embedding puede codificar información sensible del texto original. No es una copia literal, pero tampoco deberíamos tratarlo como un dato inocente. Si generamos embeddings de documentos confidenciales y permitimos búsquedas semánticas sin aplicar permisos correctamente, podemos filtrar conocimiento aunque no devolvamos el texto completo.

La seguridad debe aplicarse antes de formar candidatos o durante el proceso de búsqueda, no al final de manera cosmética. En VECTOR_SEARCH, con índices recientes y filtrado iterativo, los predicados pueden aplicarse durante la búsqueda vectorial. Eso ayuda, pero no sustituye un diseño de seguridad correcto.

En SQL Server podemos resolver parte del problema con predicados relacionales, Row-Level Security o filtros explícitos por tenant, organización, rol o ámbito documental. Lo importante es que la rama léxica y la rama semántica usen exactamente la misma lógica de visibilidad. Si full-text filtra por permisos y vector no, la fusión RRF puede devolver identificadores que la rama textual jamás habría permitido. Y entonces empieza el baile.

También hay que controlar quién puede generar embeddings. Si usamos AI_GENERATE_EMBEDDINGS, debemos revisar modelo, permisos, configuración del servicio y trazabilidad. Si los generamos fuera y los cargamos en SQL Server, debemos validar dimensiones, formato, modelo, nulos y correspondencia con el texto original. Un embedding desalineado con su documento es una mentira muy rápida de consultar.

En entornos multi-tenant, yo evitaría búsquedas vectoriales globales salvo que el aislamiento esté muy claro. Filtrar por tenant no es opcional. Y si el volumen por tenant permite búsqueda exacta con VECTOR_DISTANCE, quizá esa sea la opción más controlable. No todo problema necesita ANN global. A veces la arquitectura sencilla gana porque tiene menos formas de fallar.

La seguridad no debe aparecer como epígrafe al final del proyecto. Si el buscador ya está construido y alguien pregunta “¿cómo filtramos por permisos?”, lo más probable es que la respuesta correcta sea “reescribiendo más de lo que te gustaría”.

Observabilidad: medir relevancia y medir coste

Una búsqueda híbrida tiene dos planos de observabilidad. El primero es técnico: duración, lecturas, CPU, memoria, spills, número de candidatos por rama, uso de índice vectorial, uso de índice full-text, plan elegido, cardinalidades estimadas y reales. El segundo es funcional: consultas reales, documentos mostrados, documentos abiertos, posición del clic, reformulaciones y satisfacción del usuario.

Si solo medimos rendimiento, podemos construir un buscador rapidísimo que devuelve basura. Si solo medimos relevancia, podemos construir un buscador magnífico que tumba producción cada vez que se usa. Ninguna de las dos cosas debería darnos orgullo profesional.

A nivel técnico, conviene registrar para cada búsqueda el texto normalizado, tamaño de candidatos léxico, tamaño de candidatos semántico, top_final, valor de k, pesos aplicados, duración total y duración por rama si separamos ejecución. También podemos guardar si la consulta se trató como “literal crítica” o “semántica dominante”. Esta trazabilidad permite ajustar sin adivinar.

A nivel funcional, el dato más valioso suele ser qué resultado acaba usando el usuario. En soporte, podemos vincular búsqueda con ticket resuelto o artículo seleccionado. Si es documentación interna, podemos medir apertura y permanencia. En buscadores de catálogo, conversión o selección. La relevancia real no siempre coincide con nuestra intuición, especialmente cuando los usuarios escriben cosas que harían llorar a un parser.

También hay que comparar full-text puro, vector puro e híbrido. No para hacer una gráfica bonita, sino para demostrar que la complejidad añadida aporta valor. Si la híbrida no mejora precisión, recall o tiempo de resolución, quizá estamos decorando arquitectura. Y la decoración en producción suele ser cara.

Un enfoque serio consiste en crear un conjunto de consultas de evaluación con resultados esperados. No tiene que ser perfecto. Basta con consultas representativas, incluyendo códigos exactos, frases ambiguas, sinónimos, errores ortográficos, consultas largas y consultas absurdamente cortas. Sobre ese conjunto podemos probar distintos pesos, tamaños de ventana y valores de k.

Sin evaluación, la búsqueda híbrida se convierte en “a mí me parece que va mejor”. Esa frase ha causado más daño que algunos NOLOCK.

Casos donde no usaría búsqueda híbrida

No todo buscador necesita híbrida. Si el usuario busca exclusivamente códigos, referencias exactas, identificadores legales o claves de producto, full-text o incluso índices relacionales bien diseñados pueden bastar. Meter embeddings ahí puede añadir ruido. Una búsqueda de Factura 2024-000834 no necesita poesía semántica.

Tampoco usaría híbrida como primera respuesta a un problema de contenido mal estructurado. Si los documentos no tienen títulos decentes, categorías, producto, idioma, fecha, permisos o estado, la búsqueda híbrida no arreglará el desastre. Solo lo hará más caro. Primero se ordena el contenido; después se mejora la recuperación.

En tablas pequeñas, evitaría crear índices vectoriales salvo que exista una razón clara. Microsoft indica que VECTOR_SEARCH puede funcionar sin índice mediante escaneo brute-force, aunque el rendimiento se degrada con datasets grandes. Para desarrollo, pruebas y conjuntos pequeños, esto puede ser suficiente.

También sería prudente con cargas masivas frecuentes. Si regeneramos embeddings continuamente, cambiamos modelos a menudo o reemplazamos gran parte del dataset, el coste de mantenimiento y reconstrucción puede pesar más que la ventaja de ANN. En esos casos hay que diseñar ventanas de carga, staging, versiones de índice y validaciones. No conviene descubrirlo durante una migración nocturna con tres personas mirando una barra de progreso.

Por último, no usaría híbrida sin una estrategia de seguridad clara. La búsqueda semántica puede recuperar contenido inesperado porque no depende de palabras exactas. Eso es precisamente lo que la hace potente. También es lo que la hace peligrosa si los permisos se aplican tarde o mal.

El mejor buscador no es el que usa más tecnologías. Es el que devuelve lo correcto, rápido, dentro de permisos y con un coste operativo razonable. Parece una obviedad, pero hay arquitecturas enteras construidas para demostrar lo contrario.

Buenas prácticas para llevarlo a producción

La primera buena práctica es separar claramente recuperación y reordenación. La rama full-text recupera candidatos léxicos. La rama vectorial recupera candidatos semánticos. RRF fusiona posiciones. Si mezclamos estas fases sin orden, acabaremos con consultas imposibles de depurar.

La segunda es limitar candidatos por rama. Ni full-text ni vector deberían devolver volúmenes masivos si el resultado final tendrá 20 filas. top_n_by_rank en CONTAINSTABLE y TOP (N) WITH APPROXIMATE en VECTOR_SEARCH son herramientas básicas para controlar el tamaño del problema.

La tercera es conservar filtros relacionales fuertes. Cliente, tenant, producto, estado, idioma, fecha y permisos deben formar parte del diseño. No todo debe resolverse por similitud. A veces una igualdad bien indexada vale más que un grafo vectorial entero. No queda tan bien en una presentación, pero ejecuta mejor.

La cuarta es versionar embeddings. Guarda modelo, fecha, hash del texto y estado de generación. Si cambias el texto, regenera el vector. Cuando cambies el modelo, no mezcles vectores sin control. Si falla la generación, no insertes basura silenciosa. La base de datos recordará tu negligencia con una precisión admirable.

La quinta es medir calidad, no solo latencia. Registra consultas reales y resultados usados. Ajusta pesos y ventanas con datos. RRF funciona muy bien como punto de partida, pero cada dominio tiene sus rarezas. En soporte técnico, los literales pesan mucho. Si es búsqueda documental, la semántica puede dominar. En comercio, atributos estructurados y disponibilidad pueden importar más que ambas.

La sexta es revisar versión y comportamiento de los índices vectoriales. Los índices antiguos tienen limitaciones distintas a los recientes. La sintaxis con TOP_N queda obsoleta para índices nuevos, mientras que SELECT TOP (N) WITH APPROXIMATE es el patrón actual documentado para la búsqueda aproximada con índices recientes.

La séptima es preparar despliegues y mantenimiento. Si usas DacPac, BACPAC, replicación, particionado o cargas masivas, revisa restricciones antes de comprometer la arquitectura. Los índices vectoriales no son invisibles para la operación diaria. El DBA va a convivir con ellos, y conviene que no sea en régimen de sorpresa permanente.

Todo esto suena menos emocionante que “hemos metido IA en el buscador”. También es bastante más probable que funcione.

Conclusión

La búsqueda híbrida no sustituye al full-text ni convierte la búsqueda vectorial en una solución universal. Lo interesante aparece precisamente al combinar ambas señales con criterio, full-text aporta precisión léxica, los vectores aportan contexto semántico y RRF permite fusionar resultados sin mezclar puntuaciones incompatibles.

El diseño correcto no consiste en lanzar dos consultas y rezar. Hay que limitar candidatos, aplicar filtros relacionales, elegir entre búsqueda exacta y aproximada, revisar versiones de índice, controlar permisos, medir relevancia y entender el coste operativo. La parte bonita de la demo dura diez minutos. La parte seria vive dia a dia en producción.

SQL Server está incorporando capacidades muy potentes para búsqueda semántica e híbrida, pero potencia no significa simplicidad. Un índice vectorial mal usado, una rama full-text sin límite o una fusión de puntuaciones mal planteada pueden convertir una gran idea en otra incidencia con prioridad alta.

La búsqueda híbrida merece sitio en arquitecturas modernas, especialmente en bases de conocimiento, soporte, documentación interna y sistemas RAG. Pero exige DBAs que entiendan el motor, no operadores que copien sintaxis de una demo. Como casi siempre, la diferencia entre una solución elegante y una chapuza cara está en los detalles. Y los detalles, por suerte o por desgracia, siguen sin indexarse solos.

 

Publicado por Roberto Carrancio en Cloud, SQL Server, 0 comentarios

SQL Database en Fabric: cuánto tiene de SQL y cuánto de Fabric

Con SQL Database en Fabric Microsoft hizo algo realmente inteligente, coger un motor que conocemos bien, Azure SQL Database, y colocarlo dentro del perímetro operativo de Fabric para vender una historia unificada de datos, analítica y desarrollo. La pregunta útil no es si “es SQL”, porque sí lo es. La pregunta útil es otra: cuánto de Azure SQL conserva, cuánto sacrifica por vivir en Fabric y en qué escenarios compensa ese intercambio. El servicio está en disponibilidad general desde noviembre de 2025 y Microsoft lo presenta como una base de datos SQL serverless y “SaaS-native” dentro de Fabric.

Antes de entrar en límites y promesas, conviene despejar el malentendido principal.

¿Qué significa realmente que sea una Azure SQL Database en Fabric?

Cuando Microsoft dice que SQL Database en Fabric está “basada en Azure SQL Database”, no está jugando con las palabras. Usa el mismo SQL Database Engine que Azure SQL Database, expone TDS, se puede atacar con SSMS, VS Code, sqlcmd o bcp, y mantiene una experiencia T-SQL muy reconocible para cualquiera que lleve años peleándose con SQL Server y su descendencia cloud. Hasta aquí, bien, no es un juguete con icono nuevo y marketing con esteroides.

Ahora viene la parte que importa. No es “Azure SQL Database metida dentro de un workspace” y listo. El contrato de servicio cambia. El licenciamiento cambia. El modelo de consumo cambia. La red cambia. La seguridad cambia. Y varias capacidades de plataforma que en Azure SQL ya damos por sentadas aquí no están, o han llegado más tarde, o llegan con otra forma. Dicho de otro modo, el motor sí, el producto no del todo. Y en arquitectura de datos, como ya sabemos, el diablo se esconde en la letra pequeña

Aquí está la clave técnica que explica casi toda la propuesta.

Arquitectura: no es un único almacén, son dos representaciones coordinadas

SQL Database en Fabric guarda sus datos operacionales en ficheros .mdf, igual que Azure SQL Database, pero además replica automáticamente los datos a OneLake en formato Delta Parquet. Sobre esa copia se crea un SQL analytics endpoint de solo lectura, accesible por TDS, para lanzar consultas analíticas sin castigar el workload transaccional. El espejo arranca al crear la base de datos, no requiere configuración manual y, en su comportamiento base, siempre ha estado activado. Técnicamente, por tanto, no hablamos de “el mismo dato en el mismo motor para todo”, sino de una base operacional más una representación analítica mantenida casi en tiempo real dentro de la misma plataforma.

Eso hace que el nuevo mensaje de “translítico” que nos quieren vender tenga su parte de verdad pero también una gran parte de jerga comercial. Sí, los datos operativos quedan disponibles casi al momento para analítica, Spark, notebooks, Power BI y otras piezas de Fabric. Pero no porque el OLTP y la analítica compartan mágicamente el mismo camino de ejecución, sino porque Fabric automatiza el reflejo a OneLake y pone un endpoint analítico encima. El resultado práctico puede ser muy bueno. La simplificación conceptual que a veces se cuenta, no tanto.

Una vez entendido eso, ya podemos responder la pregunta incómoda de verdad.

Anatomía interna: plano de control, plano de datos y replicación

Si queremos entender de verdad qué es SQL Database en Fabric, no basta con decir que “es Azure SQL dentro de Fabric”. Hay que separar claramente el plano de control del plano de datos. Y aquí está una de las claves del producto. 

La experiencia de creación, gobierno, acceso y operación vive en Fabric, a través de su control plane y su UX. Pero la base de datos operacional sigue ejecutándose sobre infraestructura de Azure SQL, con almacenamiento propio de datos, log y copias de seguridad, y con un formato de almacenamiento transaccional clásico orientado a rowstore. Es decir, el envoltorio operativo es Fabric, pero el corazón que procesa las transacciones sigue siendo Azure SQL Database.

Ese matiz importa porque desmonta una simplificación bastante extendida. No estamos escribiendo directamente sobre tablas Delta en OneLake ni usando el lake como backend transaccional milagroso. La aplicación entra por el endpoint SQL, habla TDS con el motor relacional y trabaja sobre una base operacional de verdad. Después, y de forma desacoplada, Fabric replica ese contenido hacia OneLake casi en tiempo real para exponerlo en formato Delta/Parquet al resto de motores analíticos de la plataforma. Esa réplica alimenta el SQL analytics endpoint y deja los datos listos para que Warehouse, Lakehouse, notebooks o Power BI los consuman sin castigar el workload OLTP.

Visto así, la arquitectura tiene dos caminos distintos. El primero es el camino operacional: aplicación, gateway, motor SQL, almacenamiento transaccional y gestión automática del servicio. El segundo es el camino analítico: mirroring hacia OneLake, persistencia en Delta/Parquet y consumo desde los motores analíticos de Fabric. Microsoft vende esto como translítico, y la palabra no es del todo humo, pero tampoco conviene leerla con demasiada poesía. No es que una misma estructura sirva simultáneamente para OLTP y analítica pesada sin coste ni compromiso. Lo que ocurre es algo bastante más sensato: el dato nace en una base transaccional y Fabric lo proyecta automáticamente a un formato analítico común dentro de OneLake. Eso está muy bien diseñado. Y, por una vez, el truco real es más interesante que el eslogan.

Aquí además hay un detalle importante para el bolsillo y para la operación. La replicación desde SQL Database en Fabric hacia OneLake no consume coste de cómputo en CUs, y Microsoft indica que ese mirroring tiene latencia cercana al tiempo real. Es decir, el servicio no solo evita que montemos una canalización adicional para mover datos al plano analítico, sino que además no penaliza la capacidad por el mero hecho de reflejarlos. El consumo empieza cuando explotamos esos datos con otros motores, no cuando Fabric los materializa en OneLake. Que esto sea así cambia bastante la conversación, porque convierte la réplica en una capacidad estructural del producto y no en otro peaje operativo disfrazado de integración “moderna”.

Desde el punto de vista de arquitectura de datos, la consecuencia práctica es muy clara. SQL Database en Fabric no es un sustituto de Warehouse ni de Lakehouse, sino una pieza intermedia que conecta el mundo operacional con el analítico sin obligarnos a montar fontanería extra desde el minuto uno. Su valor no está en reinventar el motor SQL, sino en empaquetar el plano transaccional y el plano analítico dentro del mismo perímetro de gobierno. Y ahí es donde realmente tiene sentido: menos integración manual, menos duplicidad de circuitos y más cercanía entre la base que da servicio y la plataforma que analiza. Siempre, claro, que tengamos presente que son dos representaciones coordinadas del dato y no una fusión mística entre OLTP y analítica que resuelva por arte de magia todos los pecados de diseño acumulados durante años.

¿Hasta qué punto es SQL de verdad?

La respuesta es bastante. Soporta el motor relacional que esperamos para OLTP, tablas transaccionales, ACID, claves foráneas, stored procedures, vistas, funciones, aislamiento desde serializable hasta read committed snapshot, tuning automático e indexación automática de non-clustered según datos reales de ejecución. Para cargas operacionales normales, APIs, aplicaciones internas, ODS y bases de datos de servicio, el sabor es inequívocamente SQL. No hay que reaprender a hablar con la base de datos porque alguien haya decidido que todo debía acabar en “Lake”.

Pero tampoco conviene venderlo como paridad plena con Azure SQL Database. No hay SQL Authentication, solo Microsoft Entra ID. No hay logins de servidor ni roles a nivel servidor. SQL Server Agent tampoco está, y Microsoft te empuja a pipelines o Airflow. Tampoco están failover groups, geo-restore, elastic jobs, elastic pools, DMS, DMA, VNet endpoints o resource pools. Además, hay restricciones de superficie, no se pueden crear tablas in-memory, ledger, ledger history ni Always Encrypted, y ciertas capacidades siguen en preview, como OPENROWSET BULK, full-text indexing o algunas opciones de ALTER DATABASE SET.

Hay otra diferencia sutil pero importante. Las consultas cross-database con nombres de tres partes existen, pero el camino soportado pasa por el SQL analytics endpoint, no por el plano transaccional clásico. Es decir, el “todo habla con todo” existe, sí, pero vive del lado analítico. Eso tiene lógica técnica (y en Azure SQL Database es igual), aunque desmonta un poco la fantasía de que toda la plataforma es un gran SQL Server cósmico con camiseta de Fabric. No lo es, por suerte y por desgracia.

El siguiente punto es donde muchos proyectos se ganan o se arruinan el presupuesto.

Escala y consumo: hasta dónde llega y cómo te cobra el chiste

Llegamos a la parte escabrosa. Microsoft coloca SQL Database en Fabric en el rango de datos estructurados de volumen moderado, desde varios GB hasta unos pocos TB. La documentación de arquitectura para Fabric lo sitúa claramente por debajo del terreno natural de Warehouse o Lakehouse cuando hablamos de big data, petabytes, tablas multi-TB y analítica masiva. Dicho sin diplomacia, esto no es el nuevo sitio donde aparcar todo “porque total también es SQL”. Para eso ya tenemos suficientes cementerios de arquitectura.

En límites documentados, la base puede escalar hasta 32 vCores y 4 TB, con tempdb de hasta 1.024 GB y throughput de escritura de log de hasta 50 MB/s. Además, Microsoft ha introducido un control máximo de vCores, aún en preview, que permite acotar el techo de cómputo. La propia documentación muestra el rango entre 4 y 32 vCores y deja claro que el servicio hace autoscaling dentro de ese tope. Es decir, escala sí, pero dentro de un corral bastante definido. Muy útil para OLTP moderno y ODS razonables. Menos impresionante cuando uno viene de leer promesas grandilocuentes sobre plataforma unificada universal definitiva, edición coleccionista.

El modelo de consumo es lo que cambia la conversación. Aquí no compras una base de datos con su SKU aislada, sino que consumes capacidad Fabric compartida. Un CU de Fabric equivale aproximadamente a 0,383 vCores de base de datos, y una F64 equivale a unos 24,512 vCores de SQL Database. La base autoscala, mantiene un mínimo de 2 GB de memoria mientras está online, y tras 15 minutos de inactividad para y libera CPU y memoria, eso sí, se sigue facturando el almacenamiento. Eso suena bien hasta que recuerdas que esa misma capacidad también la usan otros workloads de Fabric. Ahí empieza la parte divertida, en el sentido en que también es divertida una alerta a las tres de la mañana.

Particularidades de consumo de Fabric.

Los consumos en Fabric se dividen en dos tipos, los interactivos y los de background.

Y esto es un matiz decisivo, el consumo de SQL Database es una operación interactiva. En el Metrics app, “SQL Usage” recoge el coste de todas las sentencias T-SQL generadas por usuarios y por sistema, y cuando la capacidad entra en throttling las consultas pueden llegar a registrarse como rechazadas. Comparado con Warehouse, donde el consumo de consulta figura como background, aquí estamos mucho más cerca del mundo de la aplicación viva que del batch analítico tranquilo. 

Dicho en lenguaje DBA SQL Server, un consumo interactivo es el que nace de una petición que alguien espera resolver ya: una query lanzada desde la aplicación, desde SSMS, desde un informe o desde cualquier proceso que está dando servicio en ese momento. El consumo en segundo plano, en cambio, es el trabajo diferido que la plataforma puede ejecutar con otra prioridad, como una carga, una transformación o una consulta analítica que no está sosteniendo la interacción directa de un usuario. SQL Database en Fabric cae en el primer grupo porque está pensado para cargas operacionales y transaccionales, no para esperar disciplinadamente su turno.

La implicación es clara, hay que competir no solo con lo que se está ejecutando ahora mismo sino con la parte proporcional (Smoothing) de los trabajos de backgrpund que se han ejecutado en las últimas 24 horas. Y claro, si la capacidad va justa, el mayor impacto lo sufre el workload vivo, el de SQL que va a ver más latencia, menos estabilidad y posibles rechazos.

Con esto claro, ya se entiende mejor la parte económica y de seguridad.

Licenciamiento, acceso y la letra pequeña

Para usar SQL Database en Fabric necesitas una capacidad válida de Fabric, Power BI Premium o Trial, y la facturación sigue el modelo de capacidad de Fabric, no el de Azure SQL Database. Los cargos aparecen en Azure Cost Management bajo la suscripción asociada a la capacidad. El coste combina cómputo y almacenamiento, y el backup storage solo empieza a cobrarse cuando supera el 100 % del tamaño aprovisionado de la base. Es un modelo cómodo para centralizar gasto, pero borra la separación mental entre “mi base de datos” y “la capacidad del resto de Fabric”, que, para la analítica contable, no siempre es una buena noticia.

En cuanto a accesos la historia es sencilla pero dura a la vez, solo podemos usar Entra ID. No hay SQL logins. Tampoco hay sa. Ni hay ese usuario legacy que vive de cadenas de conexión con usuario y contraseña incrustados desde 2017 “porque nunca dio problemas”. Además, el acceso mezcla dos planos de autorización que hay que tener siempre en mente. Por un lado primero tenemos que tener acceso a Fabric y por otro los permisos nativos SQL dentro de la base. Microsoft lo describe como una superposición “most permissive”, así que conviene dar acceso de conexión con Fabric y afinar de verdad la seguridad en el plano SQL. Seguridad moderna, sí pero también fricción con aplicaciones legacy.

Aquí además hay una novedad relevante. Tras la FabCon de marzo de 2026, Microsoft ya recoge como GA la auditoría para SQL Database en Fabric y las customer-managed keys con TDE automático a nivel de workspace. También anuncia recuperación de bases borradas y retención de backup configurable entre 1 y 35 días. 

Y aquí conviene separar copia de seguridad operativa de disaster recovery real, porque no son lo mismo aunque a veces se vendan como si lo fueran. SQL Database en Fabric sí mantiene copias automáticas y permite point-in-time restore, con retención configurable entre 1 y 35 días, pero la restauración crea una base nueva dentro de Fabric y la documentación sigue marcando como no soportados el cross-workspace restore y el cross-region restore. Traducido al mundo real: estas copias nos cubren muy bien frente a borrados accidentales, despliegues fallidos o una metedura de pata humana, pero no son una copia portable que podamos sacar y restaurar donde nos convenga. Si queremos una estrategia de DR seria fuera de ese perímetro, hay que exportar periódicamente a BACPAC con SqlPackage y guardarlo en otra región o en almacenamiento externo, que es precisamente la vía que Microsoft recomienda para un fallo regional.

Con todo eso encima de la mesa, toca la pregunta estratégica.

¿Dónde sí tiene sentido el relato translítico y dónde todavía no?

Sí la pregunta es si todo esto de tener la parte operacional y la analítica juntas, si tiene sentido cuando quieres un núcleo operacional gobernado dentro de Fabric, con latencia baja, integridad relacional, tooling SQL clásico y una salida analítica casi inmediata sin montar otro circuito de ingestión. Ahí encajan muy bien los casos de uso que Microsoft empuja de forma oficial (Operational Data Store, reverse ETL y aplicaciones translíticas). También encaja para equipos que ya viven en Fabric y quieren reducir el impuesto de integración entre la base operativa y el resto del ecosistema.

Sin embargo, no tiene tanto sentido cuando tu analítica real pide otra cosa, grandes escaneos, históricos pesados, modelos dimensionales complejos, muchísima concurrencia analítica, ingestas masivas o escalado hacia decenas de TB y PB. Ahí Fabric ya tiene mejores piezas, y la propia guía de Microsoft coloca Warehouse, Lakehouse o Eventhouse por delante según el patrón. Tampoco lo veo claro si dependes de capacidades maduras de Azure SQL Database que aquí aún faltan, o si necesitas un aislamiento de red y de cómputo mucho más predecible. Una plataforma unificada ahorra fricción, sí, pero también puede concentrar demasiadas dependencias en el mismo sitio. Y eso solo parece bonito hasta el primer incidente transversal.

Queda la parte que de verdad ayuda a decidir.

Pros, contras y lo que le pediría para ser realmente usable

La principal virtud de SQL Database en Fabric es que resuelve muy bien el espacio intermedio que durante años ha quedado incómodo, una base operacional moderna, bastante SQL de verdad, con integración directa en la plataforma analítica y sin bricolaje constante entre servicios. Para ODS, serving layers, APIs, aplicaciones internas y escenarios donde OLTP y consumo analítico conviven cerca, la propuesta tiene mucho sentido. Y el hecho de que el espejo a OneLake salga de serie elimina una cantidad obscena de fontanería que hasta ahora hacíamos “a mano” y luego fingíamos que era arquitectura elegante.

Sus peajes están claros. La paridad con Azure SQL Database aún no es suficiente para ciertos entornos serios. El aislamiento de capacidad es más difuso. La dependencia de Entra ID para usuarios corta de raíz algunos escenarios heredados. La historia de red sigue siendo menos madura de lo que muchos equipos enterprise pedirían. Y la documentación aún necesita dejar de contradecirse entre tablas, notas de lanzamiento y páginas de detalle, algo normal para un producto tan nuevo por otra parte. Pero claro, en una solución que quiere ganarse a DBAs, eso no es un matiz: es parte del producto.

¿Qué le pediría para que sea más usable? 

Hasta aquí la teoría, ahora me voy a mojar y os voy a dar mi opinión. Para mi, para hacer esto más usable pediría menos épica y más nitidez. Quiero una matriz de compatibilidad viva y fiable, una historia de migración de primera división, con DMS o equivalente real. Por pedir, quiero una solución de DR más madura, con geo-restore y failover groups. Y por supuesto, aislamiento y control de red más directos por base o por workspace sin rodeos ceremoniales. Quiero observabilidad y gobierno de capacidad cada vez más finos, porque cuando una base operacional compite por CUs con media plataforma, el problema ya no es solo de base de datos, es de convivencia. Y la convivencia, como sabemos, nunca se arregla con una keynote.

SQL Database en Fabric no viene a sustituir Azure SQL Database ni a jubilar Warehouse. Viene a ocupar un hueco muy concreto, y cuando encaja, encaja francamente bien. Pero conviene comprarla por lo que es, no por lo que el folleto insinúa. Es SQL, sí. Bastante SQL. Pero sobre todo es SQL bajo las reglas de Fabric. Y esa diferencia es exactamente la que decide si esto acaba siendo una gran pieza de plataforma o una bonita confusión con logo nuevo.

Conclusión

SQL Database en Fabric me parece una solución bastante más seria de lo que algunos quieren admitir, pero también bastante menos mágica de lo que Microsoft insinúa. Cuando el problema es OLTP moderado, integración rápida con analítica y menos fontanería entre la base operacional y el resto de la plataforma, encaja muy bien. Cuando necesitamos aislamiento más predecible, una historia de DR madura, más superficie de Azure SQL y menos dependencia del estado general de la capacidad, todavía no. No viene a sustituirlo todo, ni falta que hace. Viene a ocupar un hueco concreto, y ahí puede funcionar francamente bien. El error sería comprar el eslogan en lugar de entender la pieza. Porque aquí la diferencia importante no es que sea SQL. La diferencia importante es bajo qué reglas juega ese SQL.

Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de LinkedIn y un canal de YouTube a los que te puede unir. ¡Hasta la próxima!

Publicado por Roberto Carrancio en Cloud, SQL Server, 0 comentarios
TDE, Always Encrypted, TLS y DDM: cuándo usar cada uno

TDE, Always Encrypted, TLS y DDM: cuándo usar cada uno

Lo sé, llevo más de un mes sin publicar artículos en el blog. No ha sido precisamente porque se me haya olvidado escribir. He estado metido hasta el cuello preparando cursos y sacando adelante otros proyectos. Parece que no pero estas cosas consumen las horas con una eficacia admirable y una compasión nula. El canal de YouTube también lleva cerca de dos meses parado por lo mismo. Así que vamos a retomar ambas cosas poco a poco, con algo que además creo que merece la pena.

Hace unos días me dejaron un comentario bastante sensato en un vídeo antíguo donde explicaba cómo funciona TDE en SQL Server. @eadames2 venía a decir que el vídeo era demasiado básico y que faltaban ejemplos de vida real, contexto y, sobre todo, criterio para decidir qué método de cifrado conviene según el caso. Y sí, la observación es buena. En el vídeo enseñé el cómo. Hoy, aquí, toca hablar del cuándo y del para qué.

Sobre cifrado ya había publicado en el blog el artículo “Cifrado de datos en SQL Server”, donde repasaba TLS, TDE, Always Encrypted y DDM, y también otro texto sobre qué pasa con la inicialización instantánea de ficheros al habilitar TDE, que entra en una consecuencia operativa muy concreta. No voy a repetir aquí lo que ya está explicado allí. Lo que quiero hacer en este artículo es completar esa parte que muchas veces se queda fuera: cómo elegir bien según la amenaza real, el tipo de datos y el precio operativo que estamos dispuestos a pagar.

Antes de entrar en tecnologías concretas, conviene poner orden en una idea que suele venir torcida de fábrica.

El error habitual: elegir tecnología antes de definir la amenaza

Cuando alguien dice que quiere “cifrar la base de datos”, casi nunca está describiendo un requisito. Está describiendo una intuición. Y las intuiciones, en seguridad, suelen ser un punto de partida aceptable y un punto de llegada desastroso.

No es lo mismo proteger datos frente al robo de backups que impedir que un DBA vea una información concreta. Tampoco es lo mismo ocultar información sensible a usuarios funcionales que proteger el tráfico entre aplicación y servidor. Meter todo eso en la misma cesta y resolverlo con una sola tecnología suele acabar como acaban estas cosas: con un checkbox marcado, una falsa sensación de seguridad y una reunión desagradable más adelante.

TDE, Always Encrypted, TLS y DDM no compiten entre sí en todos los escenarios. A veces se complementan y a veces uno no sirve absolutamente para nada si el problema real está en otra parte. Por eso la pregunta correcta no es “qué método cifra más”. La pregunta correcta es “de qué quiero protegerme exactamente y quién es el adversario aquí”.

Ese matiz cambia bastante la conversación, así que vamos con casos reales.

Caso real 1: alguien roba un backup o se lleva los ficheros de la base de datos

Aquí es donde TDE encaja muy bien. Si tu preocupación principal es que alguien coja un .bak, un .mdf, un .ndf o un .ldf y se lo lleve alegremente a otro servidor para restaurarlo sin permiso, TDE es una solución razonable y bastante transparente.

La gran ventaja de TDE es precisamente esa, protege los datos en reposo sin obligarte a rediseñar la aplicación ni a reescribir consultas. El usuario legítimo sigue trabajando igual, y el motor cifra y descifra por debajo. En entornos corporativos donde el riesgo está en el acceso físico a discos, en copias de seguridad mal custodiadas o en procedimientos de restauración fuera de control, TDE tiene muchísimo sentido.

Ahora bien, conviene no pedirle milagros. TDE no evita que alguien con acceso lógico a la base de datos y permisos suficientes consulte los datos. No te protege de un SELECT bien autorizado, ni de un desarrollador con más privilegios de los que debería, ni de ese clásico “es solo para una prueba” que termina con un usuario leyendo más de la cuenta. TDE protege archivos y backups. No arregla un modelo de permisos chapucero, que es otra afición muy extendida.

Además, TDE tiene peaje. Ya conté en el artículo sobre inicialización instantánea de ficheros que al activarlo perdemos ciertas ventajas operativas y podemos notar impacto en crecimientos, restauraciones y tiempos de ciertas operaciones. Y hay otro punto que en las demos parece un detalle y en producción no lo es, el certificado. Si no haces backup del certificado y de su clave privada, el día que necesites restaurar en otro servidor te puedes ahorrar el café, porque no vas a restaurar nada. Si cifras con TDE y no haces copia de seguridad del certificado y de su clave privada, tu backup queda protegido incluso contra ti mismo. Muy seguro todo. Muy poco práctico también.

No todos los escenarios exigen llegar tan lejos. A veces el problema no es que alguien robe un backup, sino que ciertos usuarios ven más de lo que deberían ver en el día a día.

Caso 2: algunos usuarios no deberían ver los datos completos

Aquí entra DDM, y aquí conviene hablar sin maquillaje, porque bastante tiene la tecnología con el suyo propio. Dynamic Data Masking no es cifrado. Sirve para ocultar parcialmente datos cuando los consulta un usuario que no tiene permiso para verlos completos, pero el dato sigue estando almacenado tal cual en la base de datos.

Eso puede ser útil. En entornos de soporte, atención al cliente, explotación o consultas operativas, muchas veces necesitamos que ciertos perfiles trabajen con datos reales sin exponerles el valor completo de una columna sensible. Mostrar parte de un correo, ocultar tramos de un teléfono o limitar la visualización de un identificador puede tener bastante sentido. Reduce la exposición innecesaria y evita errores humanos bastante previsibles.

El problema viene cuando alguien intenta vender DDM como si resolviera necesidades de seguridad de alto nivel. No. DDM no protege un backup robado, no impide que el motor lea el dato y no sustituye ni a TDE ni a Always Encrypted. Lo que hace es modificar la presentación del dato para determinados usuarios. Nada más. Nada menos. Y mientras entendamos eso, puede ser perfectamente válido.

En otras palabras: si tu requisito es “que el personal de soporte no vea el valor completo del documento de identidad”, DDM puede encajar. Si tu requisito es “que nadie pueda extraer el dato real de la base si accede a los ficheros” o “que ni siquiera ciertos administradores puedan verlo”, entonces DDM no te sirve. Ahí ya estarías usando una cortina para parar un incendio, que tiene un punto optimista, pero poca eficacia.

A veces, sin embargo, el nivel de exigencia sube bastante más. Y en ese punto ya no basta con ocultar visualmente una parte del dato.

Caso 3: ni siquiera el DBA debería ver ciertos datos

Cuando el requisito es que ni siquiera un administrador de base de datos pueda consultar ciertos valores en claro, TDE y DDM se quedan cortos por definición. TDE porque el motor necesita descifrar la información para trabajar con ella. DDM porque solo maquilla la salida para algunos usuarios. Si el objetivo es separar de verdad quién puede ver el dato y quién solo puede administrarlo, entonces toca mirar Always Encrypted.

Always Encrypted está pensado para columnas concretas y para escenarios donde los datos son especialmente sensibles. Hablamos de información médica, datos financieros, salarios, identificadores personales o cualquier campo donde el requisito no sea simplemente proteger discos y copias de seguridad, sino impedir que ciertos perfiles con acceso a la infraestructura puedan leer el valor real. Es una diferencia importante.

La gracia de Always Encrypted está precisamente en esa separación. Las claves no se gestionan como en TDE y el modelo de confianza cambia bastante. Eso hace que el nivel de protección sea superior en algunos escenarios, pero también introduce complejidad técnica. No todas las consultas pueden hacerse igual, no todas las operaciones son cómodas y el desarrollo de la aplicación tiene que convivir con esas limitaciones. Vamos, que no es una opción para activar con alegría y descubrir el lunes que media aplicación ya no hace lo que hacía.

¿Merece la pena? Cuando el requisito lo exige, sí. Sin duda. Pero si solo quieres proteger backups o discos, meter Always Encrypted porque suena más serio es un error clásico. Aún hay quien cree que la mejor solución de seguridad es siempre la más compleja. 

Hasta ahora hemos hablado de datos en reposo o de visibilidad dentro de la propia base. Pero queda una capa distinta, y conviene separarla para no mezclar churras con certificados.

Caso real 4: el problema está en la red, no en el disco

Si los datos viajan entre cliente y servidor, o entre servicios, y tu preocupación es que alguien intercepte ese tráfico, entonces lo que necesitas mirar es TLS. Ni TDE ni DDM ni Always Encrypted sustituyen el cifrado del canal de comunicación.

Esto es importante porque sigue habiendo entornos donde alguien activa TDE y se queda tan tranquilo, como si eso protegiera automáticamente el tráfico por red. No. Cifrar el archivo de base de datos no convierte mágicamente en segura una conexión mal configurada. Son capas distintas y problemas distintos.

TLS es el mecanismo adecuado para proteger datos en tránsito. Si tienes aplicaciones conectadas por red, servicios hablando entre sí, réplicas, integraciones o accesos remotos, necesitas que el canal vaya cifrado y, si puede ser, bien configurado. Lo contrario es confiar en que nadie mire. Una estrategia audaz, desde luego, aunque no especialmente profesional.

En muchos sistemas reales, de hecho, la respuesta correcta no es elegir una sola opción, sino combinar varias con un poco de sentido común.

Lo normal en producción: combinar tecnologías según el riesgo real

La mayoría de entornos serios no viven de absolutos. Viven de compromisos bien pensados. Y eso significa que muchas veces la solución buena no es “TDE o Always Encrypted”, sino “TDE y además TLS”, o “TLS para todo el tráfico y DDM para ciertos usuarios de soporte”, o incluso “TDE para la base completa y Always Encrypted en columnas concretas especialmente sensibles”.

Un ERP corporativo puede necesitar TDE para proteger backups y discos, TLS para las conexiones y un modelo de permisos competente. Un sistema de recursos humanos probablemente necesite además evaluar Always Encrypted en campos muy concretos. Una herramienta de soporte interno puede apoyarse en DDM para limitar lo que ciertos perfiles ven en pantalla, sin vender eso como la octava maravilla de la seguridad.

La decisión, por tanto, no depende tanto del “tipo de base de datos” en abstracto como del tipo de dato, del modelo de acceso y del riesgo que quieres mitigar. Una base de datos de facturación interna y una de analítica pueden tener tamaños parecidos y una necesidad de protección totalmente distinta. El nombre del sistema importa menos que la exposición del dato y las personas que pueden tocarlo.

Con todo esto encima de la mesa, ya se puede responder de forma más útil a la pregunta del comentario.

Entonces, ¿qué método conviene según el caso?

Si lo que te preocupa es el robo de copias de seguridad o de archivos físicos, empieza por TDE. Es la opción natural, tiene un impacto asumible en muchos entornos y protege precisamente ese escenario. Si además activas TDE, haz bien el trabajo completo: gestiona certificados, documenta el procedimiento de recuperación y prueba restauraciones. Porque un TDE sin backup del certificado es una bomba de relojería con modales.

Si el problema es que determinados datos no deberían estar visibles ni para personal con privilegios altos en la infraestructura, entonces TDE no basta y hay que mirar Always Encrypted. Aquí la complejidad sube, sí, pero también lo hace el nivel de aislamiento real.

Si lo que necesitas es limitar lo que ven ciertos usuarios operativos sin cambiar la aplicación de arriba abajo, DDM puede ser útil, sabiendo perfectamente que no estás cifrando nada. Y si la preocupación es el tráfico entre cliente y servidor, no des más rodeos y configura TLS como corresponde.

Dicho de otra manera: TDE protege datos en reposo a nivel de archivos y backups. Always Encrypted protege columnas frente a accesos que no deberían ver el valor real. DDM limita exposición visual en consultas para ciertos perfiles. TLS protege el canal de comunicación. Confundirlos es bastante común. Elegirlos bien ya no debería serlo tanto.

Conclusión

El comentario de @eadames2 iba bien encaminado: enseñar a activar TDE está bien, pero no basta si no explicamos cuándo tiene sentido usarlo y cuándo no. En seguridad, la tecnología correcta no es la más llamativa ni la más compleja, sino la que responde a la amenaza real sin convertir la operación diaria en una penitencia.

Ya tenemos en el blog el artículo general sobre cifrado en SQL Server y el análisis del impacto de TDE sobre la inicialización instantánea de ficheros. Este texto viene a completar esa parte que faltaba: el criterio. Porque cifrar por cifrar sirve de poco. Lo útil es saber qué proteges, de quién lo proteges y cuánto te va a costar mantenerlo. Lo demás es decorar el problema con terminología bonita y esperar que nadie haga demasiadas preguntas.

Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de Telegram y un canal de YouTube a los que te puede unir. ¡Hasta la próxima!

Publicado por Roberto Carrancio en Cloud, SQL Server, 0 comentarios

BBDD relacionales gratis: opciones en 2026

Durante años, “base de datos relacional gratis” se traducía en una de dos cosas: MySQL por inercia o SQLite por necesidad. Y, si estabas en Windows, SQL Server Express era ese invitado que venía a la fiesta… pero se quedaba sin bebida a los 10 GB. Pues bien: Microsoft ha decidido que ya está bien de hacer el ridículo en este segmento.

SQL Server 2025 Express sube el límite máximo por base de datos a 50 GB y, de paso, elimina el baile de “Express con Advanced Services” porque ahora lo integra en la edición Express. Es un movimiento simple, directo y con mala leche competitiva: “si lo gratis te sirve para una PYME, quizá luego ya pagas”. Y no es mala estrategia.

Antes de meternos en harina, dejemos claro el marco mental: aquí no estamos eligiendo la “mejor” BBDD en abstracto. Estamos eligiendo una herramienta gratis que no te obligue a pagar con sangre en producción: mantenimiento, soporte, migraciones, rendimiento y, sobre todo, expectativas realistas.

Este giro de Microsoft da para abrir el melón: ¿puede SQL Server Express competir de verdad en el terreno de las BBDD relacionales gratuitas, o llega tarde y con limitaciones que lo condenan a “edición de prueba eterna”?

SQL Server Express 2025: La BD gratis perfecta para entornos Windows

SQL Server Express 2025 ya no muere de éxito al crecer un poco. El salto de 10 GB a 50 GB por base de datos cambia el tipo de proyectos donde encaja: aplicaciones de gestión, contabilidad, CRM de PYME, ERPs modestos, integraciones internas… ese mundo on-prem que sigue existiendo aunque a algunos les duela admitirlo.

Ahora bien, lo que Microsoft te da con una mano, te lo recuerda con la otra: Express sigue limitado en cómputo y memoria. La documentación oficial habla de “1 socket o 4 cores” y un buffer pool máximo de 1.410 MB. Es decir, 50 GB sí, pero no esperes que un informe criminal de fin de mes vuele si te dedicas a escanear tablas como si fueran cromos.

En entornos Windows empresariales, SQL Server Express juega con ventaja: instalador, tooling, drivers, autenticación integrada, ecosistema. Y aquí es donde muchos DBAs lo hemos visto triunfar sin aspavientos: un servidor Windows en una PYME, una app “de las de toda la vida” y un proveedor que no quiere complicarse la vida con stack Linux. Sí, puedes dejarlo todo en db_owner y también puedes freír huevos en la placa base. Ambas son malas ideas.

Si quieres verificar rápido qué tienes instalado y en qué edición estás, con esto basta:

Y si te preocupa el techo de memoria del motor (porque deberías), la tabla de límites por edición es bastante clara: Express vive en el barrio del 1,4 GB de buffer pool.

¿Puede Express pelear en web o la liga gratis ya se juega sin Microsoft?

La web “barata” lleva décadas en LAMP y derivados, así que aquí SQL Server siempre ha tenido que remar a contracorriente. Aun así, con 50 GB ya no se cae a la mínima, y el cambio de “Express Advanced Services desaparece porque ahora viene integrado” también reduce fricción. Menos ediciones raras, menos decisiones estúpidas por desconocimiento.

El problema real no es técnico, es cultural y de ecosistema. Donde ya hay PHP, hosting compartido, paneles de control y proveedores que viven de desplegar WordPress como churros, SQL Server no es el camino por defecto. Y esto importa más de lo que nos gustaría a los que vivimos en T-SQL.

Dicho esto, en la web corporativa interna, en intranets, en integraciones con Active Directory, en aplicaciones .NET de gestión… ahí Express sí puede competir con mucha dignidad. La pregunta no es “¿es el mejor motor?”, sino “¿cuánto te cuesta operarlo con tu equipo y tu contexto?”. En PYMES, eso pesa toneladas.

SQLite: cuando quieres una BD gratis … pero no un servidor

SQLite es el recordatorio incómodo de que muchas veces no necesitas un motor cliente-servidor, sino un fichero fiable y transaccional. SQLite es una librería embebida, serverless, autocontenida y con cero configuración real. Lo metes en tu aplicación, y a correr.

Eso sí, SQLite no es magia. Su modelo de concurrencia tiene límites muy concretos. Para escribir, necesitas un bloqueo exclusivo; solo puede haber un escritor a la vez, y la forma en la que gestiones transacciones y tiempos de bloqueo decide si tu app vive o se llena de SQLITE_BUSY.

Con WAL (Write-Ahead Logging) mejoras la convivencia entre lecturas y escrituras, los lectores no bloquean al escritor y viceversa, pero sigues sin tener “concurrencia de escritores” a lo loco. Es decir, para escenarios sin mucha concurrencia de escritura, o donde el patrón es “muchas lecturas, pocas escrituras”, SQLite es brillante. Para una API con ráfagas de escrituras simultáneas, es una invitación a sufrir.

SQLite encaja de maravilla en escritorio, móvil, IoT, cachés persistentes, herramientas internas, prototipos serios y servicios pequeños donde te interesa simplicidad por encima de todo. Y sí, lo de “es solo para juguete” lo suele decir alguien que no ha leído la documentación desde 2009.

PostgreSQL: la alternativa gratis que gana terreno porque no vive del pasado

Si me preguntas qué motor open source está ganando terreno con más consistencia, PostgreSQL aparece en la conversación antes de que termines la frase. No porque sea “moderno”, sino porque lleva años haciendo bien lo básico y lo difícil: transacciones, concurrencia, extensibilidad, tipos avanzados, rendimiento y una comunidad que no depende de que a una corporación le apetezca publicar commits este trimestre.

En datos de uso por desarrolladores, PostgreSQL aparece como el entorno de base de datos más utilizado en la encuesta de Stack Overflow 2025 (55,6%), por delante de MySQL (40,5%). No es “cuota de mercado” pura, pero sí es una señal fuerte de hacia dónde mira quien construye software hoy.

En el mundo real, PostgreSQL brilla cuando quieres portabilidad, cuando no quieres casarte con un proveedor concreto, cuando tu modelo de datos crece en complejidad o cuando necesitas features potentes sin pagar licencia. Y también cuando quieres dormir tranquilo sabiendo que el proyecto no está “mantenido por accidente”.

¿La pega? Migrar desde MySQL no siempre es trivial. Dialectos, funciones, colaciones, tipos, procedimientos, y esa colección de “pequeñas diferencias” que se convierten en semanas si nadie las planifica. Aun así, cada vez más equipos consideran que el esfuerzo compensa.

MySQL: el rey por herencia… y eso no es un cumplido

MySQL sigue siendo enorme. En popularidad tipo DB-Engines aparece en lo más alto del ranking relacional (segunda tras Oracle en enero de 2026). Y si miras muestras de tecnología en sitios web, Datanyze lo coloca como #1 en su categoría “Databases” con un 21,32% en su dataset.

Ahora viene la parte que muchos prefieren ignorar, herencia no es lo mismo que futuro. MySQL ha sido “la base de datos por defecto” de gran parte del hosting web durante años, y WordPress ha tenido muchísimo que ver en ese dominio. Pero la propia comunidad de WordPress muestra un dato muy revelador: según estadísticas resumidas en junio de 2025, MariaDB ya superaba a MySQL en sitios WordPress (52,8% vs 47,2%). Ese cambio no es teórico, el reinado de MySQL ya pasó.

Y luego está el elefante en la habitación, la actividad pública del repositorio. A fecha 13 de enero de 2026, DevClass reporta que el repositorio GitHub de MySQL Server no recibía commits desde septiembre de 2025, alimentando la percepción de abandono por parte de Oracle o, como mínimo, de desarrollo “a puerta cerrada” priorizando productos comerciales alrededor. Esto no prueba que MySQL “esté muerto”, pero sí afecta a confianza, contribuciones y comunidad.

MySQL puede seguir siendo dominante un tiempo largo, porque cambiar motores en empresas cuesta y da miedo. Pero cuando lo que te mantiene arriba es la inercia, cualquier giro del mercado te hace daño.

MariaDB: el reemplazo natural… hasta que deja de ser “drop-in”

MariaDB nació como fork de MySQL y lleva años intentando ser, de forma explícita, el sucesor natural para quien quiere compatibilidad sin depender de Oracle. La propia MariaDB Foundation insiste en esa narrativa de “successor” y en que la mayoría de usuarios no encuentran problemas de compatibilidad en su día a día.

En la práctica, MariaDB ha ganado muchísimo terreno en hosting y en stacks clásicos web. Y el dato de WordPress que comentaba antes no es casualidad, si un proveedor puede cambiar de MySQL a MariaDB sin que sus clientes se enteren, lo hará. Porque es fácil, porque suele ir bien, y porque reduce riesgo de dependencia.

El matiz importante es el de siempre, “compatible” no significa “idéntico”. A medida que los proyectos divergen, aparecen diferencias en optimizador, funciones, comportamiento, versiones y soporte. Para WordPress y aplicaciones típicas LAMP, suele funcionar como reemplazo. Para software que exprime particularidades del dialecto o dependencias muy concretas, hay que probar muy bien.

Si el mercado web se disputa hoy entre MariaDB y PostgreSQL, MariaDB juega con la ventaja de la continuidad, cambiar menos para obtener algo más.

Entonces… ¿Qué BD gratis elijo si no quiero arrepentirme en seis meses?

La selección sensata empieza por aceptar que “gratis” no significa “sin coste”. El coste es operativo: personas, conocimiento, tooling, automatización, copias, recuperación, monitorización y capacidad de escalar sin convertir cada incidencia en una novela.

Si estás en una PYME Windows, con aplicaciones de gestión y un entorno donde SQL Server encaja como un guante, Express 2025 es más serio que nunca, 50 GB te cubren un montón de escenarios reales, y la integración nativa reduce fricción. No te da alta disponibilidad, pero muchas de esas empresas tampoco la tienen con MySQL, solo que lo llaman de otra forma.

Si necesitas una base embebida, local, simple y robusta, SQLite es casi imbatible. Pero si tienes concurrencia de escritura o varias instancias pegándole fuerte, no fuerces el diseño: no es un clúster, por mucho que te empeñes.

Si quieres un motor open source con tracción clara, comunidad fuerte y cada vez más adopción por desarrolladores, PostgreSQL es la apuesta que más se repite hoy.

Si vienes de MySQL por herencia web, mi consejo profesional es simple, considera seriamente MariaDB como “continuidad sin drama”, y mira PostgreSQL como “salto con futuro”. Y si decides quedarte en MySQL, que sea por motivos técnicos y de negocio, no por costumbre ni por miedo al cambio. Lo de los commits públicos no te rompe mañana, pero sí te debería incomodar.

Conclusión

SQL Server Express 2025 por fin juega en serio en el segmento “gratis”, 50 GB cambian el tipo de proyectos donde encaja, sobre todo en on-prem y entornos Windows de PYME. SQLite sigue siendo el rey cuando no quieres un servidor y tu concurrencia de escritura no es agresiva. PostgreSQL es el que más terreno gana porque la comunidad empuja y el mercado le da la razón. MySQL aguanta por herencia, especialmente web, pero la señal de actividad pública y el desplazamiento hacia MariaDB en WordPress son avisos que un profesional no debería ignorar.

Elegir bien aquí no va de religión: va de minimizar deuda técnica. Y la deuda técnica, como siempre, se paga con intereses.

Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de Telegram y un canal de YouTube a los que te puede unir. ¡Hasta la próxima! 

Publicado por Roberto Carrancio en Otros, 0 comentarios

SQL Server sobre Hyper-V: Buenas prácticas

Durante años, mencionar Hyper-V en una conversación sobre infraestructura provocaba cierto escepticismo técnico. Los más veteranos recordamos entornos de laboratorio donde el rendimiento era, siendo amables, discutible. Pero como casi todo en tecnología, lo que ayer parecía limitado, hoy puede ser perfectamente válido… si se configura bien.

Con la adquisición de VMware por Broadcom y los movimientos corporativos que han seguido (licencias perpetuas eliminadas, precios en alza y suscripciones forzadas), muchas organizaciones están redescubriendo Hyper-V como una alternativa seria. Y no hablamos solo de pequeñas empresas. Desde entornos de desarrollo hasta producción crítica, Hyper-V vuelve a estar sobre la mesa.

Eso sí, SQL Server no se virtualiza bien «de fábrica», da igual el hipervisor. Hay que saber lo que se está haciendo. Ya vimos en el pasado artículo cómo hacerlo correctamente con VMware vSphere, y ahora toca hablar de Hyper-V.

Aquí va la guía técnica para desplegar SQL Server en máquinas virtuales Hyper-V con garantías de rendimiento, estabilidad y escalabilidad. 

Configuración de CPU y topología NUMA

Hyper-V, como vSphere, expone a la VM una topología virtual de sockets y núcleos que debe estar alineada con la arquitectura física del host. SQL Server es sensible a NUMA, así que ignorar este detalle suele traducirse en latencias adicionales, penalizaciones en la caché de CPU y acceso a memoria remota.

Más aún si usas la edición Standard de SQL Server, con su famoso límite de 4 sockets o 24 núcleos. No es raro encontrar máquinas configuradas con 8 sockets y 1 core por socket: SQL Server solo podrá usar 4 de esos sockets. Has pagado por núcleos que están ahí, pero no puedes tocarlos.

Recomendación: configura tus VMs con pocos sockets y muchos núcleos por socket, alineado con tu licenciamiento y el hardware del host. Consulta sys.dm_os_sys_info y sys.dm_os_memory_nodes para verificar desde dentro de SQL Server si la segmentación NUMA es coherente.

Memoria: estática, dedicada y bajo control

Si hay algo que no debe activarse nunca en una VM de SQL Server en Hyper-V, es la memoria dinámica. Repite conmigo: no, nunca. Realmente no se debe activar en ningúna máquina virtual sea el hipervisor que sea. SQL Server gestiona su propia memoria, y necesita tener garantizada la cantidad asignada. La memoria dinámica provoca contracciones del buffer pool, intercambios de páginas y, en general, un rendimiento lamentable.

Recomendación: desactiva la memoria dinámica. Establece un tamaño fijo adecuado y deja que SQL Server se encargue de gestionarla internamente. Si activas Lock Pages in Memory, más razón aún, asegúrate de que esa memoria está siempre disponible. Y, por favor, no sobrecomprometas memoria física del host.

Almacenamiento: discos VHDX fijos, separados y bien asignados

La tentación de usar discos dinámicos (VHDs que crecen según se escriben datos) es comprensible… pero letal. Cada crecimiento de un disco dinámico introduce latencia, fragmentación, y pausas difíciles de diagnosticar. SQL Server no espera a nadie, y menos a que el disco “se amplíe”.

Recomendación: utiliza VHDX de tamaño fijo para todos los volúmenes que gestionen datos, logs o TempDB. Preasignar el espacio elimina imprevisibilidades y evita sorpresas desagradables durante picos de carga. Una vez dentro de la VM, formatea todos los volúmenes con unidad de asignación de 64 KB, como es debido.

Además, separa cada tipo de carga I/O: el volumen del sistema operativo no debe compartir canal con los datos, ni los logs con TempDB. En Hyper-V puedes tener hasta 4 controladoras SCSI virtuales por VM. Úsalas, asigna cada grupo de discos (datos, logs, TempDB, backups) a una controladora distinta. Esto reduce la serialización del tráfico de I/O y mejora el throughput.

Rendimiento de CPU: evitar la sobreasignación

Virtualizar no significa regalar recursos. Asignar más vCPUs de las necesarias (o más de las que el host físico puede manejar de forma eficiente) no mejora el rendimiento. Al contrario, genera colas, ready time, y tiempos de espera innecesarios en ejecución.

Recomendación: empieza con pocas vCPUs y escala si la carga lo justifica. Monitoriza el uso real con sys.dm_exec_requests, sys.dm_os_wait_stats, y contadores del sistema. Si detectas latencia por CPU o colas de scheduler, ajusta. Pero no asignes 100 vCPUs “por si acaso”.

Y sí, esto aplica también si vienes de un entorno con VMware y estás migrando, el redimensionamiento es una oportunidad para quitar lastre.

Plan de energía: alto rendimiento en host y VM

Sí, sigo viendo entornos donde el host Hyper-V está en modo Balanced. En 2025. Como si SQL Server tuviera que ahorrar batería. La realidad, el plan de energía tiene un impacto directo en la frecuencia de CPU, en los P-states y, por tanto, en la latencia.

Recomendación: configura el modo High Performance en la BIOS del host, en el sistema operativo del host Hyper-V y en el sistema operativo de la VM. Sin excepciones.

Separación lógica: cada tipo de carga, su volumen

Este punto es tan importante que lo repito, SQL Server necesita separar sus cargas. La unidad C: para el sistema. Otra para MDF. Otra para LDF. Otra para TempDB. Otra para backups. Cada uno tiene un patrón de acceso distinto: los logs son secuenciales, TempDB es salvaje y los datos tienen mezcla de lecturas aleatorias y escrituras diferidas. Mezclarlo todo en un único VHD es invitar al desastre.

Recomendación: usa discos separados para cada componente, idealmente en diferentes controladoras. Y si puedes aislar físicamente esos volúmenes en distintos LUNs o pools de almacenamiento, mejor aún.

Noisy neighbors: identificarlos y silenciarlos

En entornos compartidos, tu SQL Server puede funcionar perfectamente… hasta que otra VM empieza a hacer pruebas de estrés, un backup de 5 TB, o cualquier tarea con hambre de CPU o disco. Y entonces llegan los síntomas: consultas lentas, latencia intermitente, rendimiento errático.

Recomendación: monitoriza a nivel de host. Si no tienes visibilidad desde SQL Server, estás ciego. Herramientas como SQL Sentry o el propio Performance Monitor del host pueden ayudarte a detectar estas interferencias. Considera usar Hyper-V Resource Controls para establecer límites o reservas en CPU y memoria. Y si es una carga crítica, valora asignar un host dedicado.

Otras buenas prácticas esenciales

  • Integration Services y Guest Services: mantén las integraciones Hyper-V activadas y actualizadas. Mejoran la gestión, aceleran apagados y ayudan en procesos de backup y restauración.
  • Snapshots: úsalos como lo que son, herramientas de prueba. No son backups, y dejarlos activos durante días afecta al rendimiento. Elimina los checkpoints en cuanto ya no sean necesarios.
  • Backup consistente: asegúrate de que cualquier solución de backup en caliente (VSS-aware) esté bien integrada. Si no, el backup será tan fiable como un BACKUP LOG con el disco lleno.

Conclusión

Hyper-V ya no es el pariente pobre de la virtualización. Bien configurado, es perfectamente capaz de soportar cargas exigentes de SQL Server en producción. Pero hay que saber lo que se está haciendo: desactivar memoria dinámica, evitar discos thin, configurar adecuadamente NUMA, y vigilar el entorno como un halcón.

Para quienes vienen de VMware y están considerando el cambio (por licencias, por costes o por estrategia), muchos de los principios que explicamos en el artículo anterior siguen aplicando. Pero Hyper-V tiene su propio conjunto de ajustes críticos que no se deben pasar por alto.

SQL Server necesita recursos estables, configuraciones coherentes y visibilidad total. Y eso, en Hyper-V, es perfectamente posible.

Publicado por Roberto Carrancio en Rendimiento, SQL Server, 0 comentarios

SQL Server sobre VMware vSphere: Buenas prácticas

La virtualización de SQL Server ha sido durante más de una década una de las estrategias más consolidadas en entornos corporativos. VMware vSphere ha jugado un papel central en ese éxito, ofreciendo una plataforma madura, estable y altamente optimizada para ejecutar cargas de trabajo críticas como bases de datos relacionales. Sin embargo, en 2025 la situación es diferente.

Desde que Broadcom cerró la adquisición de VMware a finales de 2023, el panorama ha cambiado. La transición forzada al modelo de suscripción, la retirada de licencias perpetuas y el aumento generalizado de precios han generado un malestar evidente en muchos clientes. Algunas organizaciones han iniciado migraciones hacia Hyper-V, otras han apostado por plataformas cloud y unas pocas han optado incluso por volver al metal físico para sus cargas más exigentes.

Pero en medio de esa reconfiguración estratégica, una cosa sigue siendo cierta: vSphere sigue siendo una de las plataformas más fiables para ejecutar entornos virtualizados críticos como servidores SQL Server, siempre que se configure correctamente. Y eso, precisamente, es lo que nos ocupa en esta guía.

A continuación, abordamos en profundidad las consideraciones técnicas clave para desplegar SQL Server sobre VMware vSphere en 2025, actualizando las recomendaciones oficiales a la realidad operativa actual. Porque más allá de las decisiones de licenciamiento o la política comercial de turno, lo que importa es garantizar que nuestras bases de datos funcionen con previsibilidad, rendimiento y resiliencia.

Antes de empezar, conviene señalar que la mayoría de los fundamentos que vamos a repasar están basados en la guía oficial de VMware publicada en 2019 (Architecting Microsoft SQL Server on vSphere). No obstante, han pasado seis años desde entonces, por lo que además de recuperar los puntos más relevantes, matizaremos aquellos aspectos donde la tecnología, el hardware o las prácticas de operación han evolucionado.

Diseño correcto de la máquina virtual

Uno de los errores más comunes en despliegues SQL Server sobre vSphere es asumir que la virtualización, cómo se puede redimensionar fácilmente, elimina la necesidad de una planificación detallada. Nada más lejos de la realidad. El rendimiento y la estabilidad de SQL Server dependen en gran medida de cómo se diseñe la máquina virtual así que si, podrás cambiarlo luego pero eso no quiere decir que no lo diseñes bien de primeras.

Dimensionamiento inicial (right-sizing)

A diferencia de entornos físicos, en VMware es preferible asignar sólo los recursos que la carga realmente necesita. Asignar más CPU o RAM de la necesaria puede generar efectos negativos: contención, mayor coste de scheduling, uso ineficiente de licencias, o incluso, aunque pueda ser contraintuitivo, peor rendimiento. Una VM con más vCPU de las que necesita puede sufrir más Ready Time, más latencia y menos rendimiento.

Para dimensionar correctamente, conviene recopilar datos de uso real de CPU, memoria y disco mediante DMVs, Performance Monitor o herramientas de observabilidad (SQL Sentry, vRealize Operations). A partir de ahí, se puede asignar el número adecuado de vCPU y memoria, ajustando posteriormente según carga.

Configuración de CPU y NUMA

Núcleos por socket: impacto técnico y de licenciamiento

La edición Standard de SQL Server impone límites que no siempre se respetan al definir una VM: máximo 4 sockets o 24 núcleos. Por tanto, es frecuente encontrar configuraciones ineficientes: por ejemplo, una VM con 8 sockets y 1 core por socket, que solo permite el uso de 4 sockets con un núcleo cada uno, aunque se hayan asignado 8 núcleos.

Lo recomendable es agrupar los núcleos virtuales en menos sockets: por ejemplo, 1 socket con 8 cores, o 2 sockets con 12. Esto permite que SQL Server aproveche todos los recursos asignados sin restricciones de licenciamiento.

Consideraciones NUMA

Cuando una VM supera los recursos de un nodo NUMA físico (CPU o memoria), se producen accesos a memoria remota, lo que introduce latencia física. SQL Server es muy sensible a este comportamiento así que tenlo en cuenta.

VMware detecta la topología NUMA del host y crea configuraciones vNUMA equivalentes, pero esto solo es posible si la VM tiene más de 8 vCPU (configurable). En cualquier caso, es necesario verificar que la asignación real de nodos NUMA es coherente, tanto desde el visor de recursos del host como desde dentro de SQL Server (por ejemplo, con sys.dm_os_memory_nodes).

Asignación y gestión de memoria

Evitar el overcommit de memoria

En entornos VMware es posible sobreasignar memoria física, confiando en mecanismos como ballooning o swapping para equilibrar el uso. Pero esto es completamente desaconsejado para máquinas que ejecutan SQL Server, ya que su gestión interna de memoria (buffer pool, cache) depende de una disponibilidad constante.

La práctica recomendada es reservar memoria para la VM (memory reservation = memory size) y evitar que el host pueda utilizar parte de esa RAM para otros fines. En ESXi modernos, la opción de Transparent Page Sharing (TPS) está deshabilitada por defecto, lo que refuerza la necesidad de no sobrecomprometer recursos.

Configuración dentro de SQL Server

Dentro de la instancia, es imprescindible limitar la memoria máxima (max server memory) para evitar que el sistema operativo se quede sin recursos. Hay que tener un especial cuidado al habilitar lock pages in memory, JAMÁS se debe activar si el balloning está activado para esa VM o puede producir errores. 

Siguiendo con estas configuraciones, el uso de large pages (Trace Flag 834) puede mejorar el rendimiento en sistemas con mucha RAM, pero es muy delicado y requiere pruebas específicas. De todas formas no seré yo quien os recomiende una configuración que ni Microsoft recomienda…

Almacenamiento y controladoras

Cuando se crean discos virtuales (VMDKs) para una VM, VMware permite elegir entre discos de tamaño fijo (thick provisioned) o dinámico (thin provisioned). Aunque el aprovisionamiento dinámico puede ahorrar espacio a corto plazo, introduce fragmentación y penalizaciones de rendimiento a medida que el disco crece.

En entornos SQL Server, donde la carga de I/O es constante y predecible, el uso de discos thin puede generar latencia adicional, sobre todo en sistemas de almacenamiento que no gestionan bien el crecimiento dinámico.

La recomendación es clara, utilizar discos de tamaño preasignado (thick eager zeroed) para todos los VMDKs que manejen datos, logs o TempDB. Este tipo de disco se crea completamente al aprovisionar la VM, evitando operaciones de escritura adicionales durante el uso. Esta práctica garantiza un mejor rendimiento sostenido, especialmente en entornos con IOPS elevados, y reduce el riesgo de fragmentación interna del datastore

Separación de discos y uso de PVSCSI

Una práctica consolidada es separar los distintos tipos de archivos de SQL Server en VMDKs distintos: sistema operativo, base de datos, logs, TempDB. Esto no solo mejora el rendimiento, también facilita la gestión de snapshots, backups y análisis de uso.

En cuanto a la controladora, VMware recomienda usar PVSCSI en lugar de LSI Logic SAS para los discos de datos. PVSCSI ofrece mayor profundidad de cola (hasta 256) y menor uso de CPU. La configuración ideal combina:

  1. LSI Logic SAS solo para la unidad C:\
  2. Varias controladoras PVSCSI adicionales para datos, logs y TempDB, separadas si es posible.

Compatibilidad con NVMe

Aunque los discos NVMe han ganado presencia en datacenters en los últimos años, las recomendaciones no cambian: PVSCSI sigue siendo preferible por compatibilidad, madurez y soporte. Solo si se trabaja directamente con hardware o almacenamiento NVMe puede valorarse otra configuración, siempre tras validación en laboratorio.

Instantáneas (snapshots): limitaciones y riesgos

Los snapshots de vSphere son herramientas útiles para pruebas y cambios puntuales, pero no deben utilizarse como método de backup. En SQL Server, los discos delta que crean los snapshots generan penalizaciones de rendimiento progresivas, especialmente en entornos con alto volumen de escritura.

Es frecuente que un snapshot olvidado de semanas cause degradaciones difíciles de diagnosticar. Si hay que usarlos, deben eliminarse en horas, no días. Y siempre debe preferirse una estrategia de backup basada en herramientas nativas o soluciones de backup empresarial compatibles con SQL Server.

Red y conectividad

SQL Server puede requerir un uso intensivo de red, especialmente en escenarios con alta concurrencia, réplicas, Always On o transacciones distribuidas.

Las interfaces de red deben ser siempre VMXNET3, que ofrecen mejor rendimiento y menor latencia que E1000. Además, se recomienda activar Receive Side Scaling (RSS) tanto en el sistema operativo como en las VMware Tools, para distribuir la carga de red entre múltiples núcleos de CPU.

Si se trabaja con grandes volúmenes de datos entre nodos (como en grupos de disponibilidad o replicaciones), debe garantizarse que la infraestructura física y virtual está optimizada para latencia baja y alto throughput. 

Por ejemplo, es una buena práctica usar una VLAN e interfaz de red (física y virtual) dedicada para la comunicación entre servidores SQL, o para la conexión con los servidores de copias de seguridad.

Configuración de energía

Cuando hablamos de servidores críticos debemos primar el rendimiento a la eficiencia energética y esto implica establecer un plan High Performance en todos los niveles

El plan de energía es una de las configuraciones más olvidadas (si aun en 2025), pero con mayor impacto. Por defecto, ESXi y Windows Server pueden utilizar políticas de ahorro de energía (Balanced), que reducen la frecuencia de CPU o introducen cambios de estado (P-states) perjudiciales para cargas sensibles.

La recomendación es clara: habilitar el modo High Performance en tres capas:

  1. BIOS del host físico.
  2. Política de energía de ESXi.
  3. Plan de energía dentro del sistema operativo invitado.

Esta configuración reduce la latencia de respuesta de la CPU y evita throttling no deseado. En pruebas reales, he notado mejoras de entre el 10 y el 15% en rendimiento solo con una buena configuración de energía.

Disponibilidad y recuperación

Garantizar la disponibilidad de una instancia de SQL Server virtualizada no se limita a activar vSphere HA o a desplegar un grupo de disponibilidad. Exige entender cómo interactúan las funcionalidades de VMware con las tecnologías de alta disponibilidad del propio SQL Server, y decidir cuál debe ser el punto de recuperación (RPO) y el tiempo de recuperación objetivo (RTO) para cada tipo de fallo.

Alta disponibilidad en la capa VMware

VMware proporciona mecanismos propios de alta disponibilidad y movilidad de cargas que pueden complementar (o incluso entrar en conflicto con) las estrategias nativas de SQL Server:

  • vSphere HA permite el reinicio automático de una VM en otro host del clúster cuando se detecta un fallo físico. No ofrece continuidad de servicio inmediata, pero sí reduce el downtime sin intervención manual. Es transparente para el sistema operativo y para SQL Server.
  • vSphere FT (Fault Tolerance) proporciona replicación síncrona a nivel de VM y failover instantáneo sin pérdida de estado. No está soportado para máquinas con más de 8 vCPU (en la mayoría de versiones actuales) y no es compatible con algunos escenarios de licenciamiento de SQL Server. Es útil solo en casos muy concretos y no se recomienda como estrategia principal de HA para SQL.
  • vMotion permite migrar en caliente una VM entre hosts sin apagado, útil para mantenimiento planificado o balanceo. Sin embargo, en cargas intensivas (como operaciones de backup, reindexación o grandes transacciones), la migración puede introducir latencias temporales. Aunque no genera caída del servicio, puede afectar al rendimiento en momentos críticos.
  • DRS (Distributed Resource Scheduler) balancea dinámicamente la carga entre hosts según consumo de recursos. Esto puede provocar movimientos frecuentes de la VM si no se definen reglas adecuadas. 

En entornos con SQL Server, es necesario evaluar cuidadosamente el impacto de vMotion y DRS en instancias críticas. Mover una VM durante una operación intensiva puede degradar el rendimiento o generar latencia adicional. Se recomienda definir reglas de afinidad o exclusión para evitar migraciones no deseadas. 

Consideraciones de diseño

A la hora de planificar una solución de alta disponibilidad para SQL Server sobre VMware, es fundamental definir el tipo de fallo que se quiere cubrir:

  • Fallo físico del host: vSphere HA es suficiente si se acepta un reinicio de VM.
  • Fallo de software en el sistema operativo o SQL Server: requiere HA a nivel de SQL Server (AG, FCI).
  • Fallo del datastore: debe cubrirse mediante almacenamiento redundante (vSAN, replicación SAN/NAS).
  • Fallo completo del datacenter: implica solución de recuperación ante desastres (DR), normalmente con réplicas geográficas y procedimientos definidos de failover manual o automático.

Es importante destacar que las soluciones de VMware y SQL Server no son excluyentes, pero deben coordinarse cuidadosamente para evitar conflictos: por ejemplo, no tendría sentido proteger una FCI solo con vSphere HA, o dejar que DRS migre réplicas sincronizadas entre hosts indiscriminadamente. En casos en los que se implementan soluciones HA de SQL Server se recomienda definir reglas de afinidad y exclusión para que las máquinas implicadas en el HA no compartan host físico.

También hay que considerar el licenciamiento: algunas ediciones de SQL Server requieren licencias activas en todas las réplicas del clúster, incluso si solo una está activa (según el uso que se haga). Además, ciertos entornos requieren asegurar que las réplicas pasivas no procesan cargas activas para beneficiarse de ventajas en licencias de Software Assurance.

Vecinos ruidosos

Uno de los retos más infravalorados en la virtualización de cargas críticas como SQL Server es el efecto de otras VMs compartiendo el mismo host físico, conocidas comúnmente como “noisy neighbors” (vecinos ruidosos).

Una máquina virtual que consume picos de CPU, I/O o memoria puede afectar negativamente a otras VMs en el mismo host, especialmente si no hay control de calidad de servicio (QoS) o reservas definidas. Los síntomas suelen incluir:

  • Latencia intermitente en consultas.
  • Variabilidad en tiempos de respuesta bajo carga constante.
  • Aumento de CPU Ready Time o Co-Stop sin incremento aparente de carga en SQL Server.

Para detectar estos problemas, se requiere visibilidad más allá del sistema operativo invitado. Herramientas como vRealize Operations, SQL Sentry o VMware Aria Operations permiten identificar VMs que saturan recursos compartidos, y correlacionar ese uso con degradaciones de rendimiento en las instancias afectadas.

En este caso las recomendaciones son:

  • Establecer reservas mínimas de recursos para VMs críticas.
  • Aplicar affinity/anti-affinity rules para separar cargas pesadas o sensibles.
  • Evitar que SQL Server comparta host con VMs que realizan tareas de backup, ETL o pruebas automatizadas en horarios críticos.
  • Monitorizar periódicamente la actividad del host para detectar comportamientos anómalos.

En entornos donde se requiere máxima previsibilidad (banca, OLTP de alto rendimiento, entornos de pricing), puede incluso justificarse la dedicación exclusiva de host para una o varias VMs SQL Server.

Versiones de hardware y VMware Tools

Mantener actualizadas tanto la versión de hardware virtual como las VMware Tools es esencial para acceder a nuevas funcionalidades, mejorar el rendimiento y garantizar el soporte oficial.

En 2025, la versión mínima recomendada es hardware version 19 (ESXi 7.0), aunque lo ideal sería estar en versión 20 u 21 si se usa ESXi 8.x. Las VMware Tools deben actualizarse de forma coordinada tras cambios de versión o parches del host.

Monitorización y observabilidad

Las métricas estándar de vSphere no siempre ofrecen suficiente visibilidad sobre los cuellos de botella que afectan a SQL Server. Por ello, se recomienda utilizar herramientas especializadas que permitan analizar desde la capa de hipervisor hasta el motor de base de datos:

  • SQL Sentry (SolarWinds): ofrece no solo métricas de SQL Server sino también propias del entorno virtual.
  • vRealize Operations: para el análisis de capacidad, planificación y rendimiento.
  • Perfmon + DMVs: exclusivo para el análisis desde dentro de la VM.

Indicadores como CPU Ready Time, Co-Stop, latencia de I/O, uso de memoria o crecimiento de snapshots deben estar controlados de forma continua.

Conclusión

La virtualización de SQL Server sobre VMware sigue siendo, en 2025, una estrategia plenamente válida para cargas de misión crítica. Pero su éxito depende de un diseño cuidadoso, de un conocimiento profundo del comportamiento del motor SQL y de una integración adecuada con las funcionalidades del hipervisor.

Los errores más comunes (malas configuraciones NUMA, exceso de vCPU, uso de snapshots como backup, planes de energía inadecuados) pueden evitarse si se siguen las prácticas que hemos repasado. Esta guía pretende servir como base técnica de referencia para garantizar que cada instancia virtualizada de SQL Server funcione con la previsibilidad, rendimiento y fiabilidad que un entorno de producción exige.

Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de Telegram y un canal de YouTube a los que te puede unir. ¡Hasta la próxima!

Publicado por Roberto Carrancio en Alta Disponibilidad, Rendimiento, SQL Server, 1 comentario

Nueva caché de seguridad en SQL Server 2025

Llevamos ya tiempo con la preview de SQL Server 2025 probando todas las novedades. La lista es larga y, a veces, cuesta distinguir entre lo realmente útil y lo puramente decorativo. Entre tanto brillo marketiniano, hay una mejora de la que no se ha hablado, que muchos pasarán por alto sin comprender las implicaciones, pero que a mi me ha hecho sonreír y decir: “Ya era hora”. Os hablo de la nueva capacidad de invalidar cachés de seguridad de forma específica por inicio de sesión en SQL Server 2025. Y sí, es tan buena como suena.

¿Qué es esto de la caché de seguridad?

Antes de meternos en harina, conviene recordar qué es exactamente esa “caché de seguridad” que ahora Microsoft ha afinado. Cuando un usuario se conecta a SQL Server, el motor evalúa qué permisos tiene para acceder a objetos, ejecutar procedimientos, ver datos… ya sabéis, lo básico para evitar que todo sea un buffet libre de SELECT * FROM SensitiveTable.

Como no somos tontos (y SQL Server tampoco), esta validación no se repite cada vez que alguien lanza una consulta. Sería un suicidio en términos de rendimiento. En su lugar, SQL Server guarda esa información en memoria (en la famosa security cache) y la reutiliza mientras no haya cambios que invaliden su contenido.

¿El problema? Hasta ahora era muy sensible. Si cambiabas cualquier permiso de cualquier usuario (cambio de permisos, modificación de roles, o revocar un acceso), se eliminaban todas las entradas DE TODOS LOS USUARIOS. Esto, por supuesto, tiene efectos inmediatos en el rendimiento de cualquier sesión abierta, aunque no tuviera nada que ver con el cambio.

Vamos, que tirábamos la caché como quien reinicia un servidor por si acaso: por pura desesperación.

SQL Server 2025 trae cordura: invalidación específica por login

Con la llegada de SQL Server 2025, se acabó el “todo o nada”. Ahora, cuando se invalidan entradas de la caché de seguridad debido a un cambio en los permisos, el sistema es lo bastante listo como para borrar solo las entradas correspondientes al login afectado. El resto permanece intacto.

Esto supone una mejora directa en varios frentes. Para empezar, reduce el impacto de cualquier cambio de seguridad. No hay invalidaciones masivas innecesarias, no se resienten las sesiones de otros usuarios, y la CPU no se dispara validando de nuevo cientos o miles de entradas de permisos para conexiones que no han cambiado ni una coma de sus privilegios.

¿Por qué esto importa? Rendimiento, escalabilidad y menos sustos

Puede parecer que un cambio de estas características no tiene mucha importancia, y así es entornos con pocos usuarios y permisos bastante genericos. Pero cuando el volumen de usuarios y la granularidad de los permisos son considerables, la diferencia entre invalidar toda la caché de seguridad y hacerlo de forma selectiva puede marcar la diferencia. En entornos con cientos o miles de sesiones concurrentes, la diferencia es tan evidente como entre ejecutar SELECT con un índice… o sin él.

Antes, un cambio puntual en los permisos podía convertirse en una mini tormenta de validaciones. La CPU subía, la latencia aumentaba, y tú te encontrabas explicando por qué un GRANT a las 9:30 había dejado la aplicación más lenta que un Access con macros durante unos minutos. Todo eso queda en el pasado con esta nueva implementación.

Ahora, si revocas un permiso a un usuario que ya estaba conectado, SQL Server se limita a eliminar sus entradas específicas de la caché. El resto de usuarios ni se enteran. Y tú tampoco tendrás que revisar gráficos de rendimiento preguntándote qué demonios ha pasado.

Cambios de roles, miembros de grupos y lo que siempre duele

Uno de los escenarios donde esto brilla especialmente es cuando se hace una modificación en roles o membresías de grupos. Añadir o quitar a alguien de un db_datareader, por ejemplo, solía ser sinónimo de purgar toda la caché de seguridad.

Con SQL Server 2025, eso se acabó. La limpieza de la caché se ciñe a ese login concreto, incluso si el cambio afecta a una membresía en roles de servidor o roles personalizados. Menos interrupciones, menos recompilaciones internas, y más estabilidad.

Que sí, que aún quedan muchos elementos que provocan recompilaciones y limpiezas de caché que no siempre tienen sentido, pero al menos aquí han puesto orden en una de las áreas más olvidadas por el motor en versiones anteriores.

¿Cómo saber si está funcionando?

No hay un nuevo DMV mágico que diga “estás disfrutando de la nueva caché de seguridad personalizada”, pero si monitorizas el uso de CPU y el acceso concurrente durante cambios de permisos, deberías notar una mejora clara. Sobre todo en sistemas con mucha actividad concurrente y una gestión de seguridad activa.

Y si eso no te vale y quieres verlo con tus propios ojos siempre nos quedarán los eventos extendidos, esa magnífica herramienta que lo captura todo. Puedes crear una sesión que capture los nuevos eventos “login_token_cache_hit” que se producen cuando el token de la caché de seguridad sigue activo y el evento “login_token_cache_miss” que es cuando el token de la caché no es válido y hay que generar una nueva entrada.

Demo caché de seguridad 

Vamos a comprobar que esto realmente funciona. Para ello tenemos nuestros logins con ID 267 y 268 y vamos a crear una sesión de xEvents que capture los eventos que hemos comentado antes:

Lo primero que vamos a hacer es borrar la caché de seguridad:

Como hemos borrado la caché, estas dos primeras entradas generan un evento “login_token_cache_miss”, no existe registro en la caché. 

Pero, si volvemos a conectarnos veremos ya los hit, es decir ha utilizado el token existente en caché

Ahora vamos a cambiar los permisos de uno de los logins

Y al volver a conectar veremos solo uno de los dos logins tiene el miss y el otro mantiene su token válido (evento hit). Además veís en la captura que yo he añadido tambien los eventos “security_cache_login_timestamp_increment” a mi captura de eventos, que me indica cuando se ha producido un cambio de permisos.

¿Qué implicaciones tiene para nosotros como DBAs?

Básicamente, nos devuelve un poco de control. Ahora podemos aplicar cambios de seguridad sin tener miedo a provocar un alud de recompilaciones y penalizaciones de rendimiento. Se acabó el tener que programar revocaciones de permisos fuera del horario laboral o acompañarlas de una explicación de daños colaterales.

También nos da más seguridad en entornos de desarrollo y pruebas. Podemos simular escenarios de cambios de permisos sin el temor a que medio entorno colapse por culpa de una caché global destruida innecesariamente.

Eso sí, no todo es perfecto. La documentación oficial todavía no entra en muchos detalles sobre cómo se comporta esta nueva caché con escenarios complejos de impersonación (EXECUTE AS), certificados o permisos a nivel de esquema. Habrá que investigar (y ya lo haré en otro artículo si me lo pedís) si este comportamiento selectivo se extiende también a esos casos.

Conclusión

La invalidación selectiva de la caché de seguridad en SQL Server 2025 es una mejora tan lógica que sorprende que no estuviera ya implementada hace años. Pero aquí está, y funciona como debe. Nos da más precisión, menos impacto colateral y permite cambios de seguridad sin temor a convertir el servidor en una verbena de validaciones.

Como siempre, no es magia. Si haces cambios absurdos o con prisas, te seguirás metiendo en líos. Pero al menos, ahora, el motor te lo pone un poco menos difícil. Y eso, en este mundo de permisos, roles y DBA que no duermen, ya es bastante.

Si tenéis alguna duda o sugerencia, podéis dejarla en Twitter, por mail o dejarnos un mensaje en los comentarios. Y recuerda que también tenemos un grupo de Telegram y un canal de YouTube a los que te puede unir. ¡Hasta la próxima! 

Publicado por Roberto Carrancio en Rendimiento, SQL Server, 0 comentarios