К словарю | К разделу Fundamentals
Partitioning — разделение большого набора данных на части, чтобы упростить
хранение, обработку, обслуживание или выполнение запросов.
Sharding — частный случай partitioning, при котором части данных
распределяются между разными физическими или логическими узлами. Обычно
sharding используют для горизонтального масштабирования базы данных или
хранилища.
Коротко: partitioning отвечает на вопрос «как разделить данные», а sharding —
«как распределить эти части по узлам».
Зачем это нужно
Partitioning и sharding применяют, когда один узел или одна таблица становятся
узким местом.
Основные причины:
- объём данных слишком большой для удобного хранения и обслуживания;
- запросы становятся медленными из-за размера таблиц или индексов;
- один сервер не выдерживает нагрузку на чтение или запись;
- нужно ограничить blast radius отказа;
- требуется масштабировать систему горизонтально;
- нужно изолировать данные по клиентам, регионам или временным диапазонам.
Разделение данных само по себе не ускоряет систему автоматически. Оно помогает,
если запросы и операции обслуживания действительно могут работать с меньшей
частью данных или распределяться между узлами.
Partitioning внутри одной базы
Partitioning может происходить внутри одного инстанса базы данных. Например,
большая таблица заказов делится на партиции по месяцу создания заказа.
Типичные варианты:
- range partitioning — данные делятся по диапазонам, например по дате,
идентификатору или сумме; - list partitioning — данные делятся по фиксированным значениям, например
по региону или типу клиента; - hash partitioning — партиция выбирается по hash от ключа;
- composite partitioning — комбинирует несколько подходов, например range
по дате и hash внутри диапазона.
Преимущество partitioning внутри одной базы в том, что приложение часто может
работать почти так же, как с обычной таблицей. База сама выбирает нужные
партиции через partition pruning, если запрос содержит подходящие условия.
Sharding между узлами
При sharding данные распределяются между несколькими шардами. Каждый шард
обычно хранит только часть данных и обслуживает часть нагрузки.
Пример: пользователи распределяются по shard key user_id. Пользователь 123
попадает на один шард, пользователь 456 — на другой. Запросы по конкретному
user_id можно направлять сразу на нужный узел.
Sharding может быть:
- application-level — приложение само решает, в какой шард идти;
- database-level — распределение выполняет сама СУБД или кластерный слой;
- proxy-based — отдельный router или proxy принимает запрос и направляет его
в нужный шард.
Чем больше логики sharding находится в приложении, тем больше контроля, но и
тем выше сложность кода, миграций и эксплуатации.
Shard key
Shard key — поле или набор полей, по которым система решает, где хранить
запись.
Хороший shard key должен:
- равномерно распределять данные и нагрузку;
- часто присутствовать в запросах;
- минимизировать cross-shard операции;
- быть стабильным, чтобы данные не приходилось часто переносить;
- учитывать будущий рост системы.
Плохой shard key создаёт hot shard: один узел получает непропорционально много
данных или запросов. Например, sharding по региону может быть плохим, если один
регион даёт 80% нагрузки.
Основные сложности
Sharding решает проблему масштаба, но добавляет распределённую сложность.
Типичные проблемы:
- cross-shard queries — запрос должен обращаться к нескольким шардам;
- distributed transactions — транзакции между шардами сложнее и дороже;
- rebalancing — при добавлении узлов данные нужно перераспределять;
- hot shards — часть шардов перегружена сильнее остальных;
- global secondary indexes — индексы по полям, не совпадающим с shard key,
становятся сложнее; - unique constraints — глобальная уникальность требует отдельного механизма;
- joins — соединения данных между шардами могут быть дорогими;
- backup и restore — нужно согласованно работать с несколькими узлами;
- observability — инциденты сложнее расследовать без привязки запросов к
шардам.
Из-за этих сложностей sharding обычно не стоит вводить заранее. Часто сначала
используют индексы, оптимизацию запросов, read replicas, vertical scaling,
кеширование и partitioning внутри базы.
Range vs hash sharding
| Подход | Как работает | Плюсы | Минусы |
|---|---|---|---|
| Range sharding | Диапазоны ключей размещаются на разных шардах | Хорош для range queries, проще понимать расположение данных | Может создавать hot shard на новых или популярных диапазонах |
| Hash sharding | Шард выбирается по hash от ключа | Лучше распределяет нагрузку | Range queries часто требуют обращения к нескольким шардам |
Если нужны запросы по временным диапазонам, range partitioning может быть
удобным. Если главная цель — равномерное распределение точечных запросов, hash
sharding часто работает лучше.
Rebalancing
Rebalancing — перераспределение данных между шардами при изменении
нагрузки, добавлении узлов или исправлении перекоса.
Простая схема hash(key) % N плохо переносит изменение количества шардов:
при изменении N большинство ключей переедет. Поэтому часто используют
consistent hashing, virtual nodes или отдельную таблицу маршрутизации, где
диапазоны ключей явно назначены шардам.
При rebalancing важно учитывать:
- как переносить данные без длительного downtime;
- как синхронизировать новые записи во время миграции;
- как переключать routing;
- как откатываться при ошибке;
- как проверять полноту и консистентность переноса.
Что важно сказать на собеседовании
Partitioning и sharding нужны не «для скорости вообще», а для управления
размером данных, нагрузкой и эксплуатацией.
Хороший ответ должен включать:
- различие между partitioning и sharding;
- примеры range, list и hash partitioning;
- роль shard key и риск hot shards;
- цену cross-shard запросов и распределённых транзакций;
- мысль, что sharding — дорогой архитектурный шаг, который стоит делать после
более простых оптимизаций или при понятной необходимости горизонтального
масштабирования.