Bandera vs tabla dividida


10

Estoy diseñando una tabla de elementos que contendrá (potencialmente) decenas de millones de registros. Algunos elementos no estarán disponibles para su uso hasta que sean "aprobados" por el administrador. Por "uso" me refiero a que dichos elementos no serán referenciados en ninguna otra tabla hasta que estén "aprobados". Hasta el 50% de los artículos pueden estar "no aprobados" en un momento dado. Los registros pueden ser "aprobados", pero no al revés.

Considero dos opciones de diseño:

  • un poco de bandera
  • una tabla separada de artículos "no aprobados": cuando el artículo se aprueba, se mueve a la tabla "normal" (la renovación de la ID del artículo no es un problema)

Creo que la segunda opción es mucho mejor. El indicador de bit solo toma un byte por fila, por lo que no es un problema. Pero si tenemos un millón de registros aprobados y un millón de registros no aprobados en la misma tabla, el tiempo de exploración aumenta para las operaciones con registros aprobados.

La pregunta es: ¿debería considerar la primera opción (bandera de bits) en su lugar? ¿Tiene algún beneficio en la situación descrita?


1
Puede ser útil recordar que puede usar índices filtrados para acelerar el acceso a los registros aprobados. brentozar.com/archive/2013/11/…
mendosi

Lamentablemente, los índices filtrados no se utilizan en consultas parametrizadas.
Dima

@Dima eso no es del todo cierto. Si un índice filtrado tiene voz WHERE status='A'y una consulta tiene WHERE status = 'A' AND (... other columns and parameters here...), entonces el índice aún podría usarse.
ypercubeᵀᴹ

Respuestas:


6

Puede tenerlo en ambos sentidos con vistas particionadas .

Se crea una tabla subyacente para cada estado, forzada por restricciones, con valores mutuamente excluyentes. Luego, una vista que une las tablas subyacentes. La vista o cada tabla base se puede referenciar explícitamente. Si el estado de una fila se ACTUALIZA a través de la vista, el DBMS lo ELIMINARÁ de una tabla base y lo insertará en la correspondiente al nuevo estado. Cada tabla base puede indexarse ​​independientemente de acuerdo con su patrón de uso. El optimizador resolverá las referencias de índice a una sola tabla base correspondiente si puede.

Los beneficios son
a) índices menos profundos. Sin embargo, haga los cálculos en el índice de despliegue En esa escala y dividida entre sus valores de estado, es posible que los índices tengan la misma profundidad en las tablas divididas que en la tabla combinada.
b) ningún código de aplicación tiene que cambiar. Los datos continúan apareciendo como un todo continuo.
c) se pueden incluir nuevos valores de estado futuros agregando una nueva tabla base, con restricción, y recreando la vista.

El costo es todo ese movimiento de datos; Se escriben dos páginas e índices asociados para cada actualización de estado. Un montón de IO para tratar. Tanto movimiento causará fragmentación también.


5

una tabla de elementos que contendrá (potencialmente) decenas de millones de registros.

En realidad, eso no es mucho, dado lo que SQL Server puede manejar de manera eficiente. Por supuesto, recuerdo uno de mis trabajos anteriores en el que una de las tablas más grandes (un sistema de instancia única) tenía 2 millones de filas y eso era lo máximo con lo que había tratado. Luego, el siguiente trabajo tuvo 17 instancias de producción con algunas tablas con cientos de millones de filas, y todas se agregaron a un Data Warehouse con múltiples tablas de hechos con más de mil millones de filas. No me malinterpreten, no me estoy burlando de decenas de millones de filas, solo estoy enfatizando que con un buen modelo de datos y una indexación adecuada (y mantenimiento del índice), SQL Server puede manejar mucho .

Hasta el 50% de los artículos pueden estar "no aprobados" en un momento dado.

Hmm Eso no suena bien. La tasa de "aprobar" entradas será la mitad de la tasa de obtener nuevas entradas? Por cada 2 nuevas entradas, ¿solo 1 será "aprobado"? En su ejemplo de 2 millones de filas, y 1 millón cada una para "aprobado" y "no aprobado", unos años más tarde con otros 10 millones de entradas, ¿espera 6 millones cada una para "aprobado" y "no aprobado"? ¿O es que el millón de "no aprobado" permanecerá algo constante, de modo que con 10 millones de nuevas entradas, habrá 11 millones de "aprobado" y todavía 1 millón de "no aprobado"?

Los registros pueden ser "aprobados", pero no al revés.

Eso es cierto hoy , pero las cosas cambian con el tiempo y, por lo tanto, siempre existe la posibilidad de que la empresa decida permitir "no aprobar", o tal vez algún otro estado, como "archivado", etc.

Entonces, veamos las opciones:

Bandera (o posiblemente incluso TINYINT"estado")

  • Ligeramente más lento para consultas de cada estado
  • Más flexible con el tiempo / fácil de incorporar un cambio como un tercer estado (por ejemplo, "Archivado") con solo un nuevo valor de estado de búsqueda. No hay una nueva tabla (necesariamente), algún código nuevo, solo un código actualizado.
  • Menos trabajo (es decir, código, pruebas, etc.) y menos espacio para errores al actualizar una sola TINYINTcolumna
  • Menos complicado = menores costos de mantenimiento a lo largo del tiempo, menor tiempo de capacitación para que los nuevos empleados descubran
  • (posiblemente) Impacto menor en el Registro de transacciones cuando se actualiza una tabla
  • Solo necesito una tabla de búsqueda para "RecordStatus" y FK entre las dos tablas.

Dos tablas separadas (una para "aprobado", una para "no aprobado")

  • Ligeramente más rápido para consultas de cada estado
  • Menos flexible con el tiempo / más difícil incorporar un cambio como un tercer estado (por ejemplo, "Archivado"); El nuevo estado probablemente requeriría otra tabla, y definitivamente un código nuevo y actualizado.
  • Más trabajo (es decir, código, pruebas, etc.) y más espacio para errores al mover registros de la tabla "No aprobada" a la tabla "Aprobada"
  • Más complicado = mayores costos de mantenimiento a lo largo del tiempo, mayor tiempo de capacitación para que los nuevos empleados descubran
  • (posiblemente) Mayor impacto en el Registro de transacciones cuando se elimina una tabla y se inserta una
  • No debe preocuparse por la " renovación de la ID del artículo ": la tabla no IDENTITYaprobada tiene una columna de ID que es una columna, y la tabla aprobada tiene una columna de ID que no es una IDENTITY(ya que no se necesita allí). Por lo tanto, los valores de ID permanecen consistentes a medida que el registro se mueve entre tablas.

Personalmente, me inclinaría hacia la mesa individual con StatusIDcolumna para empezar. Usar dos tablas parece una optimización demasiado complicada y prematura. Ese tipo de optimización puede discutirse si / cuando el número de registros está en varios cientos de millones y la indexación no proporciona ninguna ganancia de rendimiento.


Es una tabla con datos que se mueven rápidamente: a menudo se rellenan con muchas filas nuevas, a menudo se eliminan filas. Traté de eliminar todos los detalles (como la decisión comercial, la codificación del cliente, etc.) para concentrarme solo en un solo tema. Básicamente tenemos la tabla de diseño antiguo con un poco de bandera. Y sé al 100% que las filas donde el indicador se establece en 1 nunca se usan en ninguna otra tabla. Así que siento que solo tienen lugar allí y pueden trasladarse a una mesa separada. La tabla se escanea casi en cada consulta a DB. Por lo tanto, reducir su "peso" potencialmente puede reducir las operaciones de CPU / IO.
Dima

3
Otra ventaja de las tablas divididas: puede tener FK que solo hagan referencia a la tabla "Aprobada".
ypercubeᵀᴹ

El otro problema con las tablas divididas para una sola entidad es la integridad de la restricción. Las referencias de otras tablas no jugarán bien con el registro moviéndose. Esto requerirá que se escriba el código para solucionar estos problemas, como las tablas de referencia espejo para la tabla dividida -> Muy problemático
usuario1567453
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.