Как стать автором
Обновить

Оптимизация реляционных баз данных без даунтайма на примере самой нагруженной БД в Badoo

Время на прочтение9 мин
Количество просмотров26K
Всего голосов 65: ↑65 и ↓0+65
Комментарии22

Комментарии 22

Так а как вы в итоге поддерживаете уникальные индексы? Вы просто убрали все «лишние» колонки из основного инстанса и перенесли их в дополнительные? Или как? Может, я невнимательно читал статью, но я этот момент не понял.
Ключ по которому мы разбивали таблицу уже был во всех уникальных индексах, включая PK. Поэтому уникальность никак не пострадала, и так-же поддерживается средствами MySQL.
То есть, у вас теперь во всех таблицах есть все колонки, по которым проверяется уникальность? То есть, вы задублировали эти данные на всех кусочках, я правильно понимаю? А как теперь осуществляется регистрация пользователя? Что происходит, если в один кусочек данные вставились, а в другие кусочки — нет?
Представь уникальный составной ключ (A, B, C) причем уникальных значений в колонке A всего, скажем, дюжина. Данные в таблицы с таким ключем разбиваем на дюжину таблиц с ключем (B, C). Ничего в итоге не дублируется и уникальность по прежнему поддерживается
А, понял :). Прикольно.
Обжимайте размер записи в таблицах с большим количеством записей, как только возможно. Размер записи — ключевая вещь при Key Lookup, Range Seek, и основа компактности не только страниц с данными, но и индексов (втч с included-колонками).

Если поле можно сделать varchar вместо nvarchar — всегда делайте это. Если date вместо datetime — тоже. ПК в справочниках и значения в таблицах, которые гарантированно помещаются в small- или tinyint, нужно делать именно такими. NOT NULL значения нужно указывать явно. Миллионы FK-ссылок на короткий ПК сэкономят вам много места, а в самом справочнике больше страниц поместится в память.

Для таблиц, часто использующихся в связывании иерархии бизнес-сущностей, и несущих на себе еще и пользовательскую информацию (например UserID | RoleID | DateCreated | Description), создавайте параллельный уникальный индекс по ПК-колонкам и с теми Included-колонками, которые вам нужны для этих связок — по сути создастся усеченная копия основной таблицы с короткими записями, которая будет работать гораздо быстрее
Вы используете InnoDB и Foreign Keys? Я слышал Foreign Keys влияют на производительность отрицательно, так ли это?
Foreign Keys используются редко, только в не highload частях. В UDB их конечно нету.
InnoDB — наш основной движок. Ещё были эксперименты с MyRocks, но он не взлетел.
FK проверяются только при INSERT/DELETE, поэтому, если их доля мала, то ничего страшного. Хотя, если можно обойтись без них — лучше обойтись :)
Если вас не интересует целостность данных можно значительно ускорить любую БД.
Сильно зависит от структуры БД и как она используется, требований к данным.

Многие живут вообще на NoSQL-подобных решениях и ничего, как-то выживают без FK :)
Тут каждый сам решает что важнее: наличие руля и тормозов или турбины и интеркулера.
Интересно, а какая у вас версия MySQL используется?
UDB работает на 5.5 так как мы активно используем HandlerSocket который не поддерживаться в следующих версиях. Сейчас тестируем 8.0 c memcached и x protocol как замену HandlerSocket.
На остальных бд у нас 5.7
А для чего используете? Просто чтобы избежать оверхеда SQL-интерфейса?
Да. У нас много мелких запросов вида «Дай юзера по id». Недавний нагрузочный тест показал что если делать эти запросы на чистом sql то CPU load сервера возрастает до 70% — 85% против 30% — 35% с HS
А версию от Percona не тестировали?
У нас она и стоит.
Спасибо за статью.

«или альтером слейва с последующей сменой их местами» — можно рассказать ваши мысли про этот способ? Пробовали? Почему на нем не остановились? По идее самый привлекательный способ, какие там подводные камни?

У нас сейчас есть такая же задача, смотрим неспешно именно в сторону master-slave и их сменой.
Это отличный способ, но чтобы им воспользоваться изменения должны быть обратно совместимы с запросами в мастер (insert, update, delete должны корректно проходить на изменённом слейве).
Таким способом можно добавить или удалить индекс, добавить колонку с default, расширить тип данных (например с int на bigint) и тд.
К сожалению наши изменения под этот формат не подходили.
> insert, update, delete должны корректно проходить на изменённом слейве
это по идее легко обеспечивается на уровне кода для всех перечисленных кейсов естественным образом. Пока изменения не вступили в силу — код о них не знает.
Остается по сути только DELETE? Удалять колонку можно когда она перестает использоваться кодом. Вроде тоже не должно быть проблемы.
Остальные операции типа MOVE, это по сути INSERT -> DELETE, их все равно придется на уровне кода обеспечивать.

У вас было что-то специфическое, что запросы переставали быть обратно совместимы? Или я где-то не вижу рояля в кустах?
Да. У нас было изменение типа данных колонки с varchar на binary с меньшей размерностью (данные тоже сжимались).
А также, как я писал выше, разделение одной таблицы на несколько.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий