Durante nuestra última reunión semanal, una persona que no tiene experiencia en administración de bases de datos planteó esta pregunta:
"¿Habría un escenario que justifique el almacenamiento de datos en línea (cadena) en lugar de varias líneas?"
Supongamos una tabla llamada countryStates
donde queremos almacenar los estados de un país; Usaré EE. UU. Para este ejemplo y no enumeraré todos los Estados en aras de la pereza.
Allí tendríamos dos columnas; uno llamó Country
y el otro llamó States
. Como se discutió aquí , y propuesto por la respuesta de @ srutzky , PK
será el código definido por ISO 3166-1 alpha-3 .
Nuestra mesa se vería así:
+---------+-----------------------+-------------------------------------------------------+
| Country | States | StateName |
+---------+-----------------------+-------------------------------------------------------+
| USA | AL, CA, FL,OH, NY, WY | Alabama, California, Florida, Ohio, New York, Wyoming |
+---------+-----------------------+-------------------------------------------------------+
Al hacerle esta misma pregunta a un desarrollador amigo, dijo que desde el punto de vista del tamaño del tráfico de datos, esto podría ser útil, pero no si necesitamos manipular estos datos. En este caso, tendría que haber una inteligencia sobre el código de la aplicación que podría transformar esta cadena en una lista (digamos que el software que tiene acceso a esta tabla necesita crear un cuadro combinado).
Llegamos a la conclusión de que este modelo no es muy útil, pero sospeché que podría haber una manera de hacerlo útil.
Lo que me gustaría preguntar es si alguno de ustedes ya vio, escuchó o hizo algo como esto de una manera que realmente funciona .
fuente
a;b;c
, utilice la parte delantera para analizar la cadena a continuación, obtenera
,b
,c
y llevar a cabo la ejecución de hacer algo con ellos, tal vez ?. Siente que podría satisfacer algún tipo de necesidad específica de esa manera ... Pensándolo bien, no. Siempre puede almacenar ID, unirse a sus tablas y crear una cadena concatenada que pueda enviar contenido a la FE ...Respuestas:
Para empezar, el título actual de la pregunta que se refiere a "almacenar datos como una cadena en lugar de columnas" es un poco confuso. Cuando se habla de almacenar datos como cadenas en lugar de otra cosa, eso generalmente se refiere a serializar todo en un formato de cadena en lugar de un tipo de datos adecuado / fuerte (por ejemplo,
INT
oDATETIME
). Pero si se pregunta sobre el almacenamiento de datos como valores múltiples en un solo campo en lugar de filas separadas, eso es un poco diferente. Y para ser justos, aunque la concatenación de valores se hace más fácilmente con cadenas, también se puede hacer conINT
yBINARY
tipos, ya sea enmascarando bits o reservando de manera similar ciertas posiciones para tener diferentes significados. Dado que la segunda interpretación es sobre lo que realmente se está preguntando, basado en el texto de la Pregunta, abordemos eso.En una palabra: No. Si está almacenando puntos de datos reales, solo traerá dolor (en términos de código y rendimiento) ya que es una complicación innecesaria. Si es un valor que solo se almacenará como una sola unidad, se actualizará como una sola unidad y nunca se desmontará dentro de la base de datos, entonces eso podría estar bien, ya que es más o menos análogo al almacenamiento de una imagen o PDF. De lo contrario, cualquier intento de analizar los datos invalidará el uso de cualquier índice (por ejemplo
LIKE '%something%'
, usandoCHARINDEX
, oPATINDEX
, oSUBSTRING
, etc.).Si necesita almacenar valores separados en un solo campo de una sola fila, entonces hay medios más apropiados para hacerlo: XML o JSON. Estos son formatos analizables ( XML / JSON ) y XML puede incluso indexarse . Pero, idealmente, estos datos se almacenarían en campos correctamente tipados para que puedan ser realmente útiles.
Y no olvide que el propósito de un RDBMS es almacenar datos de modo que puedan recuperarse y manipularse de la manera más eficiente posible, dentro de las restricciones impuestas por cumplir con ACID . Recuperar valores concatenados es suficientemente malo debido a la necesidad de analizar primero los valores, y eso no es indexable. Pero manipular a menudo significa reemplazar todo el blob solo para actualizar una parte (suponiendo que no exista un patrón para usar con una
REPLACE
función). El tipo de datos XML al menos permite XML DML para actualizaciones simplistas, aunque todavía no son tan rápidas como una simple actualización de datos modelados adecuadamente.Además, dado un escenario como el que se muestra en la pregunta anterior, al concatenar todos los códigos de estado juntos, no podrá utilizar la clave externa (en cualquier dirección) esos valores.
¿Y qué pasa si los requisitos comerciales cambian con el tiempo y necesita rastrear propiedades adicionales de estos artículos? En términos de "estados", ¿qué pasa con las capitales, o la población, o un orden de clasificación, o cualquier otra cosa? Almacenado correctamente como filas, puede agregar más columnas para propiedades adicionales. Claro, puede tener múltiples niveles de datos analizables, como, por
|StateCode,Capital,Population |StateCode,Capital,Populate|...
suerte, cualquiera puede ver que el problema crece exponencialmente fuera de control. Por supuesto, este problema en particular se trata fácilmente con los formatos XML y JSON, y ese es su valor como se mencionó anteriormente. Pero aún necesitaría una muy buena razón para usar cualquiera de ellos como un medio inicial de modelado, ya que ninguno será tan eficiente como usar campos discretos en filas separadas.fuente
De hecho, he usado algo así para un propósito muy limitado. Creamos una tabla de encabezados para los archivos de salida. Se construyeron específicamente y en su mayoría eran solo los encabezados de las columnas, pero no del todo. Entonces los datos se veían algo así
Esencialmente parecía que era una lista delimitada. Y en cierto sentido lo fue. Pero para nuestros propósitos era una sola cadena larga.
Ese es el truco aquí. Si nunca planea analizar la lista, entonces vale la pena guardarla. Sin embargo, si necesitará o incluso necesitará analizar la lista, entonces vale la pena el espacio y el tiempo extra para dividirla y guardarla en filas separadas.
fuente
Lo he usado una vez con una mesa bastante pequeña, por ejemplo:
Y luego almacenar valores
CRM,SMS,SELF-CARE
envalid_channel
.Toda la tabla tiene algo así como 10 registros.
valid_channel
contiene valores que realmente deberían estar en una tabla de enlace que represente la relación de muchos a muchos. Mesat1
no se utilizará de forma intensiva, por lo que decidimos seguir este camino. Sin embargo, algunas políticas estuvieron involucradas en esta decisión (ver más abajo).Pero en general lo evito, no es 3NF.
El lugar donde trabajo actualmente tiene docenas de tales columnas por todo el lugar. Su justificación es que facilita sus consultas: en lugar de unir tres tablas usando la tabla de enlace, pueden ir directamente a la tabla de definición usando
LIKE
. P.ejHorrible + en Oracle deshabilita el uso del índice debido al inicio
'%,'
.fuente
LIKE
o una simple unión?LIKE
sería más lento, especialmente si los datos se modelan correctamente para usar unTINYINT
campo PK enchannel_def
. Entonces solo necesita comparar un solo byte entre las dos tablas. Aquí tiene que analizar la cadena, carácter por carácter (al menos hasta que se cumpla la condición), y está haciendo una búsqueda que no distingue entre mayúsculas y minúsculas (en función de que la tabla dada def no muestra una_BIN2
clasificación utilizada). Esto también invalida los índices en SQL Server. Abordé esto en mi respuesta diciendo que el análisis no puede usar índices. Acabo de actualizar mi respuesta para hacerlo más claro.LIKE
cláusula y produce resultados extraños, aún puede causar otros problemas o al menos hacer la depuración más difícil / más larga). También hace que la actualización delvalid_channels
campo sea más complicada. Esto no quiere decir que esto no funcione, simplemente no hay una buena razón para hacerlo.Esto se hizo aquí en SE. Como Marc Gravell escribe :
Este "nuevo formato" fue el siguiente paso del "formato anterior", que era un poco diferente y fue elegido para utilizar la función de búsqueda de texto completo de SQL Server, por lo que algunos de los beneficios no son relevantes si lo hace desde cero.
Presumiblemente no normalizaron completamente la cosa tanto por la cantidad de trabajo como por razones de rendimiento.
fuente
Bueno, un posible beneficio principal de usar cadenas y otros tipos de datos es enviarlos desde SQL Server a C #, C, C ++ (etc.) usando el SQLCLR cuando sea necesario un rendimiento absoluto. Incluso podría crear una vista o procedimiento almacenado para representar datos relacionales de manera no relacional, como lo ha hecho con su ejemplo anterior para este mismo propósito.
Ver este ejemplo:
http://aboutsqlserver.com/2013/07/22/clr-vs-t-sql-performance-considerations/
según Wikipedia: SQL CLR o SQLCLR (SQL Common Language Runtime) es una tecnología para alojar el motor de tiempo de ejecución de lenguaje común de Microsoft .NET dentro de SQL Server. El SQLCLR permite que el código administrado sea alojado y ejecutado en el entorno de Microsoft SQL Server.
fuente
En mi opinión, la respuesta sería no. No he usado este enfoque y lo evitaría; no puedo pensar en una razón por la que seguiría esa ruta. Te estás inclinando hacia el mundo de JSON / NoSQL con una matriz.
Tuvimos opciones de diseño similares en un rol anterior por el cual el equipo de arquitectos quería tener un campo "Datos" que se delimitara y luego se convirtiera en binario. No fuimos por esa ruta al final por algunas razones.
Si tuviera que unirse a este tipo de datos, sería una experiencia fea. Actualizar elementos individuales de la cadena también sería desagradable.
fuente