Heredé una aplicación que asocia muchos tipos diferentes de actividades con un sitio. Hay aproximadamente 100 tipos de actividades diferentes, y cada uno tiene un conjunto diferente de 3-10 campos. Sin embargo, todas las actividades tienen al menos un campo de fecha (podría ser cualquier combinación de fecha, fecha de inicio, fecha de finalización, fecha de inicio programada, etc.) y un campo de persona responsable. Todos los demás campos varían ampliamente y un campo de fecha de inicio no necesariamente se llamará "Fecha de inicio".
Hacer una tabla de subtipos para cada tipo de actividad daría como resultado un esquema con 100 tablas de subtipos diferentes, lo que sería demasiado difícil de manejar. La solución actual a este problema es almacenar los valores de actividad como pares clave-valor. Este es un esquema muy simplificado del sistema actual para transmitir el punto.
Cada actividad tiene múltiples campos de actividad; cada sitio tiene múltiples actividades, y la tabla SiteActivityData almacena los KVP para cada SiteActivity.
Esto hace que la aplicación (basada en la web) sea muy fácil de codificar porque todo lo que realmente necesita hacer es recorrer los registros en SiteActivityData para una actividad determinada y agregar una etiqueta y control de entrada para cada fila a un formulario. Pero hay muchos problemas:
- La integridad es mala; es posible poner un campo en SiteActivityData que no pertenece al tipo de actividad, y DataValue es un campo varchar, por lo que los números y las fechas se deben emitir constantemente.
- Los informes y las consultas ad-hoc de estos datos son difíciles, propensos a errores y lentos. Por ejemplo, obtener una lista de todas las actividades de cierto tipo que tienen una Fecha de finalización dentro de un rango específico requiere pivotes y conversión de varchars a las fechas. Los redactores del informe ODIAN este esquema, y no los culpo.
Entonces, lo que estoy buscando es una forma de almacenar una gran cantidad de actividades que casi no tienen campos en común de una manera que facilite la presentación de informes. Lo que se me ocurrió hasta ahora es usar XML para almacenar los datos de la actividad en un formato pseudo-noSQL:
La tabla de Actividad contendría el XSD para cada actividad, eliminando la necesidad de la tabla de ActivityField. SiteActivity contendría el XML de valor clave, por lo que cada actividad para un sitio ahora estaría en una sola fila.
Una actividad se vería así (pero no la he desarrollado completamente):
<SomeActivityType>
<SomeDateField type="StartDate">2000-01-01</SomeDateField>
<AnotherDateField type="EndDate">2011-01-01</AnotherDateField>
<EmployeeId type="ResponsiblePerson">1234</EmployeeId>
<SomeTextField>blah blah</SomeTextField>
...
Ventajas:
- El XSD validaría el XML, detectando errores como poner una cadena en un campo numérico a nivel de la base de datos, algo que era imposible con el antiguo esquema que almacenaba todo en varchar.
- El conjunto de registros de KVP que se utiliza para crear los formularios web podría reproducirse fácilmente utilizando
select ... from ActivityXML.nodes('/SomeActivityType/*') as T(r)
- Se podría usar una subconsulta xpath del XML para producir un conjunto de resultados que tenga columnas para la fecha de inicio, fecha de finalización, etc. sin usar un pivote, algo así como
select ActivityXML.value('.[@type=StartDate]', 'datetime') as StartDate, ActivityXML.value('.[@type=EndDate]', 'datetime') as EndDate from SiteActivity where...
¿Parece esto una buena idea? No puedo pensar en otras formas de almacenar una cantidad tan grande de diferentes conjuntos de propiedades. Otro pensamiento que tuve fue mantener el esquema existente y traducirlo en algo más fácil de consultar en un almacén de datos, pero nunca antes había diseñado un esquema en estrella y no tenía idea de por dónde empezar.
Pregunta adicional: si defino que una etiqueta tiene un tipo de datos de fecha en el XSD xs:date
, ¿SQL Server la indexará como un valor de fecha? Me preocupa si hago una consulta por fecha, tendrá que convertir la cadena de fecha a un valor de fecha y eliminar cualquier posibilidad de usar un índice.
fuente
Respuestas:
No hay suficiente representante para comentar primero, ¡así que aquí vamos!
Si el propósito principal es informar y tiene un DW (incluso si no es un esquema en estrella), le recomiendo que intente incluirlo en un esquema en estrella. Los beneficios son consultas rápidas y simples. La desventaja es ETL, pero ya está considerando mover los datos a un nuevo diseño y ETL a un esquema en estrella es más fácil de construir y mantener que una solución de envoltorio XML (y SSIS está incluido en su licencia de SQL Server). Además, comienza el proceso de un diseño reconocido de informes / análisis.
Entonces, cómo hacer eso ... Parece que tienes lo que se conoce como un hecho sin hechos . Esta es una intersección de atributos que definen un evento sin medida asociada (como un precio de venta). ¿Tiene fechas disponibles para algunas o todas sus actividades? Probablemente debería tener una intersección de una Actividad, Sitio y Fecha (s).
DimActivity
- Supongo que hay un patrón, algo que puede permitirte dividirlos en columnas al menos relativamente compartidas. Si es así, ¿puedes tener tres? ¿cinco? dimensiones para clases de actividades. En el peor de los casos, tiene un par de columnas consistentes, como el nombre de la actividad, puede filtrar y deja encabezados generales como "Atributo1", etc. para los detalles aleatorios restantes.No necesita todo en la dimensión (es probable que no haya fechas en la dimensión Actividad), todas deben estar en el hecho, como referencias clave sustitutas a la dimensión Fecha. Como ejemplo, una Fecha que permanecería en una dimensión de persona sería una fecha de nacimiento porque es un atributo de una persona. Una fecha de visita al hospital residiría en un hecho, ya que es un evento de punto en el tiempo asociado con una persona, entre otras cosas, pero no es un atributo de la persona que visita el hospital. Más discusión fecha en el hecho.
DimSite
- parece sencillo, así que describiremos Surrogate Keys aquí. Esencialmente esto es solo una identificación incremental y única. La columna de identidad entera es común. Esto permite la separación de DW y los sistemas de origen y garantiza uniones óptimas en el almacén de datos. Su Clave natural o Clave comercial generalmente se mantiene, pero para mantenimiento / diseño no se analiza y se une. Esquema de ejemplo:DimDate
- atributos de fecha. Haga una "clave inteligente" en lugar de una Identidad. Esto significa que puede escribir un número entero significativo que se relacione con una fecha para consultas como WHERE DateSK = 20150708. Hay muchos scripts gratuitos para cargar DimDate y la mayoría tiene esta clave inteligente incluida. ( una opción )DimEmployee
- su XML incluyó esto, si es un cambio más general a DimPerson, y complete con atributos de persona relevantes a medida que estén disponibles y pertinentes para la presentación de informes.Y tu hecho es:
Puede cambiar el nombre de estos en el hecho, y puede tener varias claves de fecha por evento. Los hechos suelen ser muy grandes, por lo que evitar las actualizaciones suele ser bueno ... si tiene varias actualizaciones de fecha para un solo evento, puede probar un diseño Eliminar / Insertar agregando un SK al hecho que permite la selección de filas de "actualización" en ser eliminado y luego insertar los últimos datos.
Ampliar las fechas de hechos a lo que usted necesita:
StartDateSK, EndDateSK, ScheduledStartDateSK
.Todas las dimensiones deben tener una fila Desconocida típicamente con un código SK -1 codificado. Cuando carga el hecho, y una actividad no tiene ninguna de las Fechas incluidas, simplemente debe cargar un -1.
El hecho es una colección de referencias enteras a sus atributos almacenados en las dimensiones, únalas y obtendrá todos sus detalles, en un patrón de unión muy limpio, y el hecho, debido a sus tipos de datos, es excepcionalmente pequeño y rápido. Como está en SQL Server, agregue un índice de almacén de columnas para aumentar aún más el rendimiento. Puede soltarlo y reconstruirlo durante ETL. Una vez que llegue a SQL 2014+, puede escribir en índices de almacén de columnas.
Si sigue esta ruta, investigue el modelado dimensional. Recomiendo la metodología Kimball . También hay muchas guías gratuitas, pero si esto no es una solución única, es probable que la inversión valga la pena.
fuente