Лучший подход к сегментированию таблиц MySQL - не делать этого, если это не является совершенно неизбежным.
Когда вы пишете приложение, вы обычно хотите сделать это таким образом, чтобы максимизировать скорость, скорость разработчика. Вы оптимизируете задержку (время до того, как ответ будет готов) или пропускную способность (количество ответов в единицу времени) только при необходимости.
Вы разделяете, а затем назначаете разделы различным хостам (= сегменту) только тогда, когда сумма всех этих разделов больше не умещается на одном экземпляре сервера базы данных - причина этого либо в записи, либо в чтении.
Случай записи: а) частота операций записи приводит к постоянной перегрузке дисков этого сервера или б) выполняется слишком много операций записи, поэтому репликация постоянно отстает в этой иерархии репликации.
Случай чтения для сегментирования - это когда размер данных настолько велик, что их рабочий набор больше не помещается в память, а считываемые данные начинают попадать на диск вместо того, чтобы большую часть времени обслуживаться из памяти.
Вы делаете это только тогда, когда вам нужно осколить.
В момент создания шарда вы платите за это несколькими способами:
Большая часть вашего SQL больше не декларативна.
Обычно в SQL вы сообщаете базе данных, какие данные вам нужны, и оставляете оптимизатору превратить эту спецификацию в программу доступа к данным. Это хорошо, потому что это гибко, и потому что написание этих программ доступа к данным - скучная работа, которая вредит скорости.
В сегментированной среде вы, вероятно, объединяете таблицу на узле A с данными на узле B, или у вас есть таблица размером больше, чем узел, на узлах A и B, и вы объединяете данные из нее с данными, которые находятся на узлах B и C. Вы начинаете писать разрешения соединения на основе хэшей на стороне приложения вручную, чтобы решить эту проблему (или вы заново изобретаете кластер MySQL), что означает, что вы получаете много SQL, который больше не декларативен, но выражает функциональность SQL процедурным способом (например, вы используете операторы SELECT в циклах).
У вас большая задержка в сети.
Обычно SQL-запрос может быть разрешен локально, и оптимизатор знает о затратах, связанных с доступом к локальному диску, и разрешает запрос таким образом, чтобы минимизировать затраты на это.
В сегментированной среде запросы разрешаются либо путем выполнения доступов по ключу по сети к нескольким узлам (надеюсь, с пакетным доступом по ключам, а не индивидуальным поиском ключей за круговой обход), либо путем передачи частей WHERE
предложения на узлы, где они могут быть примененным (это называется «выталкивание условия») или и то, и другое.
Но даже в лучшем случае это включает в себя намного больше сетевых обходов, чем локальная ситуация, и это более сложно. Тем более, что оптимизатор MySQL вообще ничего не знает о задержках в сети (хорошо, кластер MySQL постепенно улучшается в этом, но для ванильного MySQL вне кластера это все еще верно).
Вы теряете выразительную силу SQL.
Хорошо, это, вероятно, менее важно, но ограничения внешнего ключа и другие механизмы SQL для целостности данных не могут охватывать несколько сегментов.
MySQL не имеет API, который разрешает асинхронные запросы в рабочем состоянии.
Когда данные одного и того же типа находятся на нескольких узлах (например, пользовательские данные на узлах A, B и C), горизонтальные запросы часто необходимо разрешать для всех этих узлов («Найти все учетные записи пользователей, которые не входили в систему в течение 90 дней. или больше"). Время доступа к данным растет линейно с количеством узлов, если только несколько узлов не могут быть запрошены параллельно, а результаты агрегированы по мере их поступления («Map-Reduce»).
Предварительным условием для этого является асинхронный коммуникационный API, который не существует для MySQL в хорошей рабочей форме. Альтернативой является множество разветвлений и соединений в дочерних процессах, которые посещают мир suck по сезонному абонементу.
Как только вы начнете сегментирование, структура данных и топология сети станут видимыми как точки производительности вашего приложения. Чтобы работать достаточно хорошо, ваше приложение должно знать об этих вещах, а это означает, что в действительности имеет смысл только сегментирование на уровне приложения.
Вопрос в том, хотите ли вы автоматически сегментировать (определение того, какая строка входит в какой узел, например, путем хеширования первичных ключей) или если вы хотите функционально разделить вручную («Таблицы, относящиеся к пользовательской истории xyz, переходят к этому master, а таблицы, связанные с abc и def, переходят к этому мастеру ").
Функциональное сегментирование имеет то преимущество, что, если все сделано правильно, большую часть времени оно невидимо для большинства разработчиков, потому что все таблицы, связанные с их пользовательской историей, будут доступны локально. Это позволяет им по-прежнему извлекать выгоду из декларативного SQL как можно дольше, а также снижает задержку в сети, поскольку количество межсетевых передач остается минимальным.
Функциональное сегментирование имеет тот недостаток, что он не позволяет отдельной таблице быть больше одного экземпляра и требует ручного внимания дизайнера.
Функциональное сегментирование имеет то преимущество, что оно относительно легко выполняется с существующей кодовой базой с некоторыми изменениями, которые не являются слишком большими. http://Booking.com делал это несколько раз за последние годы, и у них это хорошо сработало.
Сказав все это, глядя на ваш вопрос, я действительно считаю, что вы задаете неправильные вопросы, или я полностью не понимаю вашу постановку проблемы.
Шардинг на уровне приложений: dbShards - единственный известный мне продукт, который выполняет «сегментирование с учетом приложений». На сайте есть несколько хороших статей. По определению, сегментирование с учетом приложений будет более эффективным. Если приложение точно знает, куда направить транзакцию, не просматривая ее или не перенаправляясь через прокси, это само по себе будет быстрее. И скорость часто является одной из основных, если не единственной проблемой, когда кто-то изучает шардинг.
Некоторые люди «шардируют» через прокси, но, на мой взгляд, это лишает смысла шардинг. Вы просто используете другой сервер, чтобы сообщить своим транзакциям, где искать данные или где их хранить. Благодаря шардингу, учитывающему приложение, ваше приложение само знает, куда двигаться. Намного эффективнее.
На самом деле это то же самое, что и №2.
источник
Несколько новых проектов в этом пространстве:
github.com/twitter/gizzard/источник
Shard-Query - это решение для шардинга MySQL на основе OLAP. Он позволяет вам определять комбинацию сегментированных таблиц и нечетких таблиц. Нечеткие таблицы (например, таблицы поиска) могут свободно присоединяться к сегментированным таблицам, а сегментированные таблицы могут быть объединены друг с другом, пока таблицы соединены ключом сегментирования (нет перекрестных сегментов или самостоятельных соединений, пересекающих границы сегментов). Будучи решением OLAP, Shard-Query обычно имеет минимальное время ответа 100 мс или меньше, даже для простых запросов, поэтому он не будет работать для OLTP. Shard-Query предназначен для параллельного анализа больших наборов данных.
Решения для сегментирования OLTP существуют и для MySQL. Решения с закрытым исходным кодом включают ScaleDB , DBShards . Решение OLTP с открытым исходным кодом включает JetPants , Cubrid или Flock / Gizzard (инфраструктура Twitter).
источник
Уровень приложения, конечно.
Лучший подход, который я когда-либо видел в этой книге
Высокопроизводительный MySQL http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064
Краткое описание: вы можете разделить свои данные на несколько частей и хранить ~ 50 частей на каждом сервере. Это поможет вам избежать второй по значимости проблемы шардинга - перебалансировки. Просто перенесите некоторые из них на новый сервер и все будет хорошо :)
Я настоятельно рекомендую вам купить его и прочитать часть "масштабирование mysql".
источник
По состоянию на 2018 год, похоже, для этого существует собственное решение MySql. На самом деле их как минимум 2 - InnoDB Cluster и NDB Cluster (есть коммерческая и общественная версия).
Поскольку большинство людей, использующих версию сообщества MySql, более знакомы с движком InnoDB, это то, что следует изучить в первую очередь. Он поддерживает репликацию и разбиение / сегментирование из коробки и основан на MySql Router для различных вариантов маршрутизации / балансировки нагрузки.
Необходимо изменить синтаксис для создания таблиц, например:
CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );
(это только один из четырех типов разбиения )
Одно очень важное ограничение:
источник
PARTITION BY HASH(YEAR...)
будут сканироваться все разделы, если у вас есть диапазон дат. Фу.