Ответ 1
Лучший подход для шейдинга таблиц MySQL не делать этого, если это совершенно неизбежно.
Когда вы пишете приложение, вы обычно делаете это так, чтобы максимизировать скорость, скорость разработчика. Вы оптимизируете время ожидания (время до готовности ответа) или пропускную способность (количество ответов на единицу времени) только при необходимости.
Вы разделяете и затем назначаете разделы на разные хосты (= shard) только тогда, когда сумма всех этих разделов больше не подходит для одного экземпляра сервера базы данных - причина того, что он либо пишет, либо читает.
Случай записи: либо) частота записи перегружает эти серверные диски на постоянной основе, либо b) происходит слишком много операций записи, что репликация постоянно задерживается в этой иерархии репликации.
Случай чтения для осколков - это когда размер данных настолько велик, что рабочий набор его больше не вписывается в память, а данные считывают начало попадания на диск вместо того, чтобы обслуживать его большую часть времени.
Только когда у вас есть, вы сделаете это.
В момент, когда вы осколки, вы платите за это несколькими способами:
Большая часть вашего SQL больше не является декларативной.
Обычно в SQL вы сообщаете базе данных, какие данные вы хотите, и оставляете ее оптимизатору, чтобы превратить эту спецификацию в программу доступа к данным. Это хорошо, потому что он является гибким, и потому, что написание этих программ доступа к данным - это скучная работа, которая наносит вред скорости.
С закрытой средой вы, вероятно, присоединяетесь к таблице на node A против данных на node B или у вас есть таблица больше, чем node, на узлах A и B и соединяются с ней данными против данные, находящиеся на node B и C. Вы начинаете вручную писать разрешения на основе хэш-хэшей на стороне приложения, чтобы решить эту проблему (или вы повторно изобретаете кластер MySQL), а это значит, что вы получаете много SQL, которые больше не декларативный, но выражает функциональность SQL процедурным способом (например, вы используете инструкции SELECT в циклах).
У вас много задержек в сети.
Обычно запрос SQL может быть разрешен локально, и оптимизатор знает о расходах, связанных с локальными обращениями к диску, и разрешает запрос таким образом, чтобы минимизировать затраты для этого.
В закрытой среде запросы разрешаются либо запуском доступа к ключевым значениям по сети, либо несколькими узлами (надеюсь, с доступными ключами доступа, а не с помощью отдельных ключевых поисков за один раз) или путем нажатия частей предложения WHERE
onward к узлам, где они могут быть применены (что называется "нажатием условия" ), или и тем, и другим.
Но даже в лучших случаях это связано со многими другими сетевыми поездками, что локальная ситуация, и это сложнее. Тем более, что оптимизатор MySQL ничего не знает о латентности сети вообще (ну, кластер MySQL постепенно становится лучше, но для ванильного MySQL вне кластера, который по-прежнему верен).
Вы теряете много выразительных возможностей SQL.
Хорошо, это, вероятно, менее важно, но ограничения внешнего ключа и другие механизмы SQL для целостности данных не способны охватывать несколько осколков.
MySQL не имеет API, который позволяет асинхронные запросы, находящиеся в рабочем состоянии.
Если данные одного и того же типа находятся на нескольких узлах (например, пользовательские данные на узлах A, B и C), горизонтальные запросы часто необходимо разрешать для всех этих узлов ( "Найти все учетные записи пользователей, которые не вошли в систему в течение 90 дней или более" ). Время доступа к данным растет линейно с количеством узлов, если несколько узлов могут задаваться параллельно, а результаты агрегируются по мере их поступления ( "Map-Reduce" ).
Предпосылкой для этого является асинхронный коммуникационный API, который не существует для MySQL в хорошей рабочей форме. Альтернативой является много разветвлений и связей в дочерних процессах, которые посещают мир сосать на сезонный проезд.
Как только вы начнете очерчивать, структура данных и топология сети становятся видимыми, поскольку производительность указывает на ваше приложение. Чтобы сделать это достаточно хорошо, ваше приложение должно знать об этих вещах, а это означает, что действительно имеет смысл только оверлей на уровне приложений.
Вопрос больше, если вы хотите автоматическое очертание (определение того, какая строка входит в число node путем хэширования первичных ключей, например) или если вы хотите разделить функционально вручную ( "Таблицы, связанные с xyz пользовательский рассказ перейдите к этому хозяину, в то время как таблицы abc и def связаны с этим мастером" ).
Функциональное очертание имеет то преимущество, что, если все сделано правильно, оно невидимо для большинства разработчиков большую часть времени, потому что все таблицы, относящиеся к их истории пользователей, будут доступны локально. Это позволяет им по-прежнему извлекать выгоду из декларативного SQL как можно дольше, а также будет иметь меньшую задержку в сети, поскольку количество межсетевых передач поддерживается минимально.
Функциональный осколок имеет тот недостаток, что он не позволяет какой-либо отдельной таблице быть больше одного экземпляра, и требует ручного внимания дизайнера.
Функциональное очертание имеет то преимущество, что его относительно легко сделать с существующей кодовой базой с рядом изменений, которые не слишком велики. http://Booking.com сделал это несколько раз за последние годы, и это сработало для них.
Сказав все это, глядя на ваш вопрос, я верю, что вы задаете неправильные вопросы, или я полностью не понимаю ваше выражение о проблеме.