¿Qué ganan las bases de datos relacionales al establecer un tipo de datos predefinido para cada columna?

44

Estoy trabajando con una base de datos SQL en este momento, y esto siempre me ha dado curiosidad, pero las búsquedas de Google no aparecen mucho: ¿por qué los tipos de datos estrictos?

Entiendo por qué tendría algunos tipos de datos diferentes, por ejemplo, cómo es importante diferenciar entre datos binarios y de texto sin formato . En lugar de almacenar los 1 y 0 de los datos binarios como texto sin formato, ahora entiendo que es más eficiente almacenar los datos binarios en su propio formato.

Pero lo que no entiendo es cuál es el beneficio de tener tantos tipos de datos diferentes:

  • ¿Por qué mediumtext, longtexty text?
  • ¿Por qué decimal, floaty int?
  • etc.

¿Cuál es el beneficio de decirle a la base de datos "Solo habrá 256 bytes de datos de texto sin formato en las entradas de esta columna". o "Esta columna puede tener entradas de texto de hasta 16.777.215 bytes"?

¿Es un beneficio de rendimiento? Si es así, ¿por qué conocer el tamaño de la entrada de antemano ayuda al rendimiento? ¿O más bien es algo completamente diferente?

John Doe
fuente
2
Pensé que esta pregunta ya debería existir aquí, pero busqué en el sitio y no encontré nada útil.
John Doe
66
Si no tuviera distintos decimal, floaty inttipos, ¿qué esperaría 1 / 3hacer? ¿Qué hay de 1.0 / 3.0? ¿Podría estar seguro de que cuando divide columnApor columnBeso obtendrá los resultados que espera?
Andrew dice que reinstala a Mónica
2
@johndoe No creo que sea necesario, pero podría ser muy conveniente. Supongamos que desea imponer una restricción de que el inventario de una tienda no puede ser inferior al 5% de sus ventas mensuales esperadas. O desea asegurarse de que el presupuesto total de cada división no supere el 20% del presupuesto total. También podría aparecer en columnas calculadas que desea calcular de la misma manera en varias aplicaciones que usan la misma base de datos.
Andrew dice que reinstale a Mónica
2
Vale la pena señalar que SQLite no establece un tipo predefinido por columna : "SQLite es" sin tipo ". Esto significa que puede almacenar cualquier tipo de datos que desee en cualquier columna de cualquier tabla, independientemente del tipo de datos declarado de esa columna. "
Prime

Respuestas:

50

SQL es un lenguaje de tipo estático . Esto significa que debe saber de qué tipo es una variable (o campo, en este caso) antes de poder usarla. Esto es lo opuesto a los lenguajes de tipo dinámico, donde ese no es necesariamente el caso.

En esencia, SQL está diseñado para definir datos ( DDL ) y datos de acceso ( DML ) en un motor de base de datos relacional . La escritura estática presenta varios beneficios sobre la escritura dinámica para este tipo de sistema.

  • Los índices , utilizados para acceder rápidamente a registros específicos, funcionan realmente bien cuando el tamaño es fijo. Considere una consulta que utiliza un índice, posiblemente con múltiples campos: si los tipos y tamaños de datos se conocen con anticipación, puedo comparar muy rápidamente mi predicado (cláusula WHERE o criterios JOIN) con los valores en el índice y encontrar los registros deseados más rápido .

  • Considere dos valores enteros . En un sistema de tipo dinámico, pueden ser de tamaño variable (piense en Java BigIntegero en los enteros de precisión arbitraria incorporados de Python). Si quiero comparar los enteros, primero necesito saber su longitud de bits. Este es un aspecto de la comparación de enteros que está oculto en gran medida por los lenguajes modernos, pero es muy real a nivel de CPU. Si los tamaños son fijos y se conocen con anticipación, se elimina un paso completo del proceso. Una vez más, se supone que las bases de datos pueden procesar millones de transacciones lo más rápido posible. La velocidad es el rey.

  • SQL fue diseñado en la década de 1970. En los primeros días de la microcomputación, la memoria era muy importante. La limitación de datos ayudó a mantener los requisitos de almacenamiento bajo control. Si un número entero nunca supera un byte, ¿por qué asignarle más almacenamiento? Ese es el espacio perdido en la era de la memoria limitada. Incluso en los tiempos modernos, esos bytes adicionales desperdiciados pueden sumar y matar el rendimiento del caché de una CPU. Recuerde, estos son motores de base de datos que pueden prestar servicio a cientos de transacciones por segundo, no solo su pequeño entorno de desarrollo.

  • En la línea de almacenamiento limitado, es útil poder ajustar un solo registro en una sola página en la memoria. Una vez que pasa una página, hay más errores de página y más acceso lento a la memoria. Los motores más nuevos tienen optimizaciones para que esto sea un problema menor, pero todavía está ahí. Al dimensionar los datos de manera adecuada, puede mitigar este riesgo.

  • Más aún, en los tiempos modernos, SQL se utiliza para conectarse a otros idiomas a través de ORM u ODBC o alguna otra capa. Algunos de estos lenguajes tienen reglas para requerir tipos fuertes y estáticos. Es mejor cumplir con los requisitos más estrictos, ya que los lenguajes de tipo dinámico pueden manejar tipos estáticos más fácilmente que al revés.

  • SQL admite la escritura estática porque los motores de base de datos lo necesitan para el rendimiento, como se muestra arriba.

Es interesante notar que hay implementaciones de SQL que no están fuertemente tipadas. SQLite es probablemente el ejemplo más popular de un motor de base de datos relacional. Por otra parte, está diseñado para uso de un solo subproceso en un solo sistema, por lo que las preocupaciones de rendimiento pueden no ser tan pronunciadas como, por ejemplo, en una base de datos Oracle empresarial que atiende millones de solicitudes por minuto.

gruszczy
fuente
SQLite tiene tipos de datos que distinguen entre datos numéricos y de texto, pero solo tiene 5 "clases" de almacenamiento de datos: sqlite.org/datatype3.html
FrustratedWithFormsDesigner
1
@FrustratedWithFormsDesigner Lo sé, pero todavía no es tan estricto como los motores como SQL Server, Oracle o PostgreSQL.
SQL no solo está tipificado estáticamente, debido a la presencia de restricciones de verificación, sino que también admite tipos de refinamiento.
cabeza de jardín
44
Aunque está implícito en la primera viñeta Indexes, se dice más básicamente: tener un tipo de datos permite que el motor de la base de datos tenga sentido de los datos , hacer comparaciones (números más grandes / más pequeños, fechas anteriores / posteriores, antes / después en el alfabeto), y, por lo tanto, permite ordenar y consultar .
Basil Bourque
Entonces, si los tamaños son importantes ... y sql necesita saber de antemano ... ¿cuál es el tamaño exacto de las transacciones "Zillion"?
WernerCD
24

Primero: el texto plano es binario (ni siquiera son los caracteres UTF8 o ASCII "0" y "1", sino bits de activación / desactivación reales)

Dicho esto, algunas de las razones son:

  • Restricciones empresariales / de diseño: permitir el número 7626355112 en la columna ALTURA de la tabla PERSONA estaría mal. Permitir "Howya" en la columna FECHA de una FACTURA estaría mal.
  • Menos código propenso a errores: no tiene que escribir código para asegurarse de que los datos recuperados de una columna de fecha sean realmente una fecha. Si los tipos de columna fueran dinámicos, tendría que hacer muchas verificaciones de tipo al leerlos.
  • Eficiencia informática: si una columna es de tipo INTEGER, y la SUMA (), el RDBMS no tiene que aplicar aritmética de coma flotante.
  • Eficiencia de almacenamiento: al indicar que una columna es VARCHAR (10), el RDBMS puede asignar espacio con mayor precisión.
  • Integridad referencial y unicidad: PK (o FK) de una tabla no debe permitir flotantes, ya que la igualdad de coma flotante es complicada, por lo que debe declararlos en un tipo no flotante, como caracteres o enteros.
  • Existen RDBMS con tipos de columna dinámicos (no estrictos) (SQLite) . Utiliza el concepto de "afinidad de tipos" mientras le permite insertar prácticamente cualquier cosa en cualquier columna sin quejarse. Hay compensaciones que no serán discutidas aquí. Ver esta pregunta .
Tulains Córdova
fuente
8

Es para que el código subyacente en el que está escrita la base de datos pueda asignar y usar registros de tamaño fijo, si sabe que un campo específico puede contener de 0 a 256 caracteres de texto, puede asignar un bloque de 256 bytes para almacenarlo.

Esto hace que las cosas sean mucho más rápidas, por ejemplo, no tiene que asignar almacenamiento adicional a medida que el usuario escribe, ya que un campo dado siempre inicia x bytes en el registro, una búsqueda o selección en ese campo sabe que siempre debe verificar x bytes en cada registro, etc.

Steve Barnes
fuente
Si tan solo todas las respuestas pudieran ser concisas y al punto ...
Darren Ringer
6

Cuando las columnas de una base de datos reciben tipos definidos, los tipos generalmente se definen a sí mismos para tener un cierto tamaño en bits. Como resultado:

1) cuando el motor de la base de datos atraviesa las filas de una tabla, no tiene que realizar ningún análisis sofisticado para determinar dónde termina cada registro, solo puede saber que cada fila consta de, digamos, 32 bytes, y así obtener el El siguiente registro es suficiente para agregar 32 bytes a la ubicación de los registros actuales.

2) al buscar un campo dentro de una fila, es posible conocer un desplazamiento exacto para ese campo nuevamente sin analizar nada, por lo que las búsquedas de columnas son una operación aritmética simple en lugar de una de procesamiento de datos potencialmente costosa.

Usuario no encontrado
fuente
Los campos de longitud fija pueden hacer que el procesamiento sea más eficiente debido a longitudes de registro consistentes y compensaciones de campo, pero los campos de longitud variable pueden anular esos beneficios porque la longitud de registro y la compensación de los campos pueden variar. Del mismo modo, la compresión a nivel de registro dará como resultado registros de longitud variable, por lo que la ubicación de un registro dado no se puede calcular simplemente.
Zenilogix
Esto es cierto, y fue un consejo común durante mucho tiempo evitar campos de longitud variable exactamente por ese motivo. No sé cómo lo hacen los grandes jugadores, pero parece que podría recuperar algunos de los beneficios de la longitud fija haciendo que el motor almacene campos de ancho variable en una tabla o bloque de memoria no visible para el usuario y tenga el Las tablas primarias que representan esos campos deben ser un 'puntero' (ancho fijo) en él. Teniendo en cuenta que, en primer lugar, debería realizar exploraciones completas de campos de longitud variable, podría valer la pena mantener el ancho fijo en el rendimiento de la indirección.
UserNotFound
3

Preguntó por qué los DBMS tienen tipos de datos estáticos.

  1. Velocidad de búsqueda. El objetivo de un DBMS es almacenar muchos más datos de los que podría cargar en un programa. Piense "todos los recibos de tarjetas de crédito generados en el mundo en los últimos diez años". Para buscar dichos datos de manera eficiente, los tipos de datos de longitud fija son útiles. Esto es especialmente cierto para datos estructurados como sellos de fecha y números de cuenta. Si sabe con anticipación a qué se enfrenta, es más fácil cargar en índices eficientes.

  2. Integridad y limitaciones. Es más fácil mantener los datos limpios si tiene tipos de datos fijos.

  3. Historia. Los RDBMS comenzaron cuando las computadoras tenían solo unos pocos megabytes de RAM, y el almacenamiento a escala de terabytes era enormemente costoso. Guardar una docena de bytes en cada fila de una tabla podría ahorrar miles de dólares y horas en esas circunstancias.

  4. La maldición de la base de clientes. Los RDBMS de hoy son paquetes de software muy complejos y altamente optimizados, y han estado en uso durante décadas acumulando datos. Son maduros Trabajan. Un bloqueo de RDBMS que resulta en una pérdida de datos a gran escala es muy raro en estos días. Cambiar a algo con un sistema de escritura de datos más flexible no vale el costo o el riesgo para la mayoría de las organizaciones.

Analogía: puede ser obvio que los sistemas de metro urbano funcionarían mejor (más silencioso, más rápido, más eficiente en el consumo de energía) en un ancho de vía más estrecho. Pero, ¿cómo va a cambiar todos los rieles en el sistema de metro de la ciudad de Nueva York para realizar esas mejoras? No lo eres, así que optimizas lo que tienes.

O. Jones
fuente
3

En general, cuanto más detalle le diga a la base de datos sobre lo que está almacenando, más puede intentar optimizar varias métricas de rendimiento relacionadas con esos datos, como cuánto espacio asignar en el disco o cuánta memoria asignar al recuperarlo. .

¿Por qué texto medio, texto largo y texto?

No estoy seguro de qué base de datos está utilizando, así que tendré que adivinar: supongo que dos de estos tipos de datos tienen límites superiores, uno de ellos no. El uso de tipos de datos para texto que tienen límites superiores le indica a la base de datos cuánto espacio de almacenamiento necesitará para cada registro. También es posible que algunas bases de datos tengan diferentes formas de almacenar texto grande (posiblemente ilimitado) frente a texto pequeño de longitud fija (esto puede variar según la base de datos, consulte su manual para ver el suyo).

¿Por qué decimal, float e int?

Los diferentes niveles de precisión requieren diferentes cantidades de almacenamiento, y no todo uso requiere los más altos grados de precisión. Por ejemplo, vea aquí: https://docs.oracle.com/cd/B28359_01/server.111/b28286/sql_elements001.htm#SQLRF50950

Oracle tiene una gran cantidad de diferentes tipos numéricos con diferentes requisitos de almacenamiento y diferentes capacidades en términos de nivel de precisión y tamaño de número que se puede representar.

FrustratedWithFormsDesigner
fuente
2

Hasta cierto punto, es histórico.

Érase una vez, los datos tabulares se almacenaban en archivos compuestos de registros de longitud fija, a su vez compuestos de campos predefinidos, de modo que un campo determinado siempre era del mismo tipo y en el mismo lugar en todos y cada uno de los registros. Esto hizo que el procesamiento sea eficiente y limitó la complejidad de la codificación.

Agregue algunos índices a dicho archivo y tendrá el comienzo de una base de datos relacional.

A medida que evolucionaron las bases de datos relacionales, comenzaron a introducir más tipos de datos y opciones de almacenamiento, incluidos campos binarios o de texto de longitud variable. Pero, esto introdujo registros de longitud variable y rompió la capacidad de ubicar registros consistentemente a través de cálculos o campos a través de un desplazamiento fijo. No importa, las máquinas son mucho más potentes hoy que en aquel entonces.

A veces es útil establecer un tamaño específico para un campo para ayudar a aplicar un poco de lógica comercial, digamos 10 dígitos para un número de teléfono de América del Norte. La mayor parte del tiempo es solo un poco de legado informático.

Zenilogix
fuente
1

Si una base de datos utiliza registros de tamaño fijo, cualquier registro en la base de datos continuará encajando, en la misma ubicación, incluso si se cambia su contenido. Por el contrario, si una base de datos intenta almacenar registros utilizando exactamente la cantidad de almacenamiento necesaria para sus campos, cambiar el nombre de Emma Smith a Emma Johnson puede hacer que su registro sea demasiado grande para caber en su ubicación actual. Si el registro se mueve a un lugar con suficiente espacio, cualquier índice que lleve un registro de dónde está necesitaría actualizarse para reflejar la nueva ubicación.

Hay una variedad de formas de reducir el costo asociado con dichas actualizaciones. Por ejemplo, si el sistema mantiene una lista de números de registros y ubicaciones de datos, esa lista será lo único que debería actualizarse si se mueve un registro. Desafortunadamente, tales enfoques aún tienen un costo significativo (por ejemplo, mantener un mapeo entre los números de registro y las ubicaciones requeriría que la recuperación de registros requeriría un paso adicional para recuperar los datos asociados con un número de registro dado). El uso de registros de tamaño fijo puede parecer ineficiente, pero hace las cosas mucho más simples.

Super gato
fuente
1

Por mucho de lo que haces como desarrollador web, no hay necesidad de entender lo que está sucediendo "bajo el capó". Hay momentos, sin embargo, cuando ayuda.

¿Cuál es el beneficio de decirle a la base de datos "Solo habrá 256 bytes de datos de texto sin formato en las entradas de esta columna". o "Esta columna puede tener entradas de texto de hasta 16.777.215 bytes"?

Como sospecha, la razón es hacer con eficiencia. Las abstracciones gotean . Una consulta como SELECT author FROM bookspuede ejecutarse bastante rápido cuando se conoce el tamaño de todos los campos de la tabla.

Como dice Joel:

¿Cómo se implementa una base de datos relacional SELECT author FROM books? En una base de datos relacional, cada fila de una tabla (por ejemplo, la tabla de libros) tiene exactamente la misma longitud en bytes, y cada campo siempre tiene un desplazamiento fijo desde el principio de la fila. Entonces, por ejemplo, si cada registro en la tabla de libros tiene una longitud de 100 bytes, y el campo de autor está en el desplazamiento 23, entonces hay autores almacenados en el byte 23, 123, 223, 323, etc. ¿Cuál es el código para moverse? el siguiente registro en el resultado de esta consulta? Básicamente, es esto:

pointer += 100;

Una instrucción de CPU. Faaaaaaaaaast.

La mayoría de las veces, estás trabajando lo suficientemente lejos de las bases fundamentales como para no tener que preocuparte por eso. Como desarrollador web basado en PHP, ¿le importa cuántas instrucciones de CPU usa su código? La mayoría de las veces, no, en realidad no. Pero a veces es útil saberlo por dos razones: puede explicar las decisiones tomadas por sus bibliotecas; y a veces debes preocuparte por la velocidad en tu propio código.

Trigonometría
fuente