2009-01-14 9 views
7

Estoy buscando almacenar algunos datos JMX de JVM en muchos servidores durante aproximadamente 90 días. Estos datos serían estadísticas como el tamaño del montón y el conteo de hilos. Esto significa que una de las tablas tendrá alrededor de 388 millones de registros.¿Cuáles son algunas técnicas de optimización para la tabla MySQL con más de 300 millones de registros?

A partir de estos datos, estoy construyendo algunos gráficos para que pueda comparar las estadísticas recuperadas de los Mbeans. Esto significa que tomaré algunos datos en un intervalo usando marcas de tiempo.

Así que la verdadera pregunta es, ¿hay alguna forma de optimizar la tabla o consulta para que pueda realizar estas consultas en un tiempo razonable?

Gracias,

Josh

Respuesta

9

hay varias cosas que puede hacer:

  1. construir su índices para que coincida con las consultas que se están ejecutando. Ejecute EXPLAIN para ver los tipos de consultas que se ejecutan y asegúrese de que todos utilicen un índice siempre que sea posible.

  2. Particiona tu mesa. La parición es una técnica para dividir una tabla grande en varias más pequeñas por una clave específica (agregada). MySQL lo admite internamente desde ver. 5.1.

  3. Si es necesario, cree tablas de resumen que guarden en caché las partes más costosas de sus consultas. A continuación, ejecute sus consultas en las tablas de resumen. De forma similar, las tablas temporales en memoria se pueden usar para almacenar una vista simplificada de su tabla como una etapa de procesamiento previo.

2

3 sugerencias:

  1. índice
  2. índice
  3. índice

P. S. para las marcas de tiempo, puede tener problemas de rendimiento: dependiendo de cómo MySQL maneje DATETIME y TIMESTAMP internamente, puede ser mejor almacenar marcas de tiempo como enteros. (# segundos desde 1970 o lo que sea)

2

Bueno, para empezar, sugiero que utilice el procesamiento "fuera de línea" para producir datos 'listos para gráficos' (para la mayoría de los casos comunes) en lugar de intentar consultar los datos sin procesar Bajo demanda.

1

Si está utilizando MYSQL 5.1 puede usar las nuevas funciones. pero ten en cuenta que contienen muchos errores.

primero debe usar índices. si esto no es suficiente, puede intentar dividir las tablas mediante el uso de particiones.

si esto tampoco funciona, también puede intentar equilibrar la carga.

1

Algunas sugerencias.

Probablemente va a ejecutar consultas agregadas sobre estas cosas, por lo que después (o mientras) cargue los datos en sus tablas, debe preagregar los datos, por ejemplo, calcular totales por hora, o por usuario, o por semana, lo que sea, obtiene la idea, y la almacena en tablas de caché que usa para sus gráficos de informes. Si puede reducir su conjunto de datos en un orden de magnitud, entonces, ¡bien por usted!

Esto significa que obtendré algunos datos en un intervalo utilizando marcas de tiempo.

¿Esto significa que solo utiliza los datos de los últimos X días?

Eliminar los datos antiguos de las tablas puede ser terriblemente lento si tiene que eliminar algunas decenas de millones de filas, el particionamiento es ideal (simplemente suelte esa partición anterior). También agrupa todos los registros del mismo período de tiempo juntos en el disco para que sea mucho más eficiente en la caché.

Ahora, si utiliza MySQL, le sugiero que use tablas MyISAM. No obtienes protección contra fallas o transacciones y el bloqueo es tonto, pero el tamaño de la tabla es mucho menor que InnoDB, lo que significa que puede caber en la memoria RAM, lo que significa un acceso mucho más rápido.

Dado que los grandes agregados pueden implicar una gran cantidad de IO en disco secuencial, un sistema IO rápido como RAID10 (o SSD) es un plus.

¿Hay alguna forma de optimizar la tabla o consulta para que pueda realizar estas consultas en un tiempo razonable?

Eso depende de la tabla y las consultas; no puedo dar ningún consejo sin saber más.

Si necesita consultas complicadas de informes con grandes agregados y uniones, recuerde que MySQL no admite ningún JOINs sofisticado, o agregados hash, o cualquier otra cosa realmente útil, básicamente, lo único que puede hacer es indexado de bucle anidado que es bueno en una tabla en caché, y absolutamente atroz en otros casos si se trata de un acceso aleatorio.

Sugiero que pruebe con Postgres. Para grandes agregados, el optimizador más inteligente funciona bien.

Ejemplo:

CREATE TABLE t (id INTEGER PRIMARY KEY AUTO_INCREMENT, category INT NOT NULL, counter INT NOT NULL) ENGINE=MyISAM; 
INSERT INTO t (category, counter) SELECT n%10, n&255 FROM serie; 

(Serie contiene líneas 16M con n = 1 .. 16000000)

MySQL Postgres  
58 s  100s  INSERT 
75s  51s  CREATE INDEX on (category,id) (useless) 
9.3s  5s   SELECT category, sum(counter) FROM t GROUP BY category; 
1.7s  0.5s  SELECT category, sum(counter) FROM t WHERE id>15000000 GROUP BY category; 

en una consulta simple como este PG es aproximadamente 2-3 veces más rápido (la diferencia sería ser mucho más grande si se trata de uniones complejas).

0
  1. explicar sus consultas SELECT
  2. LIMIT 1 al conseguir una única fila SELECT * FROM usuarios DONDE estado = 'Alabama' // mal seleccione 1 DE DONDE usuario estado LÍMITE = 'Alabama' 1

  3. Indexe los campos de búsqueda Los índices no son solo para las teclas principales o únicas. Si hay columnas en su tabla que buscará, casi siempre debe indexarlas.

  4. Indice y uso de los mismos tipos de columnas para combinaciones Si su aplicación contiene muchas consultas JOIN, debe asegurarse de que las columnas por las que se une estén indexadas en ambas tablas. Esto afecta la forma en que MySQL optimiza internamente la operación de unión.

  5. No ORDEN POR RAND() Si realmente necesita filas aleatorias de sus resultados, hay formas mucho mejores de hacerlo. De acuerdo, requiere código adicional, pero evitará un cuello de botella que empeora exponencialmente a medida que crecen sus datos. El problema es que MySQL tendrá que realizar la operación RAND() (que toma la potencia de procesamiento) para cada fila de la tabla antes de ordenarla y darle solo una fila.

  6. Utilice ENUM sobre VARCHAR Las columnas de tipo ENUM son muy rápidas y compactas. Internamente se almacenan como TINYINT, pero pueden contener y mostrar valores de cadena.

  7. Use NOT NULL If Can Can A menos que tenga un motivo muy específico para usar un valor NULL, siempre debe establecer las columnas como NOT NULL.

    "Las columnas NULL requieren espacio adicional en la fila para registrar si sus valores son NULL. Para las tablas MyISAM, cada columna NULL toma un bit adicional, redondeado al byte más cercano."

  8. Almacenar direcciones IP como INT no identificado En sus consultas puede usar INET_ATON() para convertir e IP a un entero, e INET_NTOA() para viceversa. También hay funciones similares en PHP llamadas ip2long() y long2ip().

Cuestiones relacionadas