Что является более эффективным: несколько таблиц MySQL или одна большая таблица? - PullRequest
91 голосов
/ 14 июля 2009

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

  • Это будет помощь или помеха?
  • Вопросы скорости при вызове, обновлении или поиске / манипулировании?

Вот пример некоторых структур моей таблицы:

  • пользователи - UserId, имя пользователя, адрес электронной почты, зашифрованный пароль, дата регистрации, ip
  • user_details - данные cookie, имя, адрес, контактные данные, принадлежность, демографические данные
  • user_activity - вклады, последний онлайн, последний просмотр
  • user_settings - настройки отображения профиля
  • user_interests - переменные таргетинга рекламы
  • user_levels - права доступа
  • user_stats - хиты, подсчеты

Редактировать: Я до сих пор проголосовал за все ответы, все они имеют элементы, которые по существу отвечают на мой вопрос.

Большинство таблиц имеют отношение 1: 1, что было основной причиной их денормализации.

Будут ли проблемы, если таблица охватит более 100 столбцов, когда большая часть этих ячеек, вероятно, останется пустой?

Ответы [ 8 ]

58 голосов
/ 14 июля 2009

Несколько таблиц помогают в следующих случаях / случаях:

(a) если разные люди будут разрабатывать приложения с использованием разных таблиц, имеет смысл разделить их.

(b) Если вы хотите предоставить разные виды полномочий разным людям для разных частей сбора данных, может быть удобнее разделить их. (Конечно, вы можете посмотреть на определение видов и дать им соответствующую авторизацию).

(c) Для перемещения данных в разные места, особенно во время разработки, может иметь смысл использовать таблицы, приводящие к меньшим размерам файлов.

(d) Меньший отпечаток ноги может обеспечить комфорт при разработке приложений для сбора конкретных данных одного объекта.

(e) Это возможно: то, что вы рассматривали как данные с одним значением, в будущем может оказаться действительно множественным значением. например кредитный лимит представляет собой одно поле значения на данный момент. Но завтра вы можете изменить значения на (дата от, дата до, стоимость кредита). Разделение таблиц может пригодиться.

Мой голос будет за несколько таблиц - с данными, соответствующим образом разделенными.

Удачи.

32 голосов
/ 14 июля 2009

Объединение таблиц называется денормализацией.

Это может (или не может) помочь сделать некоторые запросы (которые делают много JOIN с) более быстрыми за счет создания ада обслуживания.

MySQL может использовать только метод JOIN, а именно NESTED LOOPS.

Это означает, что для каждой записи в управляющей таблице MySQL находит соответствующую запись в ведомой таблице в цикле.

Поиск записи - довольно дорогостоящая операция, которая может занимать в десятки раз больше времени, чем чистое сканирование записей.

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

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

Технический ад, с другой стороны, гарантирован.

17 голосов
/ 14 июля 2009

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

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

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

13 голосов
/ 14 июля 2009

Имеют ли все из этих таблиц отношение 1-to-1? Например, будет ли каждая строка пользователя иметь только одну соответствующую строку в user_stats или user_levels? Если это так, возможно, имеет смысл объединить их в одну таблицу. Если же отношение не равно 1 to 1, то, вероятно, не имеет смысла объединять (денормализовать) их.

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

ETA:

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

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

8 голосов
/ 14 июля 2009

Создание одной массивной таблицы противоречит принципам реляционной базы данных. Я бы не совмещал их все в один стол. Вы собираетесь получить несколько экземпляров повторяющихся данных. Например, если у вашего пользователя три интереса, у вас будет 3 строки с одними и теми же пользовательскими данными, чтобы хранить три разных интереса. Определенно перейдите к подходу множественных «нормализованных» таблиц. См. эту страницу Wiki для нормализации базы данных.

Edit: Я обновил свой ответ, поскольку вы обновили свой вопрос ... Теперь я согласен с моим первоначальным ответом еще больше ...

большая часть этих клеток скорее всего, останется пустым

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

Я работал в телефонной компании, где было множество таблиц, для получения данных может потребоваться много объединений. Когда производительность чтения из этих таблиц была критической, то создавались процедуры, которые могли бы генерировать плоскую таблицу (то есть денормализованную таблицу), которая не требовала бы соединений, вычислений и т. Д., На которые могли бы указывать отчеты. Затем они используются вместе с агентом сервера SQL для запуска задания через определенные промежутки времени (т. Е. Еженедельное представление некоторых статистических данных будет выполняться раз в неделю и т. Д.).

7 голосов
/ 07 мая 2013

Почему бы не использовать тот же подход, который используется в Wordpress, имея таблицу пользователей с базовой информацией о пользователях, которая есть у каждого, а затем добавляя таблицу «user_meta», которая может в основном представлять собой любую пару ключ-значение, связанную с идентификатором пользователя. Поэтому, если вам нужно найти всю метаинформацию для пользователя, вы можете просто добавить ее в свой запрос. Вам также не всегда придется добавлять дополнительный запрос, если он не нужен для таких вещей, как вход в систему. Преимущество этого подхода также делает вашу таблицу открытой для добавления новых функций для ваших пользователей, таких как сохранение их маркера Twitter или каждого отдельного интереса. Вам также не придется иметь дело с лабиринтом связанных идентификаторов, потому что у вас есть одна таблица, которая управляет всеми метаданными, и вы ограничите ее только одной ассоциацией вместо 50.

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

3 голосов
/ 14 июля 2009

Я думаю, что это одна из тех ситуаций "это зависит". Наличие нескольких таблиц чище и, вероятно, теоретически лучше. Но когда вам нужно объединить 6-7 таблиц для получения информации об одном пользователе, вы можете начать переосмысливать этот подход.

1 голос
/ 14 июля 2009

Я бы сказал, что это зависит от того, что на самом деле означают другие таблицы. Содержит ли user_details более 1 пользователя / users и так далее. Какой уровень нормализации лучше всего подходит для ваших нужд, зависит от ваших требований.

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

Мне кажется, вы могли бы пропустить User_Details, так как это, вероятно, отношение 1 к 1 с пользователями. Но остальные, вероятно, много строк на пользователя?

...