Informática y Sistemas (β)

2009/10/07 - 7 octubre 2009

Evitando campos de tipo bit en tablas SQL Server 2008

Filed under: Notas sobre Productos,Tips de Desarrollo — Mario Mendez @ 22:23
Tags: ,
evaluando usar bit como tipo de dato

evaluando usar el bit como tipo de dato

Muchas veces tendemos a almacenar registros con ciertos campos que ofician de “banderas” (flags) para representar información que solo tienen dos estados posibles (sí-no; verdadero-falso; 1-0; etc.)  Este tipo de recurso es tradicional y se utiliza desde los primeros sistemas de bases de datos de acceso secuencial, donde la longitud del registro se diseñaba bit a bit; y el largo del mismo era crucial para minimizar la capacidad total, cuyo almacenamiento era sumamente costoso. En estos sistemas antiguos tomar la decisión de reservar dos o tres bit por registro para necesidades futuras era un tema para evaluar seriamente. Sin embargo el tiempo ha pasado, los sistemas de almacenamiento como SQL Server 2008 tienen acceso aleatorio apoyado por índices, y los costos de almacenamiento se abarataron hasta dejar de ser una preocupación primordial. Bajo este contexto hoy en día debemos evaluar la importancia de usar campos de tipo bit, pero desde otro punto de vista: desde el rendimiento del sistema.

Para ver la importancia que tiene este tipo de dato bit, minúsculo y casi despreciable frente a las magnitudes que se manejan hoy en día para almacenamiento dónde es común hablar de teras y hasta exabytes  (1048576 terasbytes de información), partimos de la definición que nos da el producto dónde nos informan que se ha optimizado el sistema para agrupar los campos bit de a 8 por cada registro, almacenándolos en un solo byte. Esto es debido a que en una consulta, aunque se especifiquen unos pocos campos incluyendo uno de tipo bit para el resultado el motor no puede leer “solo” un bit de información. Lo que se está realizando internamente es levantar el campo byte correspondiente al grupo que incluye este campo bit, y parsea la posición que le corresponde dentro de dicho byte según un mapeo interno para extraer su valor. Esto aunque bien manejado, es una carga extra para el motor de ejecución; y empeora aún más si el campo bit se utiliza para filtrar los resultados obtenidos de una consulta. En bases de datos de millones de registros este puede ser un factor de ralentización importante y susceptible de ser optimizado (diría que hasta necesariamente). El mecanismo descrito no es nuevo, se viene utilizando desde versiones tempranas de SQL Server, aunque nunca fue muy difundido este detalle.

En los sistemas de hoy en día, donde es común manejar lógica de negocio estructurada según diagramas de estados que describen el ciclo de vida de un registro, la necesidad de recurrir a banderas se encuentra minimizada y con un par de de estos campos se resuelven la mayoría de las situaciones. Bajo esta perspectiva, y en vista del bajo costo relativo y disponibilidad de altas capacidades de almacenamiento la mejor solución es destinar a estas banderas campos de datos tipo entero (int), que es el tipo básico y que mejor maneja el motor de ejecución. En este sentido conviene establecer la convención de interpretación a nivel de negocio consistente con los estándares (0 para falso y 1 verdadero) para facilitar su integración.

En efecto, utilizar banderas implementadas en campos de tipo entero mejora el rendimiento de las consultas tanto para obtener resultados como para realizar filtrados en base a estos campos; y personalmente no he necesitado recurrir a más de tres banderas para integrar a una misma tabla. Generalmente en sistemas modernos, la mayoría de las veces que se cae en el abuso del recurso de banderas casi siempre corresponde a pobres criterios de diseño que a necesidades reales; por lo que conviene hacer algún replanteo antes de proseguir ese camino.

(tiny)

6 comentarios »

  1. Muy bueno tu aporte creo que esto es muy importante en consideración para el diseño de un sistema ya que no tomar estos datos en cuenta son el error común de los programadores jóvenes que aun no saben apreciar el valor de los datos y tiempos sobre transacciones de un sistema de información

    Comentarios por vriks87 — 2013/11/12 - 12 noviembre 2013 @ 09:13 | Responder

    • Gracias por el feedback, a veces la falta de información sobre como cambian los estándares para nuevos productos o tecnologías hacen persistir antiguas prácticas por la tradición, más que por la lógica.

      Comentarios por Mario Mendez — 2013/11/12 - 12 noviembre 2013 @ 14:04 | Responder

  2. Creo que el valor de los campos bit es a nivel de integridad de datos: solo puedes tener 1 y 0, y a nivel booleano se integra perfectamente con .NET. Así que si deseas que la BD te ayude con la integridad de datos, aun es bueno usar bit.

    Comentarios por Roberto Miguel Garcia Aguirre — 2019/02/07 - 7 febrero 2019 @ 20:11 | Responder

    • Depende del tipo de solución y diseño la decisión final. Conociendo el problema de fondo, siempre hay que analizar el modo que se utiliza el campo flag.
      a-Si la base lo almacena como un dato accesorio, con pocos registros o con consultas que no filtran por este valor en forma masiva, la comodidad de que se integre en .net puede ser lo mejor para no complicarse con la conversión intermedia, sobre todo en formularios mapeados directamente a este campo sin entidades de paso, al estilo aplicaciones MVC o Web API en desarrollos rápidos, que suelen ser bastante restrictivos con el manejo de conversiones.
      b-Pero si la base a diseñar sabemos que tendrá una gran volumen, con una cantidad de registros importantes donde la velocidad de consultas masivas es crítica, el campo bit puede ser nefasto y dar muchos dolores de cabeza al querer optimizarlas. Hoy en día con los servicios de nube, donde los tiempos de procesamiento se facturan y son bastantes onerosos, puede ser un factor determinante para minimizar costos. La comodidad siempre tiene un precio.

      Comentarios por Mario Mendez — 2019/08/31 - 31 agosto 2019 @ 23:21 | Responder

  3. Y si en lugar de utilizar tipo int utilizamos smallint, se evita tambien problemas de velocidad ?? o solo se aconseja usar tipo int ??

    Comentarios por esteban — 2019/05/07 - 7 May 2019 @ 23:34 | Responder

    • El problema de fondo con los campos bit es el algoritmo que emplea forzosamente el motor para hacer el «parsing» registro a registro, obteniendo los bit que los componen y filtrando el que corresponda al campo en cuestión.
      No creo que haya mayor diferencia entre un int o un smallint, porque en ambos casos se usa el dato numérico en forma completa dentro del campo, sin necesitar desmembrar el valor en los diferentes bit asociados al mismo.
      Igualmente no tengo hechas pruebas con smallint como para asegurar que sean igualmente de eficientes la consultas al filtrarlo por este campo en consultas masivas.
      Personalmente la decisión entre int o smallint la haría por tema de comodidad de uso, o capacidad de almacenamiento si es relevante por cantidad de registros, antes que por rendimiento.

      Comentarios por Mario Mendez — 2019/08/31 - 31 agosto 2019 @ 23:04 | Responder


RSS feed for comments on this post. TrackBack URI

Deja un comentario

Crea un blog o un sitio web gratuitos con WordPress.com.