Разделение таблиц в MySQL. Хорошая практика?

14

Я начал работать над существующим проектом, и предыдущий разработчик разделил таблицу на 10 отдельных таблиц с одинаковыми схемами, но разными данными.

Таблицы выглядят так:

[tableName_0]
[tableName_1]
[tableName_2]
[tableName_3]
[tableName_4]
[tableName_5]
[tableName_6]
[tableName_7]
[tableName_8]
[tableName_9]

Первичный ключ - это целочисленное idполе. Приложение использует алгоритм хеширования ( idмод 10), чтобы знать, к какой таблице обращаться при выполнении поиска. Например, id= 10 приведет к [tableName_0].

В совокупности таблицы имеют, вероятно, 100 000 строк, и темпы роста относительно низкие.

Итак, мой вопрос заключается в том, является ли это жизнеспособным решением или даже если это хорошая практика в любой ситуации. Моя теория состоит в том, чтобы подтолкнуть их к объединению, так как это облегчит задачу UNIONи т. Д. Основным недостатком является изменение всего кода приложения и того, стоит ли оно того в долгосрочной перспективе.

Розовый грейпфрут
источник

Ответы:

16

Я думаю, что все слишком усложняют это. Ключевым моментом здесь является:

В совокупности таблицы имеют, вероятно, 100 000 строк, и темпы роста относительно низкие.

Это кусок пирога для любой РСУБД. Перейдите к одной таблице, правильно ее проиндексируйте и сочтите ее решенной.

Вам не нужно рассматривать разделение, «домашнее» или иное, пока вы не начнете обрабатывать очень большие объемы данных - подумайте о миллиардах строк и более.

Ник Чаммас
источник
3

Вы можете использовать таблицы слияния, однако они более устарели из версий 4.x. Учитывая, что ваше приложение разбито на разделы вручную, так как оно либо а) вы используете действительно старую версию, либо б) первоначальный разработчик не знал о разделах таблицы.

Короче говоря, если вы используете 5.1+, вы можете позволить MySQL сделать это для вас. См. Http://dev.mysql.com/doc/refman/5.1/ru/partitioning.html. Если вы используете версию 5.5, вам следует проверить эти конкретные документы, поскольку вы найдете некоторые различия.

Есть много преимуществ для разделения. Однако это действительно зависит от имеющегося набора данных, шаблонов доступа и способа его индексации. Кроме того, имейте в виду, что мои следующие комментарии относятся к разделу разделов mysql 5+, а НЕ к более ранним таблицам mysql Merge; хотя они иногда обсуждаются с точки зрения разделов.

Несколько примеров:

  • Прямое ведение (или хеширование) на основе часто используемого ключа поиска. Если вы почти всегда просматриваете первичный или другой уникальный ключ, то mysql может сократить пространство поиска в зависимости от того, сколько у вас разделов. Однако обратите внимание, что это может быть вредно, если вы разбиваете по одному ключу, а затем часто выполняете поиск по другому ключу. Если вы выполняете поиск по ключу, по которому данные не разбиты, то он должен выполнить БОЛЬШЕ поисков при поиске (по одному на каждый раздел, откровенно говоря, он не знает, где находятся данные)
  • Рассмотрим ситуации, когда у вас есть временной набор записей, который увеличивается по дате, и вы периодически сокращаете предыдущий месяц. Если вы разбиваете по дате, вы можете просто удалить раздел, который так же быстр, как и таблица, независимо от ее размера. Если бы вы должны были обрезать такую ​​таблицу по датам, вам нужно было бы выполнить один или несколько запросов DELETE, где каждая отдельная строка удаляется. Недостатком этого является то, что mysql не создает автоматически новые разделы, как только вы достигли максимальной даты, которую вы учли в этом сценарии; вам нужны дополнительные сценарии обслуживания, созданные с вашей стороны, чтобы добавлять разделы по мере необходимости.
  • Если вы используете myisam, проверки и восстановление выполняются намного быстрее. Рассмотрим таблицу myisam 100G. Если вы хотите восстановить разбитую таблицу, вам потребуется как минимум около 100 ГБ свободного места на диске. Если он был разбит на 10 разных блоков одинакового размера, вам потребуется всего 10 ГБ места (и меньше ключа key_sort_buffer для быстрого восстановления); но нужно будет сделать итерацию для каждого раздела.

Итак, в целом, общий подход к разделению таблиц может предложить много преимуществ. Однако это не волшебная палочка, которую нужно применять вслепую, не обращая внимания на шаблоны доступа и то, как именно вы разбиваете.

Я мог бы представить себе ситуации, когда желаемое разбиение зависит от конкретного приложения и было бы лучше, если бы эта логика находилась на уровне приложения. Однако, учитывая ваше прямое описание модуля 10, это не похоже на такой случай.

РЕДАКТИРОВАТЬ

При написании моего описания я забыл, что вы указали, что ваша таблица состоит из 100 тысяч строк. С полной схемой вашей таблицы и средней длиной строки трудно сказать наверняка, но в целом это звучит среднего размера даже для скромного оборудования. В то же время, если это не вызывает проблем, как сейчас или в обозримом будущем, не тратьте время и вносите риск, меняя его.

atxdba
источник
3

То, что предыдущий разработчик сделал для вас, это построение собственной реализации разбиения по хэшам. MySQL буквально поддерживает это изначально из MySQL 5.1:

http://dev.mysql.com/doc/refman/5.1/en/partitioning-hash.html

Я не могу придумать вескую причину, поэтому реализуйте свой собственный раздел за хешем, а не полагайтесь на собственную версию [1]. Выполнение изменений схемы будет кошмаром.

Я также редко рекомендую разделение за хешем (нативная реализация). Я думаю, что было бы полезно, если бы вы могли использовать его для параллельного поиска на каждом из разделов одновременно (что MySQL не будет делать). Если вам нужно выполнить поиск по нескольким разделам, описанная вами схема часто будет намного медленнее.

[1] Тем не менее, для некоторых других типов разбиения может иметь смысл развернуть собственное разбиение. MySQL заставляет вас сделать ключ раздела частью вашего первичного ключа и всех уникальных индексов.

Морган Токер
источник
2

В ответ на вопрос:

является ли это жизнеспособным решением

ИМХО, это похоже на ненужные накладные расходы. Вы можете просто правильно проиндексировать и разбить одну таблицу на части, если в описании нет другой информации.

В ответ на вопрос:

... если это хорошая практика в любой ситуации

ИМХО, вертикальный шардинг может иметь смысл в зависимости от контекста. Когда я вижу это, это обычно в какой-то форме журнала. Давайте представим, что мы используем это для журналов веб-сервера, и мы хотим разделить по месяцам. Вместо того, чтобы изменять существующую таблицу каждый день, мы могли бы создавать новую таблицу каждый день и записывать строки в эту таблицу.

Например, представьте, что таблица веб-журнала может иметь вид:

datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
uri VARCHAR(1024),
host VARCHAR(255),
user_agent VARCHAR(255),
etc...

Ваше решение создает таблицы по мере необходимости в базе данных блога:

weblogs.20120301
weblogs.20120302
weblogs.20120303

и т.п.

Таким образом, данные остаются поддерживаемыми и доступными для поиска. Добыча становится нормальным периодическим процессом. Непрерывные операции не блокируются операциями со старыми данными.

В представленном сценарии вы все равно заблокированы в структуре, так почему бы не использовать одну таблицу, оптимизированную для этой цели? Хранение строк на основе алгоритма кажется отрывочным и подверженным ошибкам.

randomx
источник
0

Если запрос нацелен на огромные данные, разделение данных по условиям запроса приведет к заметному улучшению производительности. Но такое разделение, как вы видели, поднимает некоторые проблемы программирования.

Таким образом, вопрос заключается в следующем: это разделение стоит для производительности, или это вредит производительности?

Если у вас есть транзакция, которой необходимо заблокировать несколько строк в нескольких таблицах, и в ней есть проблемы (например, тупик или тайм-аут транзакции), вы можете объединить их в одну таблицу и переписать SQL для устранения проблем.

Когда я думал о том, следует ли разбивать таблицу, я обычно рассматривал компромисс между повышением производительности и сложностью программирования.

В вашей ситуации модификация существующего кода может быть долгосрочным решением, облегчающим поддержку кода. Я бы предложил попробовать метапрограммирование. Например, используя StringTemplate для динамического генерирования SQL. Мне нравится генерировать SQL из движка метапрограммирования, если изменение существующего кода слишком сложно.

Майк Лю
источник
0

Когда вам нужно хранить файлы в таблице, использовать эту методологию помогает экспорт, восстановление и восстановление.

У меня есть таблицы с> 30 Гб, разделенные на 10 таблиц. Эти таблицы имеют только ID - BLOB и мне легко хранить. И я использую MyISAM для сохранения буфера INNODB.

Марсело Автобус
источник