Diseño de base de datos: nueva tabla versus nuevas columnas


38

(Se sugirió que se volviera a publicar aquí desde StackOverflow)

Actualmente tengo una tabla ... y necesito comenzar a agregarle nuevas columnas de datos. No todos los registros (incluso avanzar con nuevos datos después de agregar las nuevas columnas de datos) tendrán datos. Entonces, me pregunto si esto es más adecuado para una nueva tabla, ya que es realmente una extensión de algunas de las filas de datos y no es aplicable a todas las filas.

En otras palabras, dado que habrá muchas columnas no utilizadas para esos nuevos elementos de datos, ¿parece que esto sería más adecuado para una nueva tabla?

La primera tabla es un registro de visitas a la página (actualmente 2 millones de registros)

- carné de identidad
- Dirección IP
- tiempos vistos
- created_at marca de tiempo
- fecha

para cada dirección IP, se realiza un registro por día, y se agregan vistas de página consecutivas a las visitas por día

los campos adicionales serían para el seguimiento del punto de origen (es decir, fuente / medio / campaña de google analytics)

No todas las visitas tendrán esa información. Supongo que aproximadamente el 10% de las filas tendrán los datos (ya que generalmente solo se atribuyen en la primera visita)

El uso principal de los datos sería atribuir el origen de las personas. Esto puede terminar siendo utilizado con más frecuencia (que luego parece prestarse a la tabla única)

Apreciar los comentarios: puede agregar más si es necesario

Respuestas:


29

Con lo que estás luchando es con la partición vertical. Esta es una técnica de diseño de base de datos física para mejorar el rendimiento. Al igual que con cualquier técnica de diseño de base de datos física, su aplicabilidad depende de las consultas específicas que está intentando optimizar y si esta técnica las optimizará. Desde un punto de vista lógico, si estos nuevos campos dependen de la clave candidata para su entidad, entonces son hechos al respecto que pertenecen a ella. Primero, debe asegurarse de comprender completamente la dependencia funcional de estos nuevos campos en sus claves candidatas para verificar que realmente son hechos sobre las visitas diarias a la página. Si lo son, decidir dividirlos en otra tabla es una optimización del rendimiento que solo debe hacerse si logra sus objetivos de rendimiento.

En general, la partición vertical es útil si consulta estas nuevas columnas con poca frecuencia y claramente de las otras columnas en la tabla original. Al colocar esas columnas en otra tabla que comparte la misma PK que su tabla existente, puede consultarla directamente cuando desee esas nuevas columnas y obtener un rendimiento mucho mayor, ya que tendrá muchas más filas por página en el disco para esta nueva tabla ya que todas las columnas de la tabla original no se colocarán en esas filas. Sin embargo, si siempre consulta estas columnas junto con las columnas de la tabla original, una partición vertical no tendría mucho sentido, ya que siempre tendrá que unir externamente para obtenerlas. Las páginas de las tablas en el disco entran en el grupo de búferes de un DBMS de forma independiente, nunca se unen previamente, y para que la unión tenga que suceder con cada ejecución de consulta, incluso si los datos están anclados en el grupo de búferes. En este escenario, convertirlas en columnas NULABLES en la tabla original permitiría al motor de almacenamiento DBMS almacenarlas de manera eficiente cuando NULL y eliminar la necesidad de unirse en la recuperación.

Me parece que su caso de uso es el último y agregarlos como NULLABLE a su tabla original es el camino a seguir. Pero al igual que con todo lo demás en el diseño de bases de datos, depende, y para tomar la decisión correcta, necesita conocer su carga de trabajo esperada y de qué depende tomar una buena decisión. Un buen ejemplo de un caso de uso adecuado para la partición vertical sería un panel de búsqueda de personas, en el que su aplicación tiene información muy rara sobre una persona en la que alguien podría querer buscar, pero rara vez lo hace. Si coloca esa información en una tabla diferente, tiene algunas buenas opciones para el rendimiento. Puede escribir la búsqueda para que tenga 2 consultas, una que use la información principal, siempre poblada para buscar (como apellido o ssn) solamente, y uno que se une externamente a la información poblada con poca frecuencia solo cuando se solicita para la búsqueda. O podría aprovechar el optimizador DBMS si es lo suficientemente inteligente como para reconocer para un conjunto dado de variables de host que la combinación externa no es necesaria y no la realizará, y por lo tanto solo tiene que crear 1 consulta.

¿Qué plataforma DBMS estás usando? La forma en que la plataforma maneja el almacenamiento de columnas NULL, optimiza su consulta, así como la disponibilidad de soporte de columnas dispersas (SQL Server tiene esto) afectará la decisión. En última instancia, recomendaría probar ambos diseños en un entorno de prueba con datos de tamaño de producción y carga de trabajo y ver cuál logra mejor sus objetivos de rendimiento.


No me queda claro qué quiere decir con "Sin embargo, si siempre consulta estas columnas junto con las columnas de la tabla original, entonces una partición vertical no tendría mucho sentido, ya que siempre tendrá que unirlas para obtenerlas". , solo necesitaría hacer una combinación externa cuando desee que las columnas primarias estén o no disponibles las columnas secundarias, de lo contrario usaría una UNIÓN INTERNA, y hacerlo sería beneficioso en la mayoría de los casos (reduciendo el número de filas observadas )
jmoreno

Gracias por toda la ayuda aquí. De hecho, agregué los campos, pero después de pensarlo bien, vi que debería tener un par de otras tablas para identificar mejor todo. Lo que finalmente llegó fue el visitante Visitor_visits (que tiene un Visitor_id y contiene la fuente) page_views (que tiene vistor_id y Visitor_visit_id) ya que quiero saber exactamente qué page_view se atribuye a la visita, agregué ese enlace. Luché con eso por un momento, pero creo que fue la decisión correcta
Cgmckeever

10

Personalmente me inclino por agregar columnas a la tabla existente. La nueva mesa realmente no te compra nada:

  • realmente no ahorra mucho espacio porque los valores NULL en la tabla original no ocupan espacio, y la nueva tabla necesita algún tipo de identificador que compensa cualquier ahorro de todos modos
  • sus consultas se vuelven más complejas ... se where newcolumn is not nullconvierte en unleft outer join

En la tabla única, solo significa que el tamaño de su fila puede variar de una página a otra, pero esto no debería afectar a muchas de sus páginas existentes, especialmente si su índice agrupado está en una columna que aumenta monotónicamente (identidad o fecha / hora).


Dado que la tabla actualmente no es amplia (según su descripción) y estos datos no la harán demasiado amplia, estaría de acuerdo.
HLGEM

4

Dada la información que ha proporcionado, y con el objetivo de la normalización general, probablemente simplemente agregaría columnas anulables, pero no ha brindado suficiente información sobre cómo se usarán los datos para saber cuál es la mejor manera de modelar los datos es.

Dependiendo de cómo está utilizando realmente estos datos, es posible que desee considerar un modelo de datos diferente. Si está colocando estos datos para informes, es posible que desee buscar un modelo dimensional, que puede ser más eficiente para ciertos tipos de informes; por ejemplo, el análisis de la hora del día funciona bien con una dimensión de fecha y hora dividida.

Para responder preguntas analíticas, como "cuál es la hora del día más popular para las visitas de campañas como X" o "qué día de una campaña vemos la mayor cantidad de visitas por hora", una sola columna de tiempo de datos no funcionará muy bien (pero esto incluso se puede dividir en un modelo relacional), y hay muchos casos en los que podría tratar la dirección IP como una dimensión (quizás con algún tipo de datos de geografía en un copo de nieve).

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.