¿Enfoques de fragmentación de MySQL?

88

¿Cuál es el mejor enfoque para fragmentar tablas MySQL? Los enfoques en los que puedo pensar son:

  1. ¿Fragmentación de nivel de aplicación?
  2. ¿Fragmentación en la capa de proxy MySQL?
  3. ¿Servidor de búsqueda central para fragmentación?

¿Conoce algún proyecto o herramienta interesante en esta área?

sheki
fuente

Respuestas:

116

El mejor enfoque para fragmentar tablas MySQL es no hacerlo a menos que sea totalmente inevitable hacerlo.

Cuando está escribiendo una aplicación, generalmente desea hacerlo de una manera que maximice la velocidad, la velocidad del desarrollador. Optimiza la latencia (tiempo hasta que la respuesta está lista) o el rendimiento (número de respuestas por unidad de tiempo) solo cuando es necesario.

Usted particiona y luego asigna particiones a diferentes hosts (= fragmento) solo cuando la suma de todas estas particiones ya no cabe en una sola instancia de servidor de base de datos, la razón de esto es escribir o leer.

El caso de escritura es a) la frecuencia de las escrituras sobrecarga los discos de este servidor de forma permanente ob) hay demasiadas escrituras en curso de modo que la replicación se retrasa permanentemente en esta jerarquía de replicación.

El caso de lectura para la fragmentación es cuando el tamaño de los datos es tan grande que su conjunto de trabajo ya no cabe en la memoria y las lecturas de datos comienzan a llegar al disco en lugar de servirse desde la memoria la mayor parte del tiempo.

Sólo cuando se tiene a fragmentar que hacerlo.


En el momento en que fragmenta, lo paga de varias maneras:

Gran parte de su SQL ya no es declarativo.

Normalmente, en SQL le dice a la base de datos qué datos desea y deja que el optimizador convierta esa especificación en un programa de acceso a datos. Eso es bueno, porque es flexible y porque escribir estos programas de acceso a datos es un trabajo aburrido que daña la velocidad.

Con un entorno fragmentado, probablemente esté uniendo una tabla en el nodo A con datos en el nodo B, o tiene una tabla más grande que un nodo, en los nodos A y B y está uniendo datos de ella con datos que están en los nodos B y C. Está comenzando a escribir resoluciones de unión basadas en hash del lado de la aplicación manualmente para resolver eso (o está reinventando el clúster de MySQL), lo que significa que termina con una gran cantidad de SQL que ya no es declarativo, pero que expresa la funcionalidad de SQL de una manera procedimental (por ejemplo, está utilizando instrucciones SELECT en bucles).

Está incurriendo en una gran latencia de red.

Normalmente, una consulta SQL se puede resolver localmente y el optimizador conoce los costos asociados con los accesos al disco local y resuelve la consulta de una manera que minimiza los costos para eso.

En un entorno fragmentado, las consultas se resuelven ejecutando accesos de valor clave a través de una red a varios nodos (con suerte con accesos de clave por lotes y no búsquedas de claves individuales por ida y vuelta) o empujando partes de la WHEREcláusula hacia los nodos donde pueden ser aplicado (que se llama 'condición pushdown'), o ambos.

Pero incluso en el mejor de los casos esto implica muchos más viajes de ida y vuelta en red que una situación local, y es más complicado. Especialmente porque el optimizador de MySQL no sabe nada sobre la latencia de la red (Ok, el clúster de MySQL está mejorando lentamente en eso, pero para MySQL vanilla fuera del clúster eso sigue siendo cierto).

Estás perdiendo mucho poder expresivo de SQL.

Ok, eso es probablemente menos importante, pero las restricciones de clave externa y otros mecanismos de SQL para la integridad de los datos no pueden abarcar múltiples fragmentos.

MySQL no tiene API, lo que permite consultas asincrónicas que están en funcionamiento.

Cuando los datos del mismo tipo residen en varios nodos (por ejemplo, datos de usuario en los nodos A, B y C), las consultas horizontales a menudo deben resolverse en todos estos nodos ("Buscar todas las cuentas de usuario que no han iniciado sesión durante 90 días o más"). El tiempo de acceso a los datos crece linealmente con el número de nodos, a menos que se puedan solicitar varios nodos en paralelo y los resultados se agreguen a medida que llegan ("Map-Reduce").

La condición previa para ello es una API de comunicación asincrónica, que no existe para MySQL en buen estado de funcionamiento. La alternativa es un montón de bifurcaciones y conexiones en los procesos del niño, que es visitar el mundo de chupar con un pase de temporada.


Una vez que comienza a fragmentar, la estructura de datos y la topología de la red se vuelven visibles como puntos de rendimiento para su aplicación. Para funcionar razonablemente bien, su aplicación debe ser consciente de estas cosas, y eso significa que realmente solo tiene sentido la fragmentación a nivel de la aplicación.

La pregunta es más si desea dividir automáticamente (determinar qué fila va a qué nodo mediante el hash de las claves primarias, por ejemplo) o si desea dividir funcionalmente de forma manual ("Las tablas relacionadas con la historia del usuario xyz van a este master, mientras que las tablas relacionadas abc y def van a ese master ").

La fragmentación funcional tiene la ventaja de que, si se hace correctamente, es invisible para la mayoría de los desarrolladores la mayor parte del tiempo, porque todas las tablas relacionadas con su historia de usuario estarán disponibles localmente. Eso les permite seguir beneficiándose del SQL declarativo el mayor tiempo posible, y también incurrirá en una menor latencia de red porque la cantidad de transferencias entre redes se mantiene mínima.

La fragmentación funcional tiene la desventaja de que no permite que una sola tabla sea más grande que una instancia y requiere la atención manual de un diseñador.

La fragmentación funcional tiene la ventaja de que se realiza con relativa facilidad en una base de código existente con una serie de cambios que no son demasiado grandes. http://Booking.com lo ha hecho varias veces en los últimos años y les ha funcionado bien.


Habiendo dicho todo eso, mirando su pregunta, creo que está haciendo las preguntas incorrectas, o estoy malinterpretando completamente su enunciado del problema.

Isotopp
fuente
2
Esta es una buena respuesta. Pero quiero señalar que la fragmentación solo es necesaria para aplicaciones de gran volumen y es probable que estén generando algún tipo de ingresos. Una aplicación de fragmentación de terceros se encargará de todas las preocupaciones que tenga con las uniones, las transacciones entre fragmentos, etc. Y si obtiene una buena, mantendrá la integridad de una base de datos "relacional". Otras aplicaciones, tiene razón, convertirán su base de datos en un par clave-valor y así frustrarán el propósito de SQL.
chantheman
3
Todavía no he encontrado una aplicación de fragmentación, comercial o no, que tenga éxito en ocultar el hecho de que los datos ahora están dispersos por la red y están sujetos a latencia o inconsistencia debido a la falta de esperas inducidas por la latencia. Si está fragmentando, su aplicación lo notará y requerirá cambios. También podrías tener el control de eso tú mismo. No hay una fórmula mágica, pero hay mucho aceite de serpiente.
Isotopp
1
Debería consultar dbShards. Se escala mejor que linealmente según el número de "fragmentos" que agregue. Necesitará muy pocos cambios, o ninguno, en el lado de la aplicación, y sí, su aplicación no conoce la diferencia. Simplemente envía y obtiene transacciones de la misma manera que lo haría con ODBC o JDBC. dbShards también permite sugerencias de fragmentos si desea tener más control sobre una transacción. Puede decirle a dbShards exactamente desde qué fragmento desea leer o escribir.
chantheman
1
@Gigala bueno, tampoco es necesario dedicar tiempo a componer una respuesta bien definida como esta, independientemente de la amplitud, pero me alegro de que se haya hecho, ya que esta respuesta ha demostrado ser útil para mí. No desanime a los usuarios a no "pensar fuera de la caja" al responder.
mewm
12
  1. Fragmentación de nivel de aplicación: dbShards es el único producto que conozco que hace "fragmentación consciente de la aplicación". Hay algunos buenos artículos en el sitio web. Solo por definición, la fragmentación consciente de la aplicación será más eficiente. Si una aplicación sabe exactamente a dónde ir con una transacción sin tener que buscarla o ser redirigida por un proxy, eso en sí mismo será más rápido. Y la velocidad es a menudo una de las principales preocupaciones, si no la única, cuando alguien está investigando la fragmentación.

  2. Algunas personas "fragmentan" con un proxy, pero en mi opinión, eso frustra el propósito de fragmentar. Simplemente está utilizando otro servidor para indicarle a sus transacciones dónde encontrar los datos o dónde almacenarlos. Con la fragmentación consciente de la aplicación, su aplicación sabe dónde ir por sí sola. Mucho más eficiente.

  3. Esto es lo mismo que el # 2 en realidad.

chantheman
fuente
¿Se está utilizando dbShards en producción en algún lugar? tampoco es de código abierto.
sheki
Además, el enfoque 2 y 3 pueden ser diferentes si el proxy busca en función de un hash en lugar de la base de datos o una tienda.
sheki
1
dbShards está en producción con una variedad de clientes, pero no, no es de código abierto. No creo que encuentre un buen producto de fragmentación de código abierto. Y sí, tiene razón en que un hash podría usarse como una búsqueda, pero en ese caso todavía tendrá que hacer una "parada" más para llevar su transacción a la base de datos. Es por eso que la fragmentación "consciente de la aplicación" casi siempre será más rápida.
chantheman
Pero como dije, si puede obtener una aplicación de fragmentación que mantenga la integridad de las relaciones, estará en buena forma. Menciono dbShards porque es el único que conozco que lo hace. Y como lo hace, escala sus velocidades de escritura y lectura linealmente. Agrega 4 "fragmentos" o divide su servidor MySQL en 4 y se ejecutará 4 veces más rápido.
chantheman
7

¿Conoce algún proyecto o herramienta interesante en esta área?

Varios proyectos nuevos en este espacio:

  • citusdata.com
  • spockproxy.sourceforge.net
  • github.com/twitter/gizzard/
btcbb
fuente
5

Shard-Query es una solución de fragmentación basada en OLAP para MySQL. Le permite definir una combinación de tablas fragmentadas y tablas sin fragmentar. Las tablas sin fragmentar (como las tablas de búsqueda) se pueden unir libremente a las tablas fragmentadas, y las tablas fragmentadas se pueden unir entre sí siempre que las tablas estén unidas por la clave de fragmentación (no hay fragmentos cruzados o autouniones que cruzan los límites de fragmentos). Al ser una solución OLAP, Shard-Query generalmente tiene tiempos de respuesta mínimos de 100 ms o menos, incluso para consultas simples, por lo que no funcionará para OLTP. Shard-Query está diseñado para analizar grandes conjuntos de datos en paralelo.

También existen soluciones de fragmentación OLTP para MySQL. Las soluciones de código cerrado incluyen ScaleDB , DBShards . La solución OLTP de código abierto incluye JetPants , Cubrid o Flock / Gizzard (infraestructura de Twitter).

Justin Swanhart
fuente
3

Nivel de aplicación, por supuesto.

El mejor enfoque que he encontrado en este libro.

MySQL de alto rendimiento http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064

Breve descripción: puede dividir sus datos en muchas partes y almacenar ~ 50 partes en cada servidor. Le ayudará a evitar el segundo mayor problema de la fragmentación: el reequilibrio. Simplemente mueva algunos de ellos al nuevo servidor y todo estará bien :)

Te recomiendo encarecidamente que lo compres y leas la parte de "escalamiento de mysql".

Andrey Frolov
fuente
El libro que recomendó tiene 8 años ... ¿cubre la fragmentación relevante para las tecnologías actuales?
raffian
1
Cubre algunos enfoques básicos para escalar mysql. AFAIK, nada cambió al escalar mysql. Las mismas técnicas de fragmentación y replicación a nivel de aplicación se utilizan ampliamente en la actualidad.
Andrey Frolov
Podría estar equivocado, pero he estado investigando mucho sobre esto durante la última semana y parece que mySQL en sí mismo ha realizado muchos cambios en los últimos 8 años, especialmente en lo que respecta al particionamiento y el almacenamiento en caché. Hay una nueva versión que salió este año: amazon.com/High-Performance-MySQL-Optimization-Replication/dp/… No la he leído pero creo que cubre los nuevos modelos de replicación disponibles.
NateDSaint
4
Libros ... ¿por qué no explicarlo aquí?
DDD
2

A partir de 2018, parece haber una solución nativa de MySql para eso. En realidad, hay al menos 2: InnoDB Cluster y NDB Cluster (hay una versión comercial y una comunitaria).

Dado que la mayoría de las personas que utilizan MySql community edition están más familiarizadas con el motor InnoDB, esto es lo que debería explorarse como primera prioridad. Admite replicación y particionamiento / fragmentación de fábrica y se basa en MySql Router para diferentes opciones de enrutamiento / equilibrio de carga.

La sintaxis para la creación de sus tablas debería cambiar, por ejemplo:

    CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );

(este es solo uno de los cuatro tipos de particiones )

Una limitación muy importante:

Las claves foráneas InnoDB y el particionamiento MySQL no son compatibles. Las tablas de InnoDB particionadas no pueden tener referencias de clave externa, ni pueden tener columnas referenciadas por claves externas. Las tablas InnoDB que tienen o son referenciadas por claves externas no se pueden particionar.

yuranos
fuente
Tenga en cuenta que PARTITION BY HASH(YEAR...)escaneará todas las particiones si tiene un rango de fechas. ¡Qué asco!
Rick James