Máxima cantidad de columnas en una tabla

3 comentarios

Si te preguntan ¿cuántas columnas puede tener una tabla de Firebird? tu respuesta debe ser: “depende de los tipos de datos de las columnas”

¿Por qué eso?

Porque en Firebird no hay una cantidad máxima de columnas, como sí hay en Visual FoxPro, en Access y en otros lenguajes o motores de bases de datos. En los dos anteriormente nombrados el límite es de 255 columnas, pero en Firebird no existe tal cosa.

¿Por qué no?

Porque en Firebird una fila puede tener un máximo de 65.536 bytes y por lo tanto la cantidad máxima de columnas que puede tener una tabla varía entre 1 y 65.536

 Veamos esto más detalladamente:

Algunos tipos de datos ocupan una cierta cantidad predeterminada de bytes. Por ejemplo, SMALLINT ocupa siempre 2 bytes, INTEGER ocupa siempre 4 bytes, BLOB ocupa siempre 4 bytes, etc.

Pero tenemos dos casos especiales, que son CHAR y VARCHAR, la cantidad de bytes que ellos ocupan dependen del CHARACTER SET usado. Si no especificamos un CHARACTER SET o especificamos uno de los llamados “occidentales” entonces 1 carácter ocupará siempre 1 byte. Para nosotros que escribimos en castellano, portugués, francés, inglés, u otros idiomas occidentales eso es lo normal. Pero para quienes escriben en árabe, hebreo, chino, japonés, coreano, vietnamita, etc., eso ya no es cierto. Entonces, si el CHARACTER SET de la columna es por ejemplo ISO8859_1 (el recomendado para guardar texto escrito en castellano) una columna definida como CHAR(20) se cuenta como 20 bytes pero si el CHARACTER SET de la columna es UTF8 entonces una columna definida como CHAR(20) se cuenta como 40 bytes, ya que cada carácter ocupa 2 bytes cuando se usa UTF8.

¿Qué implica todo esto?

Que solamente tendremos problemas si la suma de los bytes ocupados por todas las columnas supera la cantidad de 65.536, si es igual o menos que eso estará todo bien.

Como vimos anteriormente, es muy fácil hacer esa suma.

Ejemplo 1:

Evidentemente, cada caso es distinto, depende de la estructura de la tabla para saber cuantas columnas como máximo puede tener pero supongamos lo siguiente para este ejemplo:

La cantidad de bytes que ocupa cada columna de una tabla es en promedio de 20. Por lo tanto, dividiendo 65.536 por 20 obtenemos como resultado 3.276 y para esa tabla en particular podríamos tener hasta 3.276 columnas.

Como vemos, mucho más que las 255 columnas del Visual FoxPro o del Access

De todas maneras, si necesitas una tabla que tenga tantas columnas lo más probable es que tu diseño esté muy mal y tendrías que ver la forma de mejorarlo.

Ejemplo 2:

En una tabla solamente necesitamos guardar números enteros y como cada columna de tipo INTEGER ocupa 4 bytes entonces podríamos tener un máximo de 65.536 / 4 columnas lo cual nos da como resultado 16.384 columnas.

Ejemplo 3:

En una tabla necesitamos guardar una columna de tipo SMALLINT, tres columnas de tipo INTEGER, y el resto serán columnas de tipo CHAR(60). Entonces tenemos: 65.536 – 2 – 3 * 4 = 65.522, y como 65.522 / 60 es igual a 1.092, podríamos tener hasta 1.096 columnas en esa tabla (1 columna SMALLINT, 3 columnas INTEGER, y 1.092 columnas CHAR(60)).

Conclusión:

En Firebird no hay una cantidad máxima de columnas que puede tener una fila de una tabla, lo que sí hay es una cantidad máxima de bytes que puede tener una fila de una tabla. Ese número es 65.536 bytes y es muchísimo más que suficiente para todas las necesidades que podamos tener. Si llegamos a necesitar más que 65.536 bytes entonces es seguro que nuestra Base de Datos está mal diseñada y deberíamos preocuparnos por mejorar eso.

Artículos relacionados:

Entendiendo a los conjuntos de caracteres

Algo más sobre los conjuntos de caracteres

Funciones útiles con los conjuntos de caracteres

Cantidad de columnas de una tabla

El índice del blog Firebird21

El foro del blog Firebird21

 

 

La problemática de las tablas maestras

9 comentarios

Cuando diseñamos una Base de Datos normalmente creamos cuatro tipos de tablas:

  • Configuración
  • Maestras
  • Movimientos
  • Auxiliares

Las tablas de configuración servirán para guardar datos que ayudarán a personalizar la aplicación relacionada.

Las tablas maestras servirán para guardar datos que luego usarán las tablas de movimientos.

Las tablas de movimientos servirán para guardar lo que ocurre en la operación normal de la empresa u organización, sus actividades diarias. A su vez se clasifican en cabecera y en detalle.

Las tablas auxiliares servirán para guardar datos temporales.

En las tablas de movimientos siempre tenemos una columna donde guardamos la fecha del movimiento, así que no es problema conocer las fechas cuando las necesitamos.

Pero eso muchas veces no ocurre con las tablas maestras, en ellas no se suelen guardar las fechas. Y puede ser muy necesario conocerlas.

Ejemplo:

Tenemos una tabla maestra de CLIENTES donde entre otros datos guardamos el Identificador del Cliente, su Nombre, su Dirección, su Teléfono. Y una tabla cabecera de VENTAS donde guardamos el Identificador de la Venta, el Identificador del Cliente, el Número de la Factura, la Fecha de la venta y otros datos.

Le hacemos una venta al cliente Juan Pérez, e imprimimos la Factura Número “001-002-3456789” que corresponde a esa venta. En ella consta que la Dirección de Juan Pérez es “Colón 12345” y que su teléfono es el “0123-456789”. Todo bien hasta ahí, ningún problema, se va Juan Pérez con su Factura.

Un tiempo después regresa Juan Pérez, le hacemos otra venta, pero nos dice que se mudó y que por lo tanto se cambió su Dirección, su Teléfono y hasta su Localidad. Así que ahora le imprimimos la Factura Número “001-002-9876543” que corresponde a esta última venta, la nueva Dirección es “Spartacus 44444” y el nuevo teléfono es el “0333-555555”. Todo bien hasta ahí, ningún problema, se va Juan Pérez con su Factura.

Pero …. luego surge el problema.

Hay una auditoría, el ente recaudador de impuestos hace un control cruzado entre las Facturas de Juan Pérez y nuestras Facturas y al consultar la Factura “001-002-3456789” le dice que la Dirección es “Spartacus 44444” y el Teléfono es “0333-555555” porque esos son los datos que tenemos guardados de Juan Pérez en nuestra Base de Datos actualmente.

Y está mal.

Está mal porque la Dirección que se imprimió en esa Factura era “Colón 12345”. Y aunque pasen los años y Juan Pérez se mude de casa muchas veces siempre que consultemos los datos de la Factura Número “001-002-3456789” deberíamos ver que la Dirección es “Colón 12345”. No la última Dirección que registramos en nuestra tabla de CLIENTES sino la Dirección original.

¿Cuál es la solución a este problema?

Tenemos tres alternativas, dos malas y una buena.

Una alternativa mala es restaurar un backup de la fecha de la primera venta a Juan Pérez para saber que Dirección teníamos guardada ese día.

Otra alternativa mala es guardar en la tabla cabecera de VENTAS la Dirección, el Teléfono, la Localidad, el Email y otros datos de Juan Pérez. Es cierto que eso nos aseguraría de imprimir siempre los datos correctos pero nuestra tabla no estaría normalizada y por lo tanto gastaríamos mucho más espacio en el disco duro que el necesario.

La alternativa buena es guardar en otra tabla, no en la tabla de CLIENTES sino en otra tabla, los cambios que se realicen a los datos de nuestros clientes. La estructura de esta tabla (la podríamos llamar CAMBIOS_CLIENTES) debería ser idéntica a la tabla CLIENTES pero tendría una columna más, esa columna adicional sería el Identificador de la tabla (el que usamos para su Primary Key).

La tabla CLIENTES (y por lo tanto la tabla CAMBIOS_CLIENTES) debe tener una columna donde se guarde el nombre del usuario que insertó la fila y otra columna donde se guarden la fecha y la hora de esa inserción.

De esta manera siempre podríamos saber cuales eran los datos de Juan Pérez en cualquier día de cualquier mes de cualquier año.

¿Cuál era la Dirección de Juan Pérez el día 12 de agosto de 2013?

  1. Buscamos en la tabla CAMBIOS_CLIENTES la fila más nueva que corresponda a Juan Pérez y que su fecha sea 12 de agosto de 2013 o anterior.
  2. Si la encontramos, esa es la Dirección de Juan Pérez el día 12 de agosto de 2013
  3. Si no la encontramos, buscamos en la tabla CLIENTES cual es la Dirección que originalmente tenía Juan Pérez
  4. Si esa fila fue insertada el día 12 de agosto de 2013 o antes, esa es la respuesta buscada
  5. Si la fila fue insertada posteriormente al 12 de agosto de 2013 entonces Juan Pérez aún no era nuestro cliente ese día y por lo tanto no podemos saber cual era su Dirección.

El problema con las tablas maestras

Lo que vimos en el ejemplo anterior, con las ventas a Juan Pérez y sus cambios de direcciones se aplica a todas las tablas maestras. Cualquier tabla maestra que tengamos adolecerá del mismo problema si no tomamos las debidas precauciones: que estaremos viendo los últimos datos, no los datos que teníamos anteriormente. Y en muchos casos los que deberíamos ver son los datos que teníamos anteriormente.

Una Base de Datos que no puede ser retrotraída a cualquier instante anterior no está bien diseñada.

Es así de simple:

  • Si yo necesito recurrir a un backup para que una consulta me muestre los datos correctos entonces mi Base de Datos está mal diseñada. Nada que discutir.
  • Si las tablas no están normalizadas entonces mi Base de Datos está mal diseñada. Nada que discutir.

Un buen diseño implica más trabajo

Todo tiene sus ventajas y sus desventajas, nada es perfecto. Podemos tener una Base de Datos perfectamente diseñada que nos permita responder a cualquier pregunta en cualquier momento, pero eso demandará más de nuestro tiempo. Y es que por cada tabla maestra deberemos tener una tabla de CAMBIOS. Y por cada tabla maestra deberemos tener un trigger AFTER UPDATE que le inserte una fila a la tabla de CAMBIOS. Y a su vez nuestras consultas (SELECTs) serán más complicadas cuando involucren a las preguntas ¿quién? ¿cuándo? o ¿desde cuándo? y ¿hasta cuándo?

La diferencia entre tener una Base de Datos muy bien diseñada y una pobremente diseñada la verás el día que quieras venderle tu aplicación a gente que entiende de Informática. Mientras tus clientes sean ignorantes en temas informáticos podrás venderles casi cualquier cosa pero el tema es muy distinto cuando hablas con gente entendida. Por ejemplo si una empresa tiene un Departamento de Informática es seguro que tendrás que entrevistarte con los encargados y allí enseguida descubrirán tu pobre diseño.

Por lo tanto, si quieres vender tus aplicaciones a empresas de cualquier tamaño y no pasar vergüenza cuando hables con el personal informático, diseña tu Base de Datos de la mejor manera posible.

Artículos relacionados:

El índice del blog Firebird21