Teoría BBDD

¿Cuál es el problema que quieres resolver?

Si hay una pregunta que debería resonar en la cabeza de todo DBA antes de tocar nada es esta: ¿cuál es el problema que quieres resolver?. Parece de sentido común, pero basta con ver la cantidad de “optimizaciones” fallidas que nos encontramos a diario para entender que muchos prefieren actuar primero y pensar después.

No es cuestión de señalar a los juniors recién llegados. También he visto seniors con experiencia aplicar consejos a ciegas porque lo leyeron en un blog (sí, incluso en este). Optimizar sin tener claro el objetivo es la mejor forma de acabar con más índices de los que puedes contar y un servidor que corre peor que antes.

Cuando dos índices son un problema

Hace un tiempo publiqué un artículo en el blog que mostraba un comportamiento extraño en SQL Server: si creas dos índices con los mismos campos pero en orden inverso, el optimizador puede entrar en bucle y empeorar el rendimiento.

No es que uno de los índices fuera inútil, es que la mera coexistencia de ambos confundía al motor. El resultado eran planes de ejecución incoherentes, lecturas disparadas y un servidor que parecía castigar la osadía de haber creado ese segundo índice.

Lo comprobé en mi propio laboratorio y sí, el problema existe en distintas versiones, desde 2014 hasta 2022. No hay explicación oficial, pero el efecto es evidente: un índice que no se usa puede penalizar tanto como uno mal diseñado.

La moraleja es clara: no todo lo que parece buena idea lo es. Crear un índice extra “por probar” puede desatar un problema que no estaba ahí antes.

El optimizador también se equivoca

A ese escenario extraño se suma otro que me he encontrado demasiadas veces: el optimizador sugiriendo crear un índice que ya existe.

¿Cómo puede ser? Muy simple: lo que realmente falla son las estadísticas. Si los datos de distribución están obsoletos, el optimizador cree que no tiene un índice adecuado y recomienda uno nuevo. Y como “buenos DBAs obedientes”, lo creamos. Resultado: en el mejor de los casos acabamos con dos índices redundantes, el motor igual de confundido y el verdadero problema (las estadísticas) intacto. En el peor, con el problema que hemos descrito en el apartado anterior y con las estadísticas aún desactualizadas.

La historia se repite: en vez de preguntarnos qué queremos resolver, nos dejamos llevar por la sugerencia de turno y complicamos aún más el entorno.

Optimizar sin objetivo: el problema más común

Ambos casos ponen de manifiesto lo mismo: aplicar soluciones sin entender el problema real es un deporte de riesgo.

Ya lo comentamos en este otro artículo, los entornos de bases de datos no se arreglan con recetas universales ni con “scripts definitivos” de Internet. Cada entorno es distinto, con sus cargas, sus decisiones históricas y sus miserias. Copiar y pegar soluciones genéricas es más postureo técnico que administración seria.

La optimización sin objetivo es como disparar con los ojos cerrados, con suerte no das en nada, pero la mayor parte del tiempo acabas dañando algo.

La pregunta de Brent Ozar

Aquí entra la insistencia de Brent Ozar en su mantra favorito y que da titulo a este artículo:
¿Cuál es el problema que quieres resolver?

Antes de crear índices, actualizar estadísticas o aplicar hints a lo loco o cambiar configuraciones en el servidor hay que responder a esa pregunta. ¿El problema es el tiempo de respuesta? ¿Consumo excesivo de CPU? ¿Bloqueos? ¿O solo que alguien quiere que una consulta de 3 segundos baje a 0,3 porque sí?

Uno de esos es un problema técnico. El otro es un problema de expectativas. Y mezclar ambos lleva a dedicar horas a optimizar lo que no importa mientras lo urgente sigue sin atenderse.

Si no mides, no sabes si mejoras o empeoras

Aquí está el punto que muchos olvidan, si no sabes que tienes un problema y no mides antes, no puedes saber si lo que hiciste fue una mejora o un desastre.

Un cambio sin línea base no es optimización, es puro azar. Y en producción, jugar al azar es abrir la puerta a que mañana alguien te pregunte por qué el sistema está peor y no tengas respuesta. Sin métricas antes y después, la optimización es indistinguible del postureo.

Y ojo, también tienes que medir cuando todo funciona bien, sin esa linea base es imposible saber si de verdad algo va mal o es solo la sensación de los usuarios. Ya sabemos que adoran decir: “esto ahora va más lento” sin pruebas.

Diagnóstico antes de cirugía

La única forma de trabajar en serio es diagnosticar antes de tocar. Eso implica medir, observar y recopilar evidencia. Query Store, planes de ejecución, Extended Events, DMVs… las herramientas están ahí, pero hay que usarlas con criterio.

El motor se equivoca, los consejos de Internet también, y a veces hasta nuestras “buenas prácticas” son contextuales y no universales. La diferencia entre un DBA que arregla problemas y otro que los multiplica está en hacerse siempre la pregunta incómoda antes de optimizar.

Conclusión

Cambiar configuraciones del servidor, crear índices o aplicar consejos sin diagnosticar el problema real no es optimización, es azar.

SQL Server no premia las soluciones automáticas. Premia el análisis. Y la diferencia entre un DBA que arregla cosas y otro que las rompe está en hacerse siempre esa pregunta incómoda antes de tocar nada: ¿cuál es el problema que quiero resolver?

Si no sabes que tienes un problema y no lo mides antes, no tienes forma de saber si tu cambio fue mejora o desastre. Y en bases de datos, la duda casi siempre juega en tu contra.

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, Rendimiento, SQL Server, 0 comentarios

Casos de uso comunes de Row-Level Security (RLS)

Ya sabemos qué es Row-Level Security (RLS) y cómo se configura. Sabemos que se basa en funciones, en contexto y en algo muy parecido al sentido común. Pero el verdadero reto no es activarlo: es aplicarlo bien según el escenario real que tienes delante.

Aquí no vamos a hablar de casos teóricos ni de pruebas de laboratorio. Vamos a entrar en los tres escenarios más comunes que nos encontramos en proyectos reales, de esos con datos de verdad, usuarios impacientes y arquitecturas heredadas.

RLS interno en la organización: seguridad basada en Active Directory

Este es el caso más limpio y agradecido: una empresa con usuarios autenticados en Active Directory, accediendo a la base de datos con sus propias credenciales de Windows (sí, esto existe y funciona cuando se hace bien). Aquí el RLS puede aprovechar directamente la identidad del usuario para filtrar datos.

El patrón habitual consiste en mapear usuarios o grupos de AD con permisos o ámbitos de acceso, normalmente usando el ORIGINAL_LOGIN() o SUSER_SNAME() para identificar al usuario, y compararlo contra una tabla de mapeo como:

La función RLS consulta esta tabla y determina qué datos puede ver el usuario actual. Algo así:

Este modelo funciona bien si los usuarios acceden directamente con sus identidades, y si hay una buena sincronización entre AD y los datos internos. Pero cuidado: este patrón no es válido si la aplicación usa un login compartido, porque entonces ORIGINAL_LOGIN() siempre devuelve lo mismo.

También requiere un mantenimiento cuidadoso de la tabla de mapeo. Si te olvidas de añadir un nuevo usuario, no verá nada. Y eso está bien. Lo preocupante sería que viera de más.

Este patrón es ideal para:

  • Reporting interno
  • Aplicaciones corporativas en intranets
  • Escenarios con SSRS o Power BI con Kerberos bien configurado (sí, existen)

RLS en aplicaciones con un único login SQL y múltiples usuarios

Este es, con diferencia, el escenario más habitual. Una aplicación que se conecta a la base de datos con un solo login SQL Server (por ejemplo, AppUser) y desde ahí da servicio a miles de usuarios distintos, cada uno con sus propios permisos y ámbito de acceso.

Desde el punto de vista de SQL Server, todos los accesos vienen del mismo login. Por tanto, el nombre del usuario no sirve para nada. Aquí RLS solo tiene sentido si usamos SESSION_CONTEXT() para establecer el contexto del usuario en cada sesión.

  1. El patrón correcto es:
  2. La aplicación identifica al usuario (login web, token, sesión, lo que sea).
  3. Determina su TenantId, su ámbito de acceso, si es admin, etc.
  4. Al abrir la conexión (o justo después), ejecuta
    EXEC sp_set_session_context N’TENANT_ID’, 17;
    EXEC sp_set_session_context N’ES_ADMINISTRADOR’, 0;
  5. La función RLS consulta ese contexto y decide si mostrar o no cada fila.

Funciona. Es limpio. Es seguro. Pero solo si te aseguras de que cada conexión establece su contexto correctamente. Y eso implica entender bien cómo funciona el pool de conexiones. Porque si alguien reutiliza una conexión con el contexto de otro usuario, acabas sirviendo datos del usuario A al usuario B. Y eso no es un bug: es un incidente de seguridad.

Este patrón requiere no solo código en la aplicación para establecer el contexto en cada conexión sino validación en la base de datos para asegurarse de que el contexto existe y funciones RLS bien diseñadas (inline, sin llamadas externas ni joins innecesarios). Si además añades una capa de control en la aplicación tendrás doble seguridad.

Este escenario, bien montado, es el pan de cada día en escenarios como aplicaciones web SaaS, portales internos de gestión multiusuario o APIs que consumen datos con identidad propia (pero login compartido)

RLS en aplicaciones multi-tenant con varios clientes

Aquí las cosas se complican. Estamos ante una única aplicación que sirve a múltiples clientes independientes, y todos los datos viven en las mismas tablas, separados lógicamente por una columna TenantId. Este patrón es muy eficiente… hasta que alguien mete la pata y un SELECT devuelve datos de otro tenant.

RLS aquí no es una opción. Es una necesidad.

El patrón es similar al del punto anterior: la aplicación se conecta con un login compartido, pero establece el TenantId como contexto al inicio de cada sesión. La diferencia es que ahora ese TenantId define los límites legales del acceso a datos.

Es decir, ya no es un usuario con menos o más permisos. Es otro cliente, con sus propios datos. Si algo se cuela, no solo es un error, es una violación de privacidad con consecuencias legales.

La función RLS, por tanto, debe ser clara, directa, sin adornos:

Y la política se aplica a todas las tablas sensibles. Además, conviene reforzar la integridad con defaults:

Y con predicados de bloqueo (de eso hablaremos pronto) para evitar updates o deletes entre tenants.

Este patrón funciona, pero solo si se impide a la aplicación cambiar el contexto a lo loco, el TenantId se valida contra los permisos del usuario web y todas las rutas de acceso pasan por código que inicializa el contexto.

Además, como ya he remarcado, este escenario es el más sensible, y por tanto donde más cuidado debemos tener. Si no haces RLS aquí, estás confiando en que la aplicación nunca se equivoque. Buena suerte con eso.

Predicados de bloqueo en RLS

Cuando implementamos RLS, todo el mundo se queda encantado con el FILTER PREDICATE: ese que impide que el usuario vea filas que no le tocan. Pero la mayoría se olvida, o no quiere saber, que eso no impide que puedan hacer INSERT, UPDATE o DELETE sobre datos que no deberían tocar. Así de simple. Y así de peligroso. Ahí es donde entran los BLOCK PREDICATES, el otro 50% de la seguridad que RLS nos ofrece.

Un BLOCK PREDICATE define si una operación de modificación de datos está permitida. Se puede aplicar a:

  • AFTER INSERT (cuando se insertan nuevas filas)
  • AFTER UPDATE (cuando se actualiza una fila)
  • BEFORE UPDATE (para impedir que se cambie el valor de clave de filtrado, por ejemplo TenantId)
  • BEFORE DELETE (para validar que el usuario puede borrar esa fila)

Y aquí viene la parte buena, estos bloqueos se aplican antes de que la operación se realice. Si no se cumple la condición, la instrucción falla con error. Sin necesidad de triggers, sin lógica adicional. De forma declarativa y centralizada. Como debe ser.

Vamos con un ejemplo.

Supongamos que tenemos una tabla Facturas y ya tenemos aplicado un FILTER PREDICATE que impide ver facturas de otros tenants. Muy bien. Pero si no hacemos nada más, el usuario podría hacer esto:

INSERT INTO Facturas (FacturaId, TenantId, Importe) VALUES (9999, 42, 1500);

Y colar datos con el TenantId de otro cliente. Luego, como no puede verlas, ni se entera. Pero ya están en tu base. ¿Te hace ilusión explicárselo a legal? A mí tampoco.

Para evitarlo, añadimos un BLOCK PREDICATE:

Y luego lo aplicamos así:

Esto bloquea los INSERT y DELETE por defecto. Si queremos bloquear los updates también (y deberíamos), lo hacemos explícitamente:

Y si no queremos que nadie cambie el TenantId de una fila, lo añadimos como BEFORE UPDATE:

Esto impide que alguien coja una factura legítima y le cambie el TenantId para que desaparezca mágicamente de la vista de su propietario original. Muy creativo. Muy ilegal.

Consideraciones importantes con los bloqueos de RLS

Al usar BLOCK PREDICATE, las operaciones que no cumplan la condición fallan con un error genérico del tipo:

Esto es intencionado. No dice qué falló ni por qué, porque revelar detalles de seguridad no es buena idea. Pero esto también significa que debes controlar bien los errores en la aplicación, o los usuarios se encontrarán mensajes confusos.

Y como siempre, las funciones deben ser INLINE para no perder rendimiento. Y deben ser simples, sin joins ni condiciones complejas. Esto se ejecuta en cada fila afectada. Si metes un SELECT TOP 1 dentro, estás haciendo cosas malas y mereces tus bloqueos (los tuyos, no los de RLS).

Conclusión

RLS es una herramienta poderosa, pero no mágica. Su utilidad real depende de cómo te conectas, de quién eres en la base de datos y de cómo estableces el contexto. Un mismo mecanismo puede servir tanto para proteger acceso interno como para blindar un modelo multi-tenant.

Pero si no eliges el patrón correcto para tu escenario, estás poniendo una alarma en la puerta mientras dejas la ventana abierta. Y eso no es seguridad: es postureo.

Ya hemos cubierto lo esencial de RLS: qué es, cómo se implementa, cómo se adapta a escenarios reales y cómo no confiar ciegamente en que el FILTER PREDICATE lo hace todo. Porque si no añades bloqueos, estás dejando que el usuario escriba donde no puede leer. Y eso es como cerrar la puerta pero dejar las ventanas abiertas: solo te protege si el atacante es educado.

Usar RLS bien no es complicado. Pero requiere tomárselo en serio. Establecer contexto. Validar accesos. Aplicar filtros y bloqueos. Y sobre todo: asumir que si no lo defines tú, alguien lo hará por ti. Probablemente mal.

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

Seguridad a nivel de fila (RLS) en SQL Server

Cuando hablamos de seguridad en SQL Server, la mayoría piensa primero en roles, permisos, y si somos afortunados, en principios de mínimo privilegio. Sin embargo, en muchas organizaciones se sigue dejando la lógica de acceso a los datos en manos de la capa de aplicación. Y eso, como todos sabemos, es pedirle a un desarrollador frontend que entienda el negocio y además proteja los datos. Un sinsentido. Ahí entra en juego Row-Level Security (RLS), una funcionalidad introducida en SQL Server 2016 (sí, hace casi una década) que permite filtrar los datos directamente en el motor, sin tener que montar castillos de naipes con vistas o triggers que solo traen dolores de cabeza.

¿Qué es RLS y por qué debería importarnos?

La seguridad a nivel de fila permite restringir el acceso a las filas de una tabla en función del contexto del usuario que realiza la consulta. Y esto se hace de forma transparente, sin modificar el código de las consultas. No hablamos de un WHERE opcional añadido por el ORM de turno. Hablamos de reglas que se ejecutan en el servidor, en cada acceso, sin excepciones.

RLS nos permite definir una política de seguridad que determina si una fila puede o no ser accedida. Esa política se implementa mediante una función escalar, que actúa como el portero de discoteca: decide quién entra y quién no. Y lo mejor: el usuario no ve que se le han vetado filas. Simplemente, no están.

A diferencia de los trucos sucios con vistas filtradas y lógica duplicada, RLS está diseñado para que el control sea centralizado, mantenible y eficiente. Y, lo más importante, que no se pueda esquivar con una consulta directa.

Cómo funciona RLS bajo el capó

Para habilitar RLS necesitamos tres ingredientes:

  • Una función de filtrado, generalmente inline para evitar penalizaciones absurdas de rendimiento.
  • Una política de seguridad que asocia la función con una tabla concreta.
  • Usuarios (o roles) sobre los que queramos aplicar el filtrado.

La función recibe como parámetros las columnas de la tabla que queremos usar como condición de acceso, y devuelve un 1 (permitido) o un 0 (bloqueado). Así de sencillo. Y como todo buen sistema de seguridad, lo sencillo no quita lo peligroso: una mala implementación puede abrir más puertas de las que cierra.

Veámoslo con un ejemplo rápido:

Aquí estamos usando SESSION_CONTEXT() para almacenar el contexto del usuario (en este caso, su departamento), y comparar si la fila que se intenta leer pertenece al mismo departamento. Este patrón es de lo más habitual: guarda el valor relevante al iniciar sesión, y luego úsalo como filtro en la función RLS.

Después, aplicamos la política:

Y listo. A partir de ese momento, cualquier consulta contra la tabla Empleados estará sujeta al filtro. Sin excepciones. Sin necesidad de modificar el SELECT. Sin posibilidad de que el usuario borde el control.

Tampas comunes de RLS

Sí, puedes meter lógica compleja en la función RLS. No, no deberías. Las funciones de RLS se ejecutan por cada fila accedida, y si te vienes arriba y le metes llamadas a otras tablas, condicionales complejos o conversiones mágicas, lo que consigues es una performance digna de una migración mal hecha a Access.

Además, cuidado con usar funciones escalares no inline. No solo penalizan el rendimiento, sino que en versiones anteriores a SQL Server 2019 no se pueden usar directamente en RLS. Y aun en 2019 o superior, si puedes escribir una función inline, hazlo. Por tu salud mental y la de quien venga después.

También hay quien se pregunta: “¿Y si quiero permitir el acceso completo a ciertos roles o usuarios?” Pues puedes gestionar excepciones dentro de la propia función, comprobando por ejemplo el nombre del login o algún valor del SESSION_CONTEXT. Pero hazlo con moderación. Si acabas con una función que parece una novela de Agatha Christie para decidir quién puede leer qué, igual el problema no es el RLS.

RLS en escritura: INSERT, UPDATE y DELETE

Por defecto, RLS aplica el filtro también a operaciones de escritura. Eso significa que un usuario solo podrá insertar o modificar filas que cumplan la condición del filtro. No basta con tener permiso para escribir: si el valor que se inserta no pasa el control, la operación falla.

Este comportamiento se puede personalizar con predicados de bloqueo (BLOCK PREDICATE), pero por ahora no vamos a entrar en eso. Esto es una introducción, no una tesis. Lo importante es entender que RLS no es solo para SELECT. También puede protegernos de inserts maliciosos o updates “por accidente”.

¿Dónde guarda el contexto el RLS?

Una de las claves para que RLS funcione bien es cómo pasamos el contexto del usuario al motor. SQL Server no tiene una variable mágica llamada UsuarioActual.Departamento, así que somos nosotros los que tenemos que alimentar ese contexto. La opción más limpia y controlada es usar SESSION_CONTEXT.

Esto nos permite establecer pares clave-valor que persisten durante toda la sesión, y que podemos consultar desde la función RLS. Por ejemplo, en el momento de la conexión:

Esto lo puede hacer la capa de aplicación al conectarse, o mejor aún, a través de un procedimiento almacenado bien controlado. ¿Que podríamos usar ORIGINAL_LOGIN() o SUSER_SNAME() para extraer el usuario? Sí, pero volvemos al infierno de tener que mapear usuarios, mantener tablas auxiliares, y perder la trazabilidad del acceso real.

Limitaciones que no debes ignorar (aunque quieras)

RLS no cifra los datos. No evita que un administrador con permisos vea todo. No protege frente a accesos directos desde backups o desde otros medios. Es una herramienta de seguridad a nivel lógico, no físico.

Tampoco funciona automáticamente con todo. Por ejemplo, si creas una vista que usa WITH CHECK OPTION, puedes encontrarte con comportamientos inesperados. Y si haces SELECT INTO o usas funciones que acceden a múltiples tablas, el rendimiento puede sorprenderte… pero no en el buen sentido.

Y por supuesto, si alguien tiene permisos para desactivar la política o modificar la función RLS, todo se va al garete. Esto no sustituye una buena gestión de permisos. La complementa.

Conclusión: si no usas RLS, que sea porque no lo necesitas, no porque no lo conoces

RLS es una funcionalidad potente, elegante y bastante ignorada. Nos permite aplicar reglas de acceso directamente en el motor de SQL Server, con garantías y sin depender de que la aplicación “haga lo correcto”.

Eso sí: como cualquier herramienta de seguridad, hay que usarla bien. Si no tienes un modelo claro de control de acceso, implementar RLS sin criterio solo añade complejidad. Pero si sabes lo que haces y quieres evitar que un SELECT de más enseñe lo que no debe… entonces RLS es tu amigo.

En siguientes artículos profundizaremos en patrones de uso, ejemplos reales, y cómo integrar RLS con Active Directory o Azure AD. Pero por hoy, lo dejamos aquí. Que no se diga que no avisamos.

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, 1 comentario

Novedades sobre el libro

Después de meses de trabajo, revisiones y mucha paciencia, puedo compartir tres novedades clave del libro SQL Server: La NO guía práctica de optimización:

  • El prólogo lo firma Fernando G. Guerrero, pionero en SQL Server y miembro histórico de la comunidad. Además de escribir unas palabras introductorias, ha contribuido en la revisión técnica.

  • Aquí está el índice completo, con los más de 40 capítulos organizados en 7 partes.

  • Y sí: la fecha de lanzamiento ya es oficial. El libro estará disponible a mediados de septiembre. Pronto os diré el día exacto

Índice completo

Parte 1 – Fundamentos del modelo relacional y la arquitectura
Desde la definición de base de datos relacional hasta la estructura física de páginas y archivos. El punto de partida sólido para entender qué hay detrás de cada consulta.

Parte 2 – T-SQL y construcción de consultas eficientes
SELECT, INSERT, UPDATE y DELETE como base, y a partir de ahí subconsultas, CTEs, funciones de ventana, vistas, procedimientos y ejecución de consultas. Todo lo que necesitas para escribir SQL que funcione en producción.

Parte 3 – Transacciones, concurrencia y aislamiento
Propiedades ACID, niveles de aislamiento, bloqueos, deadlocks y el nuevo modelo de bloqueos optimizados. Una sección clave para quien de verdad administre entornos críticos.

Parte 4 – Internals, configuración y mantenimiento
TempDB, almacenamiento, memoria, CPU, cardinalidad, parametrización, índices, estadísticas y particionado. La cocina interna del motor y cómo configurarlo sin hipotecar el rendimiento.

Parte 5 – Backup, recuperación y disponibilidad
Modelos de recuperación, estrategias de backup, restore, Log Shipping, Database Mirroring y Availability Groups. Todo lo que sostiene la continuidad de un entorno SQL Server serio.

Parte 6 – Seguridad y control de acceso
Principales, usuarios, roles, permisos y técnicas avanzadas de seguridad. Desde lo básico hasta RLS, cifrado y enmascaramiento de datos.

Parte 7 – Control, monitorización y diagnóstico
Herramientas internas y externas: Resource Governor, Activity Monitor, DMVs, Profiler, Extended Events, Query Store y PerfMon. Para que no solo administres, sino que entiendas qué ocurre bajo el capó.

Con este índice ya podéis ver que no es un manual de recetas rápidas, sino una guía estructurada de principio a fin para profesionales de SQL Server.

El lanzamiento será a mediados de septiembre y os avisaré en cuanto esté disponible en Amazon.

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

¿Cuál es el coste de no optimizar SQL?

La mayoría de las empresas que trabajan con SQL Server no tienen ni la más remota idea de lo que les cuesta no optimizar sus consultas. Y no, no hablo de la típica pérdida de rendimiento que molesta al usuario de vez en cuando. Hablo de dinero. Del que se escapa cada mes por la rendija del servidor porque nadie se molestó en revisar ese SELECT con JOIN cruzado que parece escrito por un algoritmo con ganas de venganza.

Pero vamos por partes. Porque el drama tiene capítulos, y todos salen caros.

Hardware: más coste para hacer lo mismo (o menos)

Cuando una consulta no está optimizada, lo primero que pide el sistema es más CPU. Más RAM. Más disco. Y como somos humanos, y a veces un poco vagos, el primer impulso es escalar verticalmente: poner más hierro. Total, si ya funciona mal, con más recursos irá mejor, ¿no?

Pues sí. Durante un rato. Luego viene otra consulta igual de mala y vuelta a empezar. El patrón es de sobra conocido: base de datos lenta, compras hardware, mejora temporal, vuelve la lentitud, compras más hardware… y cuando te das cuenta, estás alimentando un monstruo que vive de cores, GB y licencias.

Y aquí entra la broma que siempre duele: SQL Server se licencia por core. Así que cada vez que decides “arreglar” un problema de rendimiento añadiendo CPU, estás aceptando voluntariamente pagar más en licencias, que no son baratas. Es como combatir la sed bebiendo agua salada: parece que ayuda, pero en realidad te estás hundiendo más.

Logo SoyDBA

Únete a la newsletter de SoyDBA

Regístrate gratis para no perderte ninguna novedad. Te avisaré de noticias y eventos importantes

¡No hacemos spam! Lee nuestra política de privacidad para obtener más información.

El coste real en la nube: «elástico», sí, pero hacia arriba

Muchos creen que al migrar a la nube el problema desaparece. Que Azure SQL, AWS RDS o cualquier plataforma PaaS mágica va a solucionar lo que tu SELECT * no quiso arreglar. Y no, no es así.

En la nube todo se factura. Cada milisegundo de CPU, cada MB de RAM, cada GB de almacenamiento y cada IO de disco. Una consulta ineficiente en Azure no solo es lenta: es cara. Muy cara. Porque, a diferencia de tu servidor físico en el CPD, aquí no tienes un coste hundido. Aquí cada operación se convierte en un apunte contable. Y si te pasas, la factura no perdona.

He visto clientes triplicar su consumo mensual de Azure SQL sin añadir ni un solo usuario más. ¿La causa? Un informe mal diseñado, una vista que arrastra medio millón de registros y un desarrollador con más entusiasmo que criterio.

Una historia real de coste en azure

Y luego están los casos como este. Años atrás, un cliente me llamó porque su Azure SQL Managed Instance con 8 cores (unos 1.355€ al mes) tenía la CPU por encima del 90% casi todo el día, con picos constantes al 100% que parecían avisos de incendio. Lo más grave no era eso, sino que ya habían asumido que la única salida era duplicar recursos y pasar a 16 cores, lo que dispararía la factura a 2.700€/mes. Antes de firmar el salto, decidieron llamarme. Por suerte.

Lo que me encontré era un festival del despropósito. Ni un solo índice clustered, todos los índices nonclustered eran de una sola columna y, por supuesto, sin INCLUDE. Mirando el uso, el 95% de esos índices no se usaban. Y claro, la DMV de índices faltantes parecía la lista de tareas de un becario sin supervisión: infinita, desordenada y sin lógica.

Con un par de días de trabajo serio (revisión de patrones de consulta y una política de indexación con sentido común) no solo evitamos el escalado, sino que redujimos la instancia a 4 cores. El resultado fue sorprendente, CPU estable al 30% incluso en horas pico. Lo que se dice, respirar. Pero además, más de 25.000€ al año de ahorro respecto a la solución que estaban a punto de contratar.

El coste del “Pero si se lanza una vez al año…”

Ya que me he puesto en plan cuentacuentos, déjame contarte otra de esas anécdotas que se graban a fuego.

Un día me encontré con un informe, hecho en Tableau (pero eso es lo de menos), que lanzaban una vez al año y que tardaba en completarse… 22 horas. Bueno, yo lo pillé cuando llevaba 22 horas de ejecución en el SQL Server de producción, a saber cuánto más le quedaba. Cuando lo comenté, me dijeron que no pasaba nada, que solo se lanzaba una vez al año y que solían dejarlo corriendo de un día para otro, como quien pone la olla lenta con garbanzos.

Pero yo lo vi claro. La consulta tenía 47 subconsultas en el SELECT. Si, si, CUARENTA Y SIETE. No índices raros, no estructuras marcianas, solo una estructura de consulta absurda.

¿El cambio? Reescribir con LEFT JOIN bien definidos en lugar de esas subconsultas incrustadas. Nada más. Bueno si, una subconsulta que se repetía bastantes veces muy parecida se persistió como temporal al inicio del proceso. De esa manera los datos se leian y filtraban de una tabla grande una sola vez y se quedaban en una tabla pequeña para consultar el resto de las veces. Pero nada más, ni cambiar índices, ni tocar el esquema. Vamos, sin reformar la casa. ¿El resultado? Menos de 20 milisegundos.

Y esto amigos, esto no es una mejora. Eso es pasar de enviar la consulta en burro a ponerle un cohete. Y no exagero.

Porque no todo el coste es culpa del desarrollador

No vamos a demonizar. Todos hemos escrito consultas que después nos dieron vergüenza ajena. Y sí, hay veces que las prisas, las entregas y los deadlines te llevan a empalmar un par de subconsultas “de emergencia” con un UNION sin ALL y a mirar para otro lado.

Pero eso no justifica dejar ese código en producción durante años como si fuera parte del mobiliario. Porque esa consulta, aunque solo se ejecute una vez al día, puede ser la responsable de saturar el servidor, disparar el DTU en Azure o arrastrar a otras aplicaciones con ella.

Aquí entra en juego lo que me gusta llamar “el coste invisible de la desidia técnica”. No se ve, no se presupuesta, pero se paga igual. En horas de soporte, en tiempo perdido, en usuarios frustrados, en reputación quemada.

De 10 minutos a 2 milisegundos (sin efectos especiales)

Otra historia real, por si alguien aún cree que exagero.

Me llama un cliente porque un proceso tarda más de 10 minutos. Revisamos el plan de ejecución y canta como un tenor: falta un índice. Literalmente lo está pidiendo a gritos. Un Clustered Index Scan sobre una tabla de 10 millones de registros con 5 campos varchar(max).

Creamos un índice sencillo sobre los dos campos que busca… y bajamos a 20 segundos. Bien, ¿no?

Pero no me conformé. Me di cuenta de que esos campos varchar(max) apenas se usaban y propuse moverlos a otra tabla. Un cambio mínimo de esquema, sin traumas. El resultado: la consulta se resuelve ahora en 2 milisegundos.

Sí, de más de diez minutos a dos milisegundos. Sin comprar licencias, sin añadir cores, sin tirar la casa por la ventana. Solo sentido común.

Consultas eficientes, bases de datos rentables

Optimizar una consulta no es hacer magia negra ni sacrificar cabras sobre el plan de ejecución. Es técnica, análisis y experiencia. A veces basta con añadir un índice. O con quitar un SELECT * y poner solo las columnas que necesitas. O con evitar ese cursor que llevas arrastrando desde hace 10 años como si fuera un trauma sin resolver.

Una consulta optimizada no sólo corre más rápido. Consume menos CPU. Bloquea menos. Permite que más usuarios trabajen al mismo tiempo. Y, lo más importante, reduce directamente tu coste de infraestructura y licenciamiento.

No es filosofía, son matemáticas puras, si una consulta tarda 500 ms y logra pasar a 50 ms, puedes hacer 10 veces más operaciones con los mismos recursos. ¿Te imaginas que tu equipo hiciera 10 veces más tareas al mismo sueldo? Eso es lo que hace una base de datos bien afinada.

El coste del «si funciona, no lo toques»

Una de las excusas más repetidas cuando se habla de optimizar es: “Pero si ya funciona, ¿para qué meternos ahí?” Pues por eso mismo. Porque ahora va, pero mal. Y cada día que pasa, cada usuario que se conecta, cada nuevo informe que se genera, lo hace un poco peor.

La deuda técnica no caduca. Se acumula. Y cuando salta, no lo hace con un error bonito y fácil de arreglar. Lo hace con un rendimiento desastroso en el peor momento: justo antes del cierre contable, durante el Black Friday o cuando el CEO quiere ver “cómo va todo” desde Power BI (todo casos reales).

Si optimizar parece caro, espera a ver cuánto cuesta no hacerlo.

Formación, experiencia y algo de mala leche

Sí, optimizar lleva tiempo. Requiere saber leer planes de ejecución, entender estadísticas, conocer cómo SQL Server decide qué estrategia usar y cuándo. Pero también requiere actitud. Ganas de escarbar. De no conformarse con que funcione “más o menos”.

Y eso, lamentablemente, no lo da ningún botón mágico ni el asistente del Management Studio. Hay que aprenderlo. O contratar a alguien que lo sepa.

Aquí es donde entra mi parte, claro. No solo como autor de este blog, sino también como consultor. Llevo más de 12 años viendo barbaridades que harían llorar al optimizador de consultas. Y ayudando a equipos a entender por qué sus bases de datos son lentas, y cómo hacer que dejen de serlo sin hipotecar la nube ni sacrificar fines de semana enteros en tareas de mantenimiento que no deberían existir.

Y sí, estoy escribiendo un libro

Mi libro se va a llamar “SQL SERVER: La NO guía práctica de optimización”. Y no será el típico tocho con recetas milagrosas genéricas que nadie es capaz de aplicar en producción. Será un manual honesto, directo y realista. Uno que explica cómo optimizar sin morir en el intento, desde la base y comprendiendo el funcionamiento interno del motor de base de datos. Porque ya tenemos demasiadas presentaciones bonitas que no dicen nada.

Y sí, también haré formación. Y talleres. Y sesiones donde, si hace falta, nos peleamos con los planes de ejecución hasta que canten. Porque se puede. Porque debe hacerse. Y porque seguir pagando licencias por no optimizar… simplemente no tiene sentido.

¿Quieres dejar de pagar por no saber? Hablemos.

Si después de leer esto has pensado en esa consulta que lleva años sin tocar, en ese informe que tarda 12 minutos, o en ese servidor que cada semana pide más cores como si fueran cromos… ya sabes lo que hay.

Puedes seguir ignorándolo, puedes aprender cómo optimizar SQL Server o puedes llamarme y lo miramos juntos.

Tu factura lo va a notar.

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

El mito de los atajos en bases de datos: por qué no hay recetas mágicas

Pocas cosas me generan más frustración que una presentación titulada “10 trucos infalibles para optimizar tu base de datos en 5 minutos”. No porque no quiera rendimiento (lo quiero, y mucho, como todos), sino porque llevo demasiado tiempo en esto como para creer que la administración de bases de datos funciona a base de fórmulas mágicas o guías milagrosas. Cada entorno tiene sus peculiaridades, sus desastres heredados y sus decisiones cuestionables. Pretender que una receta genérica resuelva un problema específico es como recetar paracetamol para un clúster caído. Puede calmar al usuario, pero no soluciona nada.

Atajos en bases de datos que suenan bien pero no funcionan

He visto más veces de las que me gustaría cómo ciertas “técnicas exprés” se convierten en dogmas. Muchas veces aparecen en foros, otras en conversaciones de pasillo, y a veces incluso las incluye algún artículo con demasiadas estrellitas y poca base técnica. Algunas de estas ocurrencias incluso se disfrazan de buenas prácticas, cuando en realidad son puro maquillaje técnico.

Uno de los clásicos eternos es el de desactivar todos los índices antes de una carga masiva. Suena lógico: menos índices, menos mantenimiento durante la inserción. Y puede tener sentido, pero solo si sabemos lo que estamos haciendo. ¿Qué tipo de índices hay? ¿Son realmente necesarios? ¿Cuál es el coste de reconstruirlos después? Porque de nada sirve ahorrar cinco minutos en la carga si luego pasamos tres horas rehaciendo estructuras en plena ventana de mantenimiento (o peor, fuera de ella).

Otro habitual es el uso de hints a ciegas, como si un INNER HASH JOIN fuera una especie de hechizo arcano que mágicamente convierte cualquier consulta en un rayo de luz. El problema, claro, es que el optimizador tiene más información de la que solemos tener nosotros en tiempo de ejecución. Forzar un plan sin pruebas, sin medir, sin entender por qué el motor decide lo que decide, es jugar a ser adivino con el presupuesto de IOPS de otro.

Y por supuesto, no podía faltar el legendario DBCC SHRINKDATABASE, convertido en herramienta habitual de “mantenimiento” por muchos que aún no se han parado a medir sus consecuencias reales. Fragmentación masiva, crecimiento inmediato posterior, tiempos de espera, y un uso de recursos que no compensa ni en entornos de desarrollo, mucho menos en producción. Apretar y soltar el disco como si fuera un globo no libera espacio: solo complica las cosas.

También me topo, de tanto en tanto, con scripts “mágicos” que prometen optimizar todas las consultas de una base de datos con un solo clic. El solo hecho de que alguien los haya escrito ya es preocupante, pero lo que me quita el sueño es que otros los ejecuten sin pararse a pensar. Optimizar no es lanzar un script genérico; es entender, medir, corregir y validar. Todo lo demás es ruido.

La influencia de las redes sociales y los vídeos cortos

En los últimos años, hemos visto cómo el contenido técnico (especialmente en campos con más tracción como ciberseguridad, desarrollo web o administración de sistemas) ha sido invadido por lo que yo llamo la cultura del vídeo de 30 segundos. Esos fragmentos de sabiduría empaquetada en un reel, un TikTok o un hilo de X (antes Twitter, cuando la gente aún sabía debatir sin stickers), donde se vende una técnica como si fuera una revelación divina.

Y aunque parecía que nuestro sector de las bases de datos estaba a salvo de esa superficialidad, cada vez veo más vídeos y publicaciones que sugieren cosas como “optimiza tu SQL Server con este comando”, “el índice que no conocías y te cambiará la vida”, o directamente “el script definitivo para tunear tu instancia”. La cruda realidad es que si usas un script definitivo sin saber qué hace, probablemente estés abriendo un ticket para mí en dos semanas.

¿Que hay gente compartiendo contenido útil? Por supuesto. Pero también hay mucho perfil que ha aprendido a posicionarse en el algoritmo antes que en el execution plan. Lo importante ya no es si lo que dicen tiene sentido, sino si entra bien en vertical, con una música pegadiza de fondo y subtítulos en negrita.

No tengo nada en contra del formato ágil, yo también consumo contenido rápido, pero sí tengo todo en contra de presentar trucos sin contexto, sin advertencias, y sin reconocer que la base de datos no es un entorno de juguete. Es producción. Y producción no se toca a base de “5 tips en 30 segundos”.

El problema no es solo la desinformación. Es que, al repetirse tanto, estos “atajos mágicos” terminan calando. Y entonces llegan al entorno del cliente, del compañero, o al nuestro, envueltos en frases como “vi a un experto decir que esto mejora el rendimiento” o “lo probé en local y funcionó”. El día que alguien monte un clúster con instrucciones de un TikTok, no quiero estar cerca.

La importancia de entender los fundamentos de SQL Server

Lo que realmente marca la diferencia no son los trucos, sino entender qué está pasando dentro del motor. Cuando dejamos de repetir recetas y empezamos a estudiar el comportamiento real de SQL Server, la administración deja de ser un ejercicio de fe y se convierte en una disciplina técnica seria.

Por ejemplo, saber que SQL Server trabaja internamente con páginas de 8 KB nos hace pensar mejor en los tipos de datos, la compresión, la fragmentación y el diseño de índices. Si no entendemos eso, cualquier optimización será como mover las sillas en el Titanic mientras se hunde, entretenido, pero inútil.

También aprendemos cómo funciona el optimizador de consultas, qué espera encontrar, cómo interpreta las estadísticas, y por qué a veces se equivoca. La cardinalidad, ese concepto que a muchos les suena a magia negra, resulta ser clave para entender por qué una consulta se convierte en un escaneo de tabla de millones de filas o en un plan eficiente con pocos milisegundos de CPU.

Y sí, los bloqueos no son enemigos a eliminar. Son síntomas, advertencias, mecanismos de protección. Una transacción larga puede ser más dañina que cien bloqueos bien gestionados. Aprender a leer deadlock graphs, entender niveles de aislamiento y diseñar correctamente el acceso concurrente es mucho más útil que cualquier script que prometa “evitar bloqueos automáticamente”.

Tampoco podemos olvidarnos de las estadísticas. Ejecutar UPDATE STATISTICS porque lo leímos en una lista de tareas semanales es mejor que nada, pero muy lejos de una estrategia de mantenimiento inteligente. Entender cuándo se actualizan, cómo afectan a los planes de ejecución y qué impacto tienen en entornos con muchas escrituras es parte del trabajo que no puede automatizarse con un clic.

Logo SoyDBA

Únete a la newsletter de SoyDBA

Regístrate gratis para no perderte ninguna novedad. Te avisaré de noticias y eventos importantes

¡No hacemos spam! Lee nuestra política de privacidad para obtener más información.

Conocimiento frente a atajos: la diferencia entre arreglar y entender

Aquí es donde la cosa se pone seria. Porque cualquiera puede buscar un error en Google, copiar el primer bloque de código que encuentra y cruzar los dedos. Pero entender el origen del problema, anticipar sus consecuencias y aplicar una solución sostenible y perdurable requiere tiempo, conocimiento y experiencia. Y eso no se compra ni se descarga.

Cuando tengo que elegir entre arreglar algo deprisa o entender por qué está roto, prefiero lo segundo. Porque arreglar sin comprender es pan para hoy y desastre para mañana. Ya nos conocemos ese guion: parche rápido, alivio temporal, y dentro de una semana… el mismo problema, pero más grande.

Los atajos, en general, no resuelven nada. Solo tapan síntomas. Como esa costumbre de algunos de hacer REBUILD INDEX sin mirar estadísticas de fragmentación, sin diferenciar índices columnstore y sin medir el impacto real en el rendimiento. Más mantenimiento no siempre es mejor mantenimiento. A veces es solo ruido.

Conclusión

Si algo tengo claro después de más de una década en esto es que los milagros no existen en administración de bases de datos. Hay herramientas útiles, sí. Hay buenas prácticas, también. Pero no hay soluciones universales. Y cada vez que alguien actúa como si las hubiera, lo único que consigue es complicar aún más el trabajo de quienes venimos detrás a recoger los pedazos.

SQL Server no premia al que improvisa, sino al que entiende. No necesitamos más scripts mágicos, necesitamos más análisis, más diagnóstico, más contexto. Y sobre todo, más respeto por el conocimiento técnico. Porque al final, el rendimiento real no llega por hacer más clics, sino por hacer las preguntas correctas y saber interpretar las respuestas.

Así que, si alguien te promete un truco definitivo para que tu base de datos vuele, recuerda: también hay quien promete que los cursores funcionan bien. No les creas.

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

¿Por qué estudiar los fundamentos?

Llevo más de una década trabajando con bases de datos, y si hay algo que tengo cada vez más claro es esto: los fundamentos importan. Y no, no lo digo por nostalgia académica ni por espíritu conservador. Lo digo porque cada vez que veo un desastre en producción, casi siempre hay un denominador común: alguien ignoró los fundamentos, o directamente nunca los estudió. Así que vamos a hablar de eso. De lo básico. De lo que muchos consideran opcional y, sin embargo, marca la diferencia entre un profesional que sabe lo que hace y uno que improvisa con Stack Overflow abierto en una pestaña (o ChatGPT en estos tiempos).

Fundamentos: no se ven pero se notan

Entender cómo funciona una base de datos por dentro no es un lujo, es una necesidad. Y lo digo con conocimiento de causa. Me he encontrado proyectos donde la base de datos era una especie de Frankenstein montado a base de copiar código, sin ninguna lógica de integridad ni normalización. Y claro, luego vienen los lloros cuando hay incoherencias, cuellos de botella inexplicables o bloqueos que paralizan toda la aplicación.

Hablar de fundamentos es hablar de normalización, de integridad referencial, de transacciones, de concurrencia, de índices, de bloqueos, de cómo se almacenan los datos físicamente… Y eso no es teoría: es el pan de cada día si queremos que un sistema aguante sin incendiarse cada semana.

SQL Server no es sólo Management Studio

Cuando empecé con SQL Server, también me deslumbró el Management Studio. Tan cómodo, tan visual, tan lleno de botones que prometían hacer magia. Pero claro, esa magia dura lo que tarda en explotar el primer MERGE mal planteado o en aparecer un plan de ejecución de 20 niveles de nested loops.

Con el tiempo, y a base de errores, fui entendiendo que SQL Server es una bestia que hay que conocer. Hay que saber cómo el motor registra las operaciones en el Transaction Log, cómo se gestiona la memoria, qué hace el optimizador cuando decide (o no) usar un índice. Porque si no sabes eso, estás jugando a la ruleta rusa cada vez que ejecutas algo en producción. Y lo peor: ni siquiera lo sabes.

El boom del autodidacta exprés

He visto mucha gente entrar en este mundo con ganas, con energía, con actitud. Y eso me encanta. Pero también he visto cómo se les empuja a saltarse pasos. Tutoriales que enseñan a hacer SELECT * sin explicar por qué no deberías hacerlo jamás. Cursos que te arman para hacer un JOIN pero no te dicen qué es una clave primaria o cómo se gestionan los bloqueos.

Lo autodidacta tiene muchísimo valor. Yo mismo he aprendido así muchas cosas. Pero cuando todo se basa en “funciona, siguiente”, estamos criando técnicos que saben hacer, pero no entienden lo que están haciendo. Y eso es peligroso. Porque cuando algo deja de funcionar —y tarde o temprano, lo hará— no saben por qué. Y entonces empieza el festival de parches, workarounds, y soluciones que solo esconden el problema, como barrer la mierda debajo de la alfombra.

Esto no va de teoría vs. práctica

A veces me dicen: “Eso son cosas de la universidad, lo que importa es lo que funciona”. Y yo me río. Porque he estado a las tres de la mañana revisando por qué una transacción no terminaba, por qué un índice no se usaba o por qué un proceso estaba bloqueando a media base de datos. Y en esos momentos, lo que me salvó no fue ningún truco aprendido en Reddit, sino entender cómo funciona el motor por dentro.

Los fundamentos no te hacen más lento, te hacen más preciso. No es teoría inútil, es saber en qué estás apoyando todo lo demás. Es tener criterio para decidir, no ir al tuntún. Porque cuando entiendes lo básico, puedes aprender cualquier herramienta nueva con cabeza. Pero si solo sabes herramientas, dependes de ellas como quien necesita el GPS hasta para ir a comprar el pan.

Los fundamentos son las bases que no lo básico

Hay una confusión peligrosa que veo cada vez más: pensar que los fundamentos son lo básico. Como si hablar de ACID, de niveles de aislamiento o del funcionamiento del buffer pool fuera algo para juniors, y lo verdaderamente avanzado empezara cuando montas un clúster distribuido o haces tuning con hints arcanos. Pues no. Justo al revés.

Los fundamentos no son el punto de partida. Son el núcleo. Lo que no caduca. Lo que no depende de versiones ni modas. Cuando entiendes bien cómo trabaja el motor de SQL Server con páginas de 8KB, cómo se comporta una transacción en READ COMMITTED SNAPSHOT, o qué ocurre cuando haces un ROLLBACK a mitad de un trigger, no estás en lo básico. Estás en el corazón mismo de cómo funcionan las cosas.

He visto a gente presumir de saber hacer particionamiento por fecha y, al mismo tiempo, no tener claro qué diferencia hay entre un índice agrupado y uno no agrupado. ¿De qué sirve montar una solución distribuida si no controlas el coste de una tabla sin estadísticas? ¿Qué sentido tiene optimizar con Query Store si no sabes cómo interpreta el optimizador una subconsulta correlacionada?

Los fundamentos no se superan. Se profundizan. Cada vez que los reviso, aprendo algo nuevo. Y cada vez que los ignoro… lo pago. Con tiempo, con sustos, o con llamadas a deshora

Lo que pasa cuando se olvidan los fundamentos

He visto demasiadas veces los síntomas de no haber tocado nunca los fundamentos. Tablas sin claves primarias. Tipos de datos elegidos a boleo. Relaciones “gestionadas desde la aplicación”. Procedimientos imposibles de mantener, triggers infernales, y consultas que parecen escritas por un generador aleatorio de SQL.

Y todo eso se podría haber evitado si alguien hubiese dedicado un par de tardes a entender qué es una tercera forma normal o cómo funciona un índice no agrupado. No se trata de ser purista, se trata de no meter la pata en cosas que tienen solución desde hace décadas.

¿Y entonces qué?

Pues estudiemos. Con calma. Con profundidad. No para pasar exámenes ni certificar nada, sino para trabajar mejor. Volvamos a los libros viejos que explican qué es una base de datos relacional. Leamos la documentación de SQL Server, pero de verdad, no solo los ejemplos de código. Miremos planes de ejecución como si fueran mapas del tesoro, no como pantallazos incomprensibles.

Aprender los fundamentos es como afilar el cuchillo antes de cortar. Puede parecer una pérdida de tiempo… hasta que cortas mejor, más rápido, y sin cortarte tú.

Conclusión

Yo no quiero trabajar con gente que se sabe 50 funciones de ventana pero no entiende lo que hace un ROLLBACK. Quiero trabajar con gente que tenga criterio. Y ese criterio solo se construye con base, no con atajos.

Así que sí: hay que estudiar los fundamentos. Porque eso es lo que marca la diferencia entre un profesional fiable y alguien que copia y pega esperando que funcione. No es glamour. No es moda. Es oficio.

Y si este verano tienes un rato, échale un ojo a cómo funciona el Transaction Log. Te prometo que es más interesante que muchas series. Y desde luego, más útil.

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 Otros, 1 comentario