¿Cuál de estos diseños de mesa es mejor para el rendimiento?


16

Se me ha pedido que cree algo que rastree el costo diario para cobrar en las cuentas, y estoy tratando de descubrir un esquema de tabla de base de datos que lo respalde.

Esto es lo que se

  • La compañía tiene más de 2.5 millones de cuentas.
  • De estos, actualmente trabajan un promedio de 200,000 por mes (que cambia con los niveles de personal, que actualmente son bajos)
  • Tienen 13 tipos de costos diferentes que les gustaría rastrear, y han advertido que podrían agregar más en el futuro
  • Quieren que los costos sean rastreados diariamente
  • Los costos no se dividen en todo el inventario. Se dividen en el número de cuentas que se trabajan por mes (200,000), o los usuarios pueden ingresar identificadores de cuenta para aplicar un costo a un grupo de cuentas, o simplemente pueden especificar a qué cuentas aplicar el costo.

Mi primer pensamiento fue una base de datos normalizada:

ID de la cuenta
Fecha
CostTypeId
Cantidad

Mi problema con esto es hacer los cálculos. Esta mesa se va a poner enorme rápidamente. Suponiendo que los 13 tipos de costos se apliquen a todas las cuentas trabajadas para el mes actual, es decir 200k * 13 * N days in month, alrededor de 75-80 millones de registros por mes, o cerca de mil millones de registros por año.

Mi segundo pensamiento fue desnormalizarlo un poco

ID de la cuenta
Fecha
Coste total
CostType1
CostType2
CostType3
CostType4
CostType5
CostType6
CostType7
CostType8
CostType9
CostType10
CostType11
CostType12
CostType13

Este método está más desnormalizado y puede crear hasta 6 millones de registros por mes ( 200k * N days in month), o aproximadamente 72 millones por año. Es mucho menos que el primer método, sin embargo, si la compañía decide un nuevo Tipo de costo en el futuro, será necesario agregar otra columna de base de datos.

De los dos métodos, ¿cuál prefiere? ¿Por qué? ¿Hay alguna otra alternativa en la que puedas pensar que manejaría esto mejor?

Estoy más interesado en informar sobre el rendimiento, tanto informes resumidos como detallados. El trabajo que repartirá los costos sobre las cuentas se ejecutará todas las noches cuando no haya nadie cerca. Una preocupación secundaria es el tamaño de la base de datos. La base de datos existente ya tiene casi 300 GB, y creo que el espacio en el disco es de alrededor de 500 GB.

La base de datos es SQL Server 2005


Entonces consiga otro disco. Los discos son baratos. Puede tener 2 TB por el costo de una reunión para discutir sobre esto.

Respuestas:


9

Mil millones de registros al año no es mucho.

Con la partición (por tipo de costo, tal vez) y el archivo es manejable.

El número de elementos de datos para almacenar sigue siendo 200k * 13 * N.Como columnas, obtendrá menos filas por página y ocupará más espacio que las filas. Puede ganar si "CostType1" no es un tipo de datos de longitud fija, pero es marginal.

"BESO" como dicen


3
@ Rachel Definitivamente recomendaría implementar un esquema de partición con un conjunto de datos tan grande. Si se centran en trabajar e informar mes a mes, entonces es mejor elegir una clave de partición que pueda coincidir con esa mentalidad. Además, si configura correctamente su partición, puede cambiar fácilmente los datos dentro y fuera de la tabla a tablas de preparación, lo que hace que las grandes cargas y eliminaciones de datos para conjuntos de datos continuos sean instantáneas y demoren segundos en lugar de horas.
David

6

Si bien su diseño ciertamente puede marcar una diferencia de día o de noche, en este caso me enfocaría más en los índices, incluida la cobertura de los índices según sea necesario. También miraría algunas de las herramientas que SQL Server le brinda para manejar tablas muy grandes, como el particionamiento de tablas.

Piénselo de esta manera, a pesar de que hay 80 mil millones de registros en la tabla, con una indexación adecuada, los que realmente le interesan en cualquier punto dado se agruparán físicamente en el disco. Debido a la forma en que se organizan los datos en el servidor SQL, los datos divididos por límites de índice también pueden estar en otra tabla porque no tiene que leer toda la tabla para obtener lo que necesita.

Si también elige particionar la tabla, puede mejorar el tiempo de acceso y el tiempo de inserción.


4

Me normalizaría. Realizamos la contabilidad de costos para la rentabilidad de la cuenta del cliente en un banco y generamos más de 250 millones de filas de costos individuales utilizando cientos de factores que se asignaron por centro de costos o por libro mayor o por varias otras técnicas en millones de cuentas cada mes.

Por ejemplo, el costo total del servicio de los cajeros automáticos se dividió entre las cuentas que habían usado cajeros automáticos en función de la cantidad relativa de uso. Entonces, si $ 1 millón se gastó en el mantenimiento de cajeros automáticos y solo 5 clientes lo usaron una vez cada uno y un cliente lo usó 5 veces, entonces ese cliente le costó al banco $ .5m y los otros clientes le costaron al banco $ .1m cada uno. Otros controladores pueden ser mucho más complejos.

En última instancia, probablemente encontrará que es escaso (ciertas cuentas no obtienen costos de ciertas fuentes / controladores) y algunas cuentas no obtienen nada. En un modelo normalizado, esas filas no existen. En el modelo desnormalizado, la fila existe, con algunas columnas vacías. Además, en un modelo normalizado disperso, debería ver una mejora en el rendimiento, ya que la existencia de una fila suele ser más rápida de verificar (con un índice de cobertura en CostType) que verificar todas las filas con un valor no NULL en un "depósito" particular (incluso con índices en cada columna de cantidad, que puede ver que comienza a ser muy derrochador).


SPARSE: este es un muy buen punto que marca la diferencia. Si es escaso, ahorra espacio al normalizar. De otra forma no. Pero el espacio en disco es barato, así que personalmente voto por la máxima flexibilidad (normalizada).

3

Independientemente del beneficio de rendimiento, definitivamente estaría a favor de la opción 1. La opción 2 sería robarle a Peter para pagarle a Paul, en mi opinión.


2

Iría con la opción 1, y luego, si la velocidad de los informes se convertía en un problema en el futuro, también agregaría la tabla 2 y la completaría en una base de datos de informes en algún tipo de proceso automatizado durante la noche / pico.

También podría considerar acumular la estructura de la tabla 2 diaria en acumulaciones adicionales semanales, mensuales, trimestrales y anuales si se justifica.

Pero, como dije, también elegiría almacenar los datos 'en bruto' en forma adecuada (normalizada).


0

Teniendo en cuenta los volúmenes que mencionas, elegiría la segunda opción, pero sin TotalCost. Se podría decir que todavía está normalizado.


Editar: como alternativa, y según sus requisitos y el tamaño del AccountId, también podría considerar lo siguiente:

AccountDate
-----------
AccountId  
Date  
AcDtID (surrogate key)

Costs
-------
AcDtID
CostTypeId  
Amount  

Con ese diseño, aún puede agregar un TotalCost desnormalizado a la primera tabla y volver a calcularlo todas las noches, lo que permite ejecutar algunos informes solo en la primera tabla.


Tengo TotalCostallí porque la mayoría de los informes se resumen, y pensé que sería más rápido consultar un solo valor que agregar 13 valores diferentes.

Probablemente, pero entonces realmente introduces una dependencia transitiva. ¿Se actualizarán esos registros alguna vez? o solo escrito y luego solo leído?

Los registros se actualizarán cada vez que se aplique un nuevo costo a ese rango de fechas. Después de aproximadamente un mes, es poco probable que el costo total se actualice, pero aún es posible debido a cosas como las tarifas anuales de soporte.

Luego, cada actualización requeriría 2 actualizaciones, y el campo TotalCost agrega un riesgo de inconsistencia.

Dependencia transitiva, pero no necesariamente un riesgo de inconsistencia: una restricción CHECK () puede garantizar que TotalCost sea siempre la suma de los costos.
Mike Sherrill 'Cat Recall'

0

En realidad, debe dividir la primera tabla en dos tablas para poder usar una subconsulta y seleccionar la segunda fila como una columna, o muchas columnas. es más flexible de esa manera y por eso, puede obtener un resultado como el segundo más fácilmente.

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.