Antecedentes
Soy estudiante de CS de primer año y trabajo a tiempo parcial para la pequeña empresa de mi padre. No tengo experiencia en el desarrollo de aplicaciones del mundo real. He escrito guiones en Python, algunos cursos en C, pero nada como esto.
Mi papá tiene un pequeño negocio de capacitación y actualmente todas las clases se programan, graban y siguen a través de una aplicación web externa. Hay una función de exportación / "informes" pero es muy genérica y necesitamos informes específicos. No tenemos acceso a la base de datos real para ejecutar las consultas. Me han pedido que configure un sistema de informes personalizado.
Mi idea es crear las exportaciones genéricas de CSV e importarlas (probablemente con Python) en una base de datos MySQL alojada en la oficina todas las noches, desde donde puedo ejecutar las consultas específicas que se necesitan. No tengo experiencia en bases de datos, pero entiendo los conceptos básicos. He leído un poco sobre la creación de bases de datos y los formularios normales.
Podemos comenzar a tener clientes internacionales pronto, así que quiero que la base de datos no explote si eso sucede. Actualmente también tenemos un par de grandes corporaciones como clientes, con diferentes divisiones (por ejemplo, empresa matriz de ACME, división de atención médica de ACME, división de cuidado corporal de ACME)
El esquema que se me ocurrió es el siguiente:
- Desde la perspectiva del cliente:
- Clientes es la mesa principal
- Los clientes están vinculados al departamento para el que trabajan
- Los departamentos se pueden dispersar por un país: RRHH en Londres, Marketing en Swansea, etc.
- Los departamentos están vinculados a la división de una empresa.
- Las divisiones están vinculadas a la empresa matriz.
- Desde la perspectiva de las clases:
- Sesiones es la mesa principal
- Un profesor está vinculado a cada sesión.
- Se proporciona un statusid a cada sesión. Por ejemplo, 0: completado, 1: cancelado
- Las sesiones se agrupan en "paquetes" de un tamaño arbitrario
- Cada paquete se asigna a un cliente
- Sesiones es la mesa principal
"Diseñé" (más bien garabateó) el esquema en una hoja de papel, tratando de mantenerlo normalizado a la 3ra forma. Luego lo conecté a MySQL Workbench y lo hizo todo bonito para mí:
( Haga clic aquí para ver el gráfico a tamaño completo )
(fuente: maian.org )
Consultas de ejemplo que estaré ejecutando
- Qué clientes con crédito aún quedan están inactivos (aquellos sin una clase programada en el futuro)
- ¿Cuál es la tasa de asistencia por cliente / departamento / división (medida por la identificación de estado en cada sesión)
- ¿Cuántas clases ha tenido un maestro en un mes?
- Marcar clientes que tienen baja tasa de asistencia
- Informes personalizados para departamentos de recursos humanos con tasas de asistencia de personas en su división
Pregunta (s)
- ¿Esto es de ingeniería excesiva o me dirijo en la dirección correcta?
- ¿La necesidad de unir varias tablas para la mayoría de las consultas dará como resultado un gran éxito en el rendimiento?
- He agregado una columna 'última sesión' a los clientes, ya que probablemente será una consulta común. ¿Es una buena idea o debería mantener la base de datos estrictamente normalizada?
Gracias por tu tiempo
fuente
divisions
tiene una columna llamadadivisionid
. ¿No te parece redundante? Solo nómbraloid
. también sus nombres de tabla, incluidos_has_
: eliminaría eso y solo lo nombraría, por ejemplocities_departments
. susDATETIME
columnas deben ser de tipo aTIMESTAMP
menos que sean valores ingresados por el usuario. Creo que es una buena idea tener las tablascities
ycountries
. puede tener problemas para limitar las tablas a una solastatus
. considere usar unINT
y realice comparaciones bit a bit en él, para que pueda tener más significado allíRespuestas:
Algunas respuestas más a sus preguntas:
1) Estás bastante en el blanco para alguien que se acerca a un problema como este por primera vez. Creo que los consejos de otros sobre esta cuestión hasta ahora prácticamente lo cubren. ¡Buen trabajo!
2 y 3) El éxito en el rendimiento que tendrá dependerá en gran medida de tener y optimizar los índices correctos para sus consultas / procedimientos particulares y, lo que es más importante, el volumen de registros. A menos que esté hablando de más de un millón de registros en sus tablas principales, parece estar en camino de tener un diseño lo suficientemente convencional como para que el rendimiento no sea un problema en un hardware razonable.
Dicho esto, y esto se relaciona con su pregunta 3, con el comienzo que tiene probablemente no debería preocuparse demasiado por el rendimiento o la hipersensibilidad a la ortodoxia de normalización aquí. Este es un servidor de informes que está creando, no un servidor de aplicaciones basado en transacciones, que tendría un perfil muy diferente con respecto a la importancia del rendimiento o la normalización. Una base de datos que respalda una aplicación de registro y programación en vivo debe tener en cuenta las consultas que tardan segundos en devolver los datos. Una función del servidor de informes no solo tiene más tolerancia para consultas complejas y largas, sino que las estrategias para mejorar el rendimiento son muy diferentes.
Por ejemplo, en un entorno de aplicación basado en transacciones, sus opciones de mejora del rendimiento pueden incluir la refactorización de los procedimientos almacenados y las estructuras de la tabla en el enésimo grado, o el desarrollo de una estrategia de almacenamiento en caché para pequeñas cantidades de datos comúnmente solicitados. En un entorno de informes, ciertamente puede hacer esto, pero puede tener un impacto aún mayor en el rendimiento al introducir un mecanismo de instantánea donde se ejecuta un proceso programado y almacena informes preconfigurados y sus usuarios acceden a los datos de la instantánea sin estrés en su nivel de base de datos en a por solicitud.
Todo esto es una queja larga para ilustrar que los principios de diseño y los trucos que empleas pueden diferir dado el papel de la base de datos que estás creando. Espero que sea útil.
fuente
Tienes la idea correcta. Sin embargo, puede limpiarlo y eliminar algunas de las tablas de mapeo (tiene *).
Lo que puede hacer es en la tabla Departamentos, agregar CityId y DivisionId.
Además de eso, creo que todo está bien ...
fuente
Los únicos cambios que haría son:
1- Cambie su VARCHAR a NVARCHAR, si se va a internacionalizar, puede que desee unicode.
2- Cambie sus ID de int a GUID (identificador único) si es posible (esta podría ser mi preferencia personal). Suponiendo que finalmente llegue al punto donde tiene múltiples entornos (dev / test / staging / prod), es posible que desee migrar datos de uno a otro. Tener ID de GUID hace esto significativamente más fácil.
3- Tres capas para su empresa -> División -> La estructura del departamento puede no ser suficiente. Ahora, esto podría ser una ingeniería excesiva, pero podría generalizar esa jerarquía de modo que pueda soportar n niveles de profundidad. Esto hará que algunas de sus consultas sean más complejas, por lo que puede que no valga la pena el intercambio. Además, podría ser que cualquier cliente que tenga más capas pueda "integrarse" fácilmente en este modelo.
4- También tiene un estado en la tabla de clientes que es un VARCHAR y no tiene ningún enlace a la tabla de estados. Esperaría un poco más de claridad sobre lo que representa el estado del cliente.
fuente
No. Parece que estás diseñando con un buen nivel de detalle.
Creo que los países y las empresas son realmente la misma entidad en su diseño, como lo son las ciudades y las divisiones. Me desharía de las tablas de Países y Ciudades (y Cities_Has_Departments) y, si es necesario, agrego un indicador booleano IsPublicSector a la tabla Companies (o una columna CompanyType si hay más opciones que simplemente Sector privado / Sector público).
Además, creo que hay un error en su uso de la tabla Departamentos. Parece que la tabla Departamentos sirve como referencia para los diversos tipos de departamentos que puede tener cada división de clientes. Si es así, debería llamarse DepartmentTypes. Pero sus clientes (que, supongo, son asistentes) no pertenecen a un tipo de departamento, pertenecen a una instancia de departamento real en una empresa. Tal como está ahora, sabrá que un cliente determinado pertenece a un departamento de recursos humanos en algún lugar, ¡pero no a cuál!
En otras palabras, los Clientes deben estar vinculados a la tabla que usted llama Divisions_Has_Departments (pero que yo llamaría simplemente Departamentos). Si esto es así, debe colapsar las Ciudades en Divisiones como se discutió anteriormente si desea utilizar la integridad referencial estándar en la base de datos.
fuente
Por cierto, vale la pena señalar que si ya está generando CSV y desea cargarlos en una base de datos mySQL, LOAD DATA LOCAL INFILE es su mejor amigo: http://dev.mysql.com/doc/refman/5.1/ es / load-data.html . También vale la pena analizar Mysqlimport, y es una herramienta de línea de comandos que básicamente es un buen contenedor para el archivo de datos de carga.
fuente
La mayoría de las cosas ya se han dicho, pero creo que puedo agregar una cosa: es bastante común que los desarrolladores más jóvenes se preocupen demasiado por el rendimiento por adelantado, y su pregunta sobre unir tablas parece ir en esa dirección. Este es un antipatrón de desarrollo de software llamado ' Optimización prematura '. Intenta desterrar ese reflejo de tu mente :)
Una cosa más: ¿Crees que realmente necesitas las tablas de 'ciudades' y 'países'? ¿No sería suficiente tener una columna 'ciudad' y 'país' en la tabla de departamentos para sus casos de uso? Por ejemplo, ¿su aplicación necesita enumerar departamentos por ciudad y ciudades por país?
fuente
Los siguientes comentarios se basan en el rol de especialista en Business Intelligence / Reporting y gerente de estrategia / planificación:
Estoy de acuerdo con la dirección de Larry arriba. En mi humilde opinión, no es demasiado sobre ingeniería, algunas cosas simplemente parecen un poco fuera de lugar. Para simplificar, etiquetaría al cliente directamente a una ID de empresa, Descripción de departamento, Descripción de división, ID de tipo de departamento, ID de tipo de división. Utilice el ID de tipo de departamento y el ID de tipo de división como referencias a las tablas de búsqueda y a los campos internos de informes / análisis para obtener coherencia a largo plazo.
La tabla de paquetes contiene la columna "Crédito", ¿no debería estar realmente vinculado a la tabla base del Cliente, por lo que si tienen muchos paquetes, puede ver cuánto crédito le queda para las clases futuras? La aplicación puede encargarse del cálculo y almacenarlo centralmente en la tabla Cliente.
La información de la compañía podría usar muchos más campos, incluida la dirección / teléfono / etc obvio. información. También estaría preparado para agregar columnas DUN "DUN" (Sitio / Sucursal / Ultimate) a largo plazo, Dun and Bradstreet (D&B) tiene un gran catálogo de compañías y más adelante encontrará que su información es muy útil para informes / análisis. Esto se encargará del problema de división múltiple que mencione y le permitirá acumular su jerarquía para sub / division / sucursales / etc. de grandes cuerpos.
No mencionas con cuántos registros trabajarás, lo que podría implicar prepararte para una gran iniciativa de desarrollo que podría haberse hecho más rápido y con muchos menos dolores de cabeza con el software de "informes" preempaquetado. Si no está lidiando con una gran base de datos (<65000) filas, asegúrese de que MS-Access, OpenOffice (Base) o las soluciones de desarrollo de informes / aplicaciones relacionadas no podrían hacer el truco. Yo uso bastante el software APEX gratuito de Oracle, viene con su base de datos gratuita Oracle XE, solo descárguelo de su sitio.
FYI - Información de informes: para grandes bases de datos, normalmente tiene dos instancias de base de datos a) base de datos de transacciones para registrar cada registro detallado. b) base de datos de informes (data mart / data warehouse) alojada en una máquina separada. Para obtener más información, busque en Google tanto Star Schema como Snowflake Schema.
Saludos.
fuente
Quiero abordar solo la preocupación de que unirse a varias tablas provocará un éxito en el rendimiento. No tengas miedo de normalizar porque tendrás que hacer uniones. Las uniones son normales y esperadas en bases de datos relacionales y están diseñadas para manejarlas bien. Deberá establecer relaciones PK / FK (para la integridad de los datos, es importante tenerlo en cuenta en el diseño), pero en muchas bases de datos los FK no se indexan automáticamente. Como se utilizarán en las combinaciones, definitivamente querrá comenzar indexando el FKS. Las PK generalmente obtienen un índice de creación, ya que tienen que ser únicas. Es cierto que el diseño de datawarehouse reduce el número de uniones, pero generalmente no se llega al punto de almacenamiento de datos hasta que se necesita acceder a millones de registros en un informe. Incluso entonces, casi todos los almacenes de datos comienzan con una base de datos transaccional para recopilar los datos en tiempo real y luego los datos se mueven al almacén en un horario (nocturno o mensual o lo que sea necesario para el negocio). Por lo tanto, este es un buen comienzo, incluso si necesita diseñar un almacén de datos más adelante para mejorar el rendimiento del informe.
Debo decir que su diseño es impresionante para un estudiante de CS de primer año.
fuente
No está sobre diseñado, así es como abordaría el problema. Unirse está bien, no habrá mucho impacto en el rendimiento (¡es completamente necesario a menos que desnormalice la base de datos, lo que no se recomienda!). Para los estados, vea si puede usar un tipo de datos enum para optimizar esa tabla.
fuente
He trabajado en el ámbito de la formación / escuela y pensé en señalar que generalmente hay una relación M: 1 entre lo que llaman "sesiones" (instancias de un curso determinado) y el curso en sí. En otras palabras, su catálogo ofrece el curso ("Español 101" o lo que sea), pero puede tener dos instancias diferentes durante un solo semestre (Tu-Th enseñado por Smith, Wed-Fri enseñado por Jones).
Aparte de eso, parece un buen comienzo. Apuesto a que encontrará que el dominio del cliente (gráficos que conducen a "clientes") es más complejo de lo que ha modelado, pero no se exceda con eso hasta que tenga algunos datos reales que lo guíen.
fuente
Algunas cosas me vinieron a la mente:
Las mesas parecían orientadas a la presentación de informes, pero en realidad no dirigían el negocio. Creo que cuando un cliente se registra, esencialmente se hace un pedido para el cliente que asiste a una lista de sesiones, y ese pedido podría ser para varios empleados en una empresa. Parecería que una tabla de "pedidos" realmente estaría en el centro de su sistema e impulsaría la captura de datos y los informes eventuales. (Compare los documentos en papel que ha estado utilizando para administrar el negocio con el diseño de su base de datos para ver si hay una coincidencia lógica).
Las empresas a menudo no tienen divisiones. Los empleados a veces cambian divisiones / departamentos, tal vez incluso a mitad de sesión. Las empresas a veces agregan / eliminan / renombran divisiones / departamentos. Asegúrese de que el posible cambio en tiempo real del contenido de sus tablas no dificulte la creación de informes / agrupaciones posteriores. Con tantos datos de contacto divididos en tantas tablas, es posible que deba aplicar una validación de entrada de datos muy estricta para mantener sus informes significativos e inclusivos. Por ejemplo, cuando se agrega un nuevo cliente, asegurarse de que su empresa / división / departamento / ciudad coincida con los mismos valores que sus compañeros de trabajo.
El concepto de "paquetes" no está claro en absoluto.
Como indica que es una pequeña empresa, sería sorprendente que el rendimiento fuera un problema, teniendo en cuenta la velocidad y la capacidad de las máquinas actuales.
fuente