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 WHERE
clá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.
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.
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.
Esto es lo mismo que el # 2 en realidad.
fuente
Varios proyectos nuevos en este espacio:
github.com/twitter/gizzard/fuente
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).
fuente
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".
fuente
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:
fuente
PARTITION BY HASH(YEAR...)
escaneará todas las particiones si tiene un rango de fechas. ¡Qué asco!