¿Usa MySQL para hacer regularmente combinaciones de múltiples vías en tablas de más de 100 GB?


11

Antecedentes :
he creado una aplicación web que me gustaría poder escalar razonablemente bien. Sé que no soy Google ni Twitter, pero mi aplicación utiliza una cantidad bastante grande de datos para cada usuario y, por lo tanto, tiene requisitos de datos bastante altos. Quiero estar listo para escalar razonablemente bien sin tener que rediseñar todo más tarde.

Me considero un desarrollador de software, no un experto en bases de datos. Es por eso que estoy publicando aquí. Espero que alguien con mucha más experiencia en bases de datos pueda darme consejos.

Con un número relativamente grande de usuarios, pero nada parecido a los números de Facebook, espero tener un DB que se vea así:

Una "mesa grande":

  • 250 millones de registros
  • 20 columnas
  • Aproximadamente 100 GB de datos
  • Tiene una clave foránea indexada bigint (20)
  • Tiene una columna varchar (500) string_id indexada
  • Tiene una columna de "valor" int (11)

4 otras mesas:

  • 10 millones de registros cada uno
  • Aproximadamente 2 - 4 GB de datos cada uno
  • cada una de estas tablas tiene 4 - 8 columnas
  • una columna es datetime date_created
  • una columna es la columna varchar (500) string_id
  • se seleccionarán una o dos columnas de cada una de estas tablas en una unión

Una de estas tablas se usa para almacenar promedios: su esquema es bigint (20) id, varchar (20) string_id, datetime date_created, float average_value

Lo que quiero hacer : dos consultas relativamente caras:

  1. Calcular nuevos valores promedio:

    • Con una clave externa, seleccione hasta varios millones de registros separados de la tabla grande.
    • Calcule un nuevo promedio, agrupando por string_id.
    • Insertar resultados en la tabla de promedios.
    • Tal como se construye actualmente, esta consulta usa dos combinaciones.
  2. Cree registros de solo lectura no normalizados para servir a los usuarios:

    • Use una clave externa para seleccionar entre 1,000 y 40,000 registros de la tabla grande.
    • Únase a cada una de las otras cuatro tablas en el registro más nuevo con la columna de id. De cadena.
    • Inserte los resultados en una tabla desnormalizada.
    • Estos registros son para uso del front-end para mostrar información a los usuarios.
    • Tal como se construye actualmente, esta consulta usa cuatro combinaciones.

Planeo ejecutar cada una de estas costosas consultas en una base de datos de fondo de lote que empujará sus resultados a un servidor de base de datos front-end en tiempo real que maneja las solicitudes de los usuarios. Estas consultas se ejecutarán a intervalos regulares. No he decidido con qué frecuencia. La consulta promedio podría hacerse quizás una vez al día. La consulta de normalización deberá ser más frecuente, tal vez cada pocos minutos.

Cada una de estas consultas se ejecuta actualmente en unos pocos segundos en MySQL en una máquina de muy bajo nivel con un conjunto de datos con 100K registros en la "tabla grande". Me preocupan tanto mi capacidad de escalar como los costos de escalar.

Preguntas :

  1. ¿Este enfoque parece sólido? ¿Hay algo obviamente malo desde una perspectiva general?
  2. ¿Es un RDBMS la herramienta adecuada, o debería mirar otras soluciones de "big data" como algo de la familia Hadoop? Mi inclinación es usar un RDBMS porque los datos están estructurados y encajan perfectamente en el modelo relacional. Sin embargo, en cierto momento, entiendo que es posible que ya no pueda usar un RDBMS. ¿Es eso cierto? ¿Cuándo sería necesario este cambio?
  3. ¿Funcionará? ¿Se pueden ejecutar estas consultas en un tiempo razonable? Puedo esperar quizás horas para la consulta n. ° 1, pero la consulta n. ° 2 debería finalizar en minutos.
  4. ¿Qué debo considerar desde una perspectiva de hardware? ¿Cuáles son mis cuellos de botella de RAM y CPU? Asumo que mantener índices en RAM es importante. ¿Hay algo más que deba considerar?
  5. En algún momento, probablemente tendré que particionar mis datos y usar múltiples servidores. ¿Parece que mi caso de uso ya está en esa categoría, o podré escalar una sola máquina verticalmente por un tiempo? ¿Funcionará esto con 10 veces los datos? 100x?

Este es difícil de responder a fondo. Quizás sea mejor que investigue sobre las características de rendimiento de las consultas MySQL en general para que sepa lo que puede esperar .; Una cosa que siempre puede hacer, por supuesto, es colocar 20 discos en el servidor para que pueda leer a 3 GB / s más o menos. Pero creo que buscas una respuesta exhaustiva de solo software.
usr

Respuestas:


4

¿Has intentado acumular más datos y compararlos? 100K filas son intrascendentes. Pruebe 250M o 500M como espera que necesite manejar y ver dónde están los cuellos de botella.

Un RDBMS puede hacer muchas cosas si presta mucha atención a las limitaciones e intenta trabajar con las fortalezas del sistema. Son excepcionalmente buenos en algunas cosas y terribles en otras, por lo que tendrá que experimentar para asegurarse de que encajan bien.

Para algunos trabajos de procesamiento por lotes, realmente no puede vencer a los archivos planos, cargar los datos en la RAM, destruirlos usando una serie de bucles y variables temporales, y descartar los resultados. MySQL nunca podrá igualar ese tipo de velocidad, pero si se ajusta correctamente y se usa correctamente, puede entrar en un orden de magnitud.

Lo que querrá hacer es investigar cómo se pueden particionar sus datos. ¿Tiene un gran conjunto de datos con demasiados enlaces cruzados para poder dividirlo, o hay lugares naturales para dividirlo? Si puede dividirlo, no tendrá una tabla con un montón de filas, sino potencialmente muchas más pequeñas. Las tablas más pequeñas, con índices mucho más pequeños, tienden a funcionar mejor.

Desde una perspectiva de hardware, deberá probar para ver cómo funciona su plataforma. A veces la memoria es esencial. Otras veces es E / S de disco. Realmente depende de lo que esté haciendo con los datos. Deberá prestar mucha atención al uso de su CPU y buscar altos niveles de E / S. Espere para saber dónde radica el problema.

Siempre que sea posible, divida sus datos en múltiples sistemas. Puede usar MySQL Cluster si se siente valiente, o simplemente activar muchas instancias independientes de MySQL donde cada una almacena una porción arbitraria del conjunto de datos completo utilizando algún esquema de partición que tenga sentido.


@tadman Gracias por tu consejo. Me doy cuenta de que no hay sustituto para probarlo realmente. No lo he comparado con 250 millones de filas porque primero quería asegurarme de que obviamente no había nada malo en mi enfoque. Parece que no hay. Además, obtener esa cantidad de datos y hacerlo de una manera que sea algo realista es un desafío que aún no he descubierto cómo resolver. Tengo algunas formas potenciales de particionar los datos. Supongo que luego intentaré aumentar mis datos y ver cómo funciona en diferentes puntos de control: 1M, 10M, 100M, etc.
xnickmx

1

Tablas de resumen.

Todos los días, calcule información agregada para los datos del día. Ponga eso en la (s) tabla (s) de "resumen". Haz tus consultas contra ellos. Fácilmente 10 veces más rápido.

Para mayor discusión, por favor proporcione

  • MOSTRAR CREAR TABLA (tal como está ahora)
  • Tamaños de tabla (que ha mencionado)
  • SELECTs propuestos

Algunas cosas obvias ...

  • BIGINT rara vez se justifica. Tarda 8 bytes. INT UNSIGNED toma 4 y permite valores 0..4 billones. Y hay MEDIUMINT, etc.
  • Los índices múltiples en la tabla de "hechos" suelen ser un problema de rendimiento grave, especialmente para los INSERT. ¿Tienes algún problema allí?
  • DATETIME es de 8 bytes; TIMESTAMP es 4
  • Las RESTRICCIONES EXTRANJERAS CLAVE explícitas son agradables, pero costosas
  • JOIN puede o no ser un problema de rendimiento; necesita ver SELECCIONAR y CREAR.
  • 100 GB es un buen tamaño para una base de datos MySQL 'grande'; Sospecho que podría funcionar sin Hadoop, etc. Ahora trato con uno de esos db: la mayoría de las páginas de la interfaz de usuario responden en menos de un segundo a pesar de que los datos están bastante involucrados.
  • ¿Va a 'purgar' datos en algún momento? (Esto lleva al caso de uso principal para PARTICIONAMIENTO).

"Más pequeño -> más almacenable en caché -> más rápido


0

Para servir sus datos de front-end, a menos que haya montones y montones de insertos todo el tiempo, realmente no puede superar el uso de disparadores para insertar en vistas materializadas que se mantienen sincronizadas con el back-end pero optimizadas para servir los datos. Por supuesto, debe mantener las uniones, etc., etc., al mínimo en estos desencadenantes. Una estrategia que he usado es poner estos insertos / actualizaciones en una tabla intermedia y luego enviarlos más tarde cada minuto más o menos. Es mucho más fácil enviar un registro que 4 GB de registros. La transmisión de 4 GB de datos tarda mucho tiempo, incluso si puede encontrar rápidamente los registros que está buscando.

Estoy de acuerdo con tadman. Lo mejor es perfilarlo con el tipo de datos que espera del tipo de sistema que desea.


Como mencioné en mi publicación, las vistas dependen de una consulta que utiliza cuatro combinaciones en tablas con decenas de millones de registros, por lo que realmente no veo cómo va a ayudar una vista materializada.
xnickmx

Los disparadores pueden no ser lo suficientemente rápidos para esta base de datos de tamaño. ¿Cuántos INSERTOS por segundo están sucediendo?
Rick James el

1
@xnickmx Si no hay tantas inserciones / actualizaciones, los disparadores hacen que sea fácil / eficiente mantener sincronizados los datos desnormalizados. Si necesita ir más rápido para las inserciones / actualizaciones, agrúpelas con algo como esto: blog.shlomoid.com/2008/04/… o hornee el suyo. De esta manera, no tiene que unirse a las tablas de 100 millones de filas existentes para obtener los nuevos datos, ya que cuando se activa el desencadenador, aprovecha el hecho de que conoce los nuevos datos en ese momento y puede desnormalizarlos como parte del tx o ponerlo en cola para la desnormalización posterior.
wes.stueve

@RickJames De acuerdo. Debe tener en cuenta la cantidad de inserciones para este tipo de estrategia y qué tan rápido deben procesar.
wes.stueve
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.