Almacenar envíos de grandes cantidades de datos en MySQL

babri

Buenas MediCoders!

Estoy actualmente en un proyecto en el que revisando todo minuciosamente me he encontrado con lo siguiente:

Tabla: XXXXXXXX
Registros: 20.654.165
Peso: 4gb

Me ha sorprendido ver dicha tabla porque la tabla que debería de contener la esencia del negocio no sobrepasa los 500mil registros que es básicamente lo que vendemos.

Ante esto me he puesto a revisar código y para que os hagáis una idea lo que hacemos es generar envíos de datos, esto significa vender un CSV con X registros en cada archivo. Por ejemplo esta mañana le vendimos a un cliente un CSV de 6k de registros. Hasta aquí OK.

Pero lo malo es que se genera 1 registro en la super tabla de 12 milones por cada registro que vendemos en vez de hacer una tabla de envíos y asociarlo.

Estoy planteando como generar Envio 1 Envio 2 Envio 3 y por su id saber que registros se envía en cada envío.
Pero si lo hago una relacional volvería a generar el mismo problema.

La consultas se están yendo a 6 segundos para en según que zonas de la aplicación, sobre todo en reporting.

Alguna sugerencia?
Una NoSQL podría ayudar?

HeXaN

Un Postgres bien montado debería comerse eso sin problema. Si el problema es relacional, mantenlo relacional y diséñalo bien.

2 1 respuesta
babri

#2 Es relacional, la verdad que la BBDD es para verla, casi mi pregunta es alguna idea para plantear el diseño y migrar lo que ya hay.

Wasd

Primero habria que saber si luego consultas esa información de forma unidireccional o bidireccional (es decir, solo te interesa saber qué registros se enviaron en cada envío, o tambien te puede interesar saber qué envios contienen X registro?).
Esta tabla de 20 millones, se utiliza unicamente a modo de histórico o tiene valor funcional?
No tengo claro que una solución NoSQL puede aportar algo en este caso.

Se me ocurre por ejemplo:

  • Una tabla n-m que relacione envíos con registros. Se seguirán generando un huevo de rows, pero la información en ellas seran solo id de envío y id de registro.
  • Que la tabla envíos contenga un campo JSON con todos los id's de sus registros (eso implica no poder consultar directamente sino que necesitarías un proceso de parseo. Me puede parecer interesante si la tabla solo se usa a modo de histórico y consultarlo es algo que ocurre solo de vez en cuando), y por supuesto estaría pensado de forma unidireccional, ya que si tienes millones de envíos, mirar qué registros aparecen en qué envíos puede ser un suplicio.

Si las queries de reporting se ven afectadas por esa tabla imagino que tiene valor funcional y no se usa unicamente para insertar datos por cada venta. Creo que en general falta información...

1 1 respuesta
Ranthas

En #4 tienes la respuesta. En mi opinión, una BBDD NoSQL no te va a solucionar el problema.

Si tienes un histórico de envíos que usas para reporting (algo absolutamente normal y corriente) debes mantener esa tabla como la traducción de la relación M:N entre dos entidades (producto y envío). Mantienes la mínima información, las inserciones mantienen la máxima eficiencia (sólo recreas el índice de la PK) y las búsquedas son directas a la vez que filtrantes.

Una BBDD relacional no debe tener problemas con ese volumen de información, así que todo apunta a un diseño poco consistente o erróneo.

Otra solución (nosotros la tenemos implementada) es mantener un versionado del histórico. Todos los datos del histórico no son necesarios, ya que en nuestro negocio, sólo son "relevantes" los datos del año en curso y cuatro años posteriores; datos más viejos no se usan apenas, sólo en requerimientos judiciales, algo extraordinario. Por tanto, el 90% de los datos de ese histórico son irrelevantes, por lo que se mueven a una nueva tabla, un versionado del histórico, y se mantienen allí.

De esa manera conservas todo el volumen de datos, pero mantienes las tablas de negocio saneadas con la información imprescindible. Para que te hagas una idea, estas tablas de las que te hablo (histórico) maneja un volumen del orden de 109 registros, y el historico simplemente no le he hecho un count(*), pero puede ser de espanto.

Otra solución si no puedes modificar la BBDD, es páginar las consultas por soft o SQL (LIMIT en Oracle).

Ya nos comentas, espero que te sirva de ayuda

1
babri

Buenas!

Al final voy a dejar N a N los registros de la tabla grande y separo como entidad ENVIOS.
De esta forma no tengo que estar filtrado en 12 millones de registros a día de hoy mucha información y solo saco X registros según su relación.

Muchas gracias a todos :)

1 respuesta
JackSparow

#6 Si la demora es por una consulta con unos filtros muy concretos, como por ejemplo, filtrar siempre una combinación de dos columnas, prueba de crear un índice sobre esa combinación de dos columnas (no dos índices).

Usuarios habituales

  • JackSparow
  • babri
  • Ranthas
  • Wasd
  • HeXaN