Antecedentes
Tengo una red de aproximadamente 2000 sensores, cada uno de los cuales tiene alrededor de 100 puntos de datos que recopilamos en intervalos de 10 minutos. Estos puntos de datos suelen ser valores int, pero algunos son cadenas y flotantes. Estos datos deben almacenarse durante 90 días, más si es posible y aún así eficientes.
Diseño de bases de datos
Cuando originalmente tuve la tarea de este proyecto, escribí una aplicación C # que escribía archivos separados por comas para cada sensor. En ese momento no había tantos, cuando alguien quería mirar las tendencias, abríamos el csv en Excel y lo graficamos según fuera necesario.
Las cosas crecieron y cambiamos a una base de datos MySQL. Creé una tabla para cada sensor (sí, lo sé, ¡muchas tablas!); Ha estado funcionando bien, pero tiene algunas limitaciones. Con tantas tablas, obviamente es imposible escribir una consulta que encuentre datos entre todos los sensores cuando se busca un valor particular.
Para la próxima versión, cambié a Microsoft SQL Server Express y puse todos los datos del sensor en una tabla grande. Esto también funciona y nos permite hacer consultas para encontrar valores entre todos los sensores que son de interés. Sin embargo, me encontré con el límite de 10 GB para la versión Express, y he decidido volver a MySQL en lugar de invertir en SQL Server Standard.
La pregunta
Estoy contento con el rendimiento y la escalabilidad de MySQL, pero no estoy seguro de si es mejor apegarse al enfoque de todos los datos en una tabla. 10GB en una sola mesa parece estar pidiendo un diseño diferente. Debo mencionar que la necesidad de consultar datos para la representación gráfica todavía existe, y me preocupa que haya problemas de rendimiento para una consulta que grafica, por ejemplo, datos de temperatura para un sensor durante los 90 días completos. (En otras palabras, el gráfico debe ser algo que se produzca rápidamente, sin esperar a que SQL clasifique las pilas de datos solo para aislar el sensor de interés).
¿Debería dividir esta tabla de alguna manera para aumentar el rendimiento? ¿O no es inusual tener una mesa tan grande?
Tengo índices en las columnas ID de sensor y Marca de tiempo, que son más o menos los límites que definen cualquier consulta. (es decir, obtener datos para el sensor X del tiempo A al tiempo B).
He leído un poco sobre fragmentación y particionamiento, pero no creo que sean apropiados en este caso.
Editar:
Según los comentarios y las respuestas hasta ahora, alguna información adicional puede ser útil:
Almacenamiento no indefinido: actualmente no almaceno datos durante los últimos 90 días. Diariamente, ejecuto una consulta que elimina datos de más de 90 días. Si se vuelve importante en el futuro, almacenaré más, pero por ahora es suficiente. Esto ayuda a mantener el tamaño bajo control y un alto rendimiento (er).
Tipo de motor: la implementación original de MySQL utilizaba MyISAM. Al crear las tablas esta vez para la nueva implementación (una tabla de datos en lugar de muchas), su valor predeterminado es InnoDB. No creo que tenga un requisito para uno u otro.
Normalización: Por supuesto, hay otras tablas además de la tabla de recopilación de datos. Estas tablas de soporte almacenan cosas como información de red para los sensores, información de inicio de sesión para los usuarios, etc. No hay mucho que normalizar (que yo sepa). La razón por la que la tabla de datos tiene tantas columnas es que hay tantas variables de cada sensor. (Múltiples temperaturas, niveles de luz, presión de aire, etc.) La normalización para mí significa que no hay datos redundantes o grupos repetidos. (Al menos para 1NF.) Para un sensor dado, el almacenamiento de todos los valores en un momento particular requiere una fila de datos y no hay relaciones 1: N involucradas allí (eso veo).
Podría separar la tabla funcionalmente, haciendo (por ejemplo) todos los valores relacionados con la temperatura en una tabla, y todos los valores relacionados con la presión del aire en otra. Si bien esto podría mejorar la eficiencia para alguien que realiza una consulta de solo temperatura, todavía tengo que insertar todos los datos a la vez. Aún así, la ganancia de eficiencia podría valer la pena para las operaciones SELECT. Obviamente, sería mejor separar la tabla verticalmente según la frecuencia con la que los usuarios solicitan los datos. Quizás esto es todo lo que debería hacer. Supongo que al hacer mi pregunta, estoy buscando confirmación de que valga la pena hacerlo.
Edición 2:
Uso de datos: en última instancia, gran parte de los datos nunca se miran ni se necesitan, porque generalmente nos enfocamos solo en elementos con problemas. Pero al tratar de encontrar problemas, utilizamos varias herramientas para buscar los datos y determinar qué elementos ampliar.
Por ejemplo, notamos una correlación entre un valor de uso de memoria (un programa de software propietario específico del cliente) y un reinicio / bloqueo. Uno de los puntos de datos que recopilo se relaciona con este uso de memoria, y pude ver datos históricos para mostrar que los dispositivos se vuelven inestables después de que se excede un uso de memoria en particular. Hoy, para el subconjunto de dispositivos que ejecutan este software, verifico este valor y emito un comando de reinicio si es demasiado alto. Hasta que se descubrió esto, no pensé que la recopilación de estos datos fuera de valor.
Por esta razón, he mantenido que se recopilan y almacenan unos 100 puntos de datos, incluso si el valor es cuestionable. Pero en el uso normal del día a día, los usuarios suelen examinar una docena de estos parámetros. Si un usuario se interesa en un área geográfica particular, puede (utilizando software) generar gráficos u hojas de cálculo de datos para quizás unas pocas docenas de sensores. No es raro mirar un gráfico de 30 días con dos o tres líneas de trama que muestran cosas como la temperatura, la presión del aire y los niveles de luz. Hacer esto ejecutaría una consulta similar a esta:
SELECT sensor_id, location, data_timestamp, temp1, air1, light1
FROM data
WHERE data_timestamp >= '2012-02-01'
AND sensor_id IN (1, 2, 3);
(En la versión original de MySQL, donde cada sensor tenía su propia tabla, se emitirían tres consultas separadas, pero los resultados se combinaron en un software para crear el gráfico).
Debido a que la data
tabla contiene tantas filas (~ 10 millones), a pesar de tener índices id
y data_timestamp
, el rendimiento es notablemente peor que el escenario de tablas múltiples (4500 filas devueltas en 9 segundos en lugar de menos de un segundo con este ejemplo). La capacidad de encontrar qué sensores cumplen ciertos criterios es prácticamente nula en el esquema de varias tablas, y por lo tanto, la razón para pasar a una sola tabla.
Varios usuarios pueden realizar este tipo de consulta en una sucesión rápida, ya que seleccionan diferentes grupos de datos y comparan los gráficos de cada resultado. Puede ser bastante frustrante esperar casi 10 segundos por gráfico u hoja de cálculo.
Los datos se descartan después de 90 días. Podría archivarse pero actualmente no es un requisito.
Esperemos que esta información ayude a mostrar de manera más adecuada cómo se usan los datos después de la recolección y el almacenamiento.