Короткий ответ
Шардирование по ключу (hash) даёт равномерное распределение нагрузки записи, но делает диапазонные запросы и перебалансировку сложнее; шардирование по диапазону (range) упрощает диапазонные запросы и добавление новых шардов, но рискует создавать «горячие» шарды при неравномерном распределении ключей; в обоих случаях транзакции и JOIN между шардами перестают быть атомарными и эффективными на уровне одной СУБД.
Как это работает подробнее
При шардировании данные одной логической таблицы физически распределяются по нескольким независимым базам на основе ключа шардирования; обычная транзакция и JOIN работают только внутри одного шарда — операции между шардами требуют распределённой транзакции или перепроектирования логики так, чтобы связанные данные оказывались в одном шарде (co-location).
Сравнение
- Компромисс. Решение зависит от того, какие запросы доминируют (точечные по ключу или диапазонные/аналитические), темпа роста и приемлемости сложности перебалансировки; hash-шардирование проще держать равномерным, но диапазонные запросы и resharding обычно дороже, чем при range-шардировании — нужно явно обсуждать, какие cross-shard сценарии бизнес готов обслуживать отдельным (более медленным/асинхронным) путём.
Пример кода
Сценарий: мультитенантный SaaS, 10 000 клиентов, данные растут неравномерно.
Вариант A (hash по tenant_id): равномерная нагрузка записи, но отчёт "все платежи за месяц по всем клиентам"
требует запроса ко всем шардам и слияния на стороне приложения.
Вариант B (range по дате регистрации клиента): новые клиенты концентрируются в последнем шарде
("горячий" шард), но поддержка старых клиентов стабильна.
Решение команды: hash по tenant_id + co-location всех таблиц клиента в одном шарде,
аналитика — через отдельный ETL в DWH, а не прямые cross-shard JOIN.Что использовать на практике
- Практика. Ключ шардирования выбирают так, чтобы большинство транзакционных операций и JOIN укладывались в один шард — например, шардировать по tenant_id, если почти все запросы скоуплены одним клиентом; для агрегации по всем шардам обычно используют отдельный путь — ETL в аналитическое хранилище, а не прямые cross-shard JOIN в OLTP-пути.
Подводные камни
- Ошибка. Выбирают ключ шардирования по техническому удобству, не учитывая реальные паттерны запросов, что приводит к постоянным cross-shard операциям; откладывают проектирование шардирования до момента, когда миграция требует болезненного простоя или сложного дуального write.