Estoy trabajando en una aplicación que involucra una ejecución muy alta de consultas de actualización / selección en la base de datos.
Tengo una tabla base (A) que tendrá alrededor de 500 registros para una entidad por un día. Y para cada usuario en el sistema, se crea una variación de esta entidad basada en algunas de las preferencias del usuario y se almacenan en otra tabla (B). Esto lo realiza un trabajo cron que se ejecuta a la medianoche todos los días.
Entonces, si hay 10,000 usuarios y 500 registros en la tabla A, habrá 5 millones de registros en la tabla B para ese día. Siempre guardo los datos de un día en estas tablas y a medianoche guardo los datos históricos en HBase. Esta configuración funciona bien y no tengo problemas de rendimiento hasta ahora.
Últimamente ha habido algún cambio en los requisitos comerciales y ahora algunos atributos en la tabla base A (para 15-20 registros) cambiarán cada 20 segundos y en función de eso tengo que volver a calcular algunos valores para todos esos registros de variación en la tabla B para todos los usuarios. A pesar de que solo cambian 20 registros maestros, necesito volver a calcular y actualizar 200,000 registros de usuarios, lo que lleva más de 20 segundos y, para entonces, la próxima actualización se produce finalmente y todas las consultas de Select se ponen en cola. Recibo alrededor de 3 solicitudes de obtención / 5 segundos de usuarios en línea, lo que resulta en 6-9 consultas de selección. Para responder a una solicitud de API, siempre uso los campos de la tabla B.
Puedo comprar más potencia de procesamiento y resolver esta situación, pero estoy interesado en tener un sistema a escala adecuada que pueda manejar incluso un millón de usuarios.
¿Alguien aquí puede sugerir una mejor alternativa? ¿Nosql + base de datos relacional me ayuda aquí? ¿Existen plataformas / almacenes de datos que me permitan actualizar los datos con frecuencia sin bloqueo y, al mismo tiempo, me den la flexibilidad de ejecutar consultas seleccionadas en varios campos de una entidad?
fuente
Respuestas:
Parece que la tabla
B
es algún tipo de caché. Pero ese tipo de caché que reduce la productividad ...Incluso si tiene 25 consultas por segundo , puede rechazar el uso de la tabla
B
y calcular la respuesta para cada solicitud.De todos modos , si tiene 30 segundos de retraso en la actualización de 20 registros, es una falla en una arquitectura de software (me equivoco, si su DB calcula los primeros 10 ^ 100 signos de PI para cada registro).
Como sé, la base de datos relacional sin consultas SQL feas, con índices y con menos de 1 000 000 de registros funcionará perfectamente para casi todas las consultas.
Intente rechazar el uso de la tabla
B
y agregue índices apropiados a su tablaA
(la mayoría de las bases de datos modernas tienen una herramienta auxiliar). A continuación: intente optimizar la estructura de datos (tablaA
) y una consulta (utilizando el analizador de consultas o con expertos en SQL) para acelerar el cálculo. Si actualiza solo 20 registros, la existencia de índices no dañará la productividad de un proceso de actualización , pero mejorará significativamente la velocidad de selección .fuente
La pregunta realmente es qué sistema calcula el registro para insertar en B y el tamaño de los datos de B.
Cualquier base de datos (p. Ej. MSSQL) debería poder manejar el volumen de inserciones de las que está hablando, no hay problema, suponiendo que el objeto no sea enorme.
Las actualizaciones pueden ser un problema más difícil, pero con la indexación y el bloqueo correctos, nuevamente no debería ser un gran problema.
El 99% del tiempo cuando veo un problema como este se debe a que el registro B está siendo calculado por un proceso almacenado. Esto pone toda la carga en el servidor db
Si este es el caso, la solución es mover este código a un servicio fuera de línea que se puede llamar a través de un sistema de colas.
Por lo tanto, su mensaje de actualización A desencadenaría un proceso de trabajo que pasaría por los usuarios y crearía un mensaje de actualización B para cada usuario
Un segundo proceso de trabajo B recogería la actualización Usuario X con el evento de datos A crearía el registro B y actualizaría la base de datos
Esto se puede escalar agregando más cuadros con trabajadores de cola en ellos, para que tenga más y más poder de procesamiento detrás del cálculo, dejando su base de datos libre para concentrarse en actualizaciones y selecciones.
puede optimizar aún más separando las selecciones de las actualizaciones / inserciones. tiene una nueva base de datos que obtiene todas las solicitudes de selección como esclavo de replicación, la antigua base de datos que recibe todas las actualizaciones.
fuente
Si está ejecutando en Amazon, consideraría DynamoDB. Está basado en memoria flash. Aquí hay un enlace: https://aws.amazon.com/dynamodb/ .
¿Qué tipo de RDBMS estás usando? Es posible que pueda aumentar el rendimiento utilizando un UDF o un campo calculado en una vista. ¿Está ejecutando el cálculo en la base de datos a través de una única consulta de actualización, o selecciona los datos de la base de datos, ejecuta los cálculos en otro proceso y luego los carga nuevamente?
Oracle está configurado de manera predeterminada para usar la ejecución en modo de instantánea, lo que significa que las filas no están bloqueadas durante la actualización y las selecciones simultáneas obtienen el valor original. SQL Server está configurado de manera predeterminada con concurrencia pesimista, por lo que las selecciones simultáneas se bloquearán hasta que se complete la actualización. Algunas versiones de SQL Server se pueden poner en modo de instantánea, sin embargo, aumenta considerablemente el estrés en la tabla temporal.
¿En qué tipo de entorno estás corriendo? Si se trata de un RDBMS en una instancia EC2 en Amazon, intente colocar los archivos de datos DB en el disco flash local. He visto una diferencia de orden de magnitud al mover los archivos de EBS al disco local.
fuente