какой из этих 2 методов наиболее эффективен с PHP / MYSQL

#php #mysql #performance

#php #mysql #Производительность

Вопрос:

У меня есть некоторые данные о местоположении, которые находятся в таблице locations , причем ключ является уникальным location_id

У меня есть некоторые пользовательские данные, которые находятся в таблице users , причем ключ является уникальным user_id

Я думал связать эти два способа вместе:

  1. Я могу указать «местоположение» в данных каждого пользователя.

     'SELECT user_id FROM users WHERE location = "LOCATIONID";'
    //this IS NOT searching with the table's key
    //this does not require an explode
    //this stores 1 integer per user
      
  2. Я также могу поместить ‘идентификаторы пользователей’ в виде строки идентификаторов, разделенных запятой, в данные каждого местоположения.

     'SELECT userIDs FROM locations WHERE location_id = "LOCATIONID";'
    //this IS searching with the tables key
    //this needs an explode() once the comma delimited list is retrieved
    //this stores 1 string of user ids per location
      

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

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

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

1. может ли много пользователей быть из одного и того же местоположения? И может ли пользователь быть связан со многими местоположениями?

2. в местоположении может быть много пользователей, но каждый пользователь может находиться только в одном местоположении.

Ответ №1:

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

С вариантом 2 существует множество проблем, включая отсутствие возможности использовать идентификаторы пользователя до тех пор, пока вы не перенесете их в PHP, а затем приходится запускать гораздо больше SQL-запросов для каждого идентификатора. Это крайне неэффективно.Делайте как можно больше внутри MySQL, оптимизация, которую уровень базы данных может выполнить во время выполнения запроса, легко будет намного быстрее, чем все, что вы пишете на PHP.

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

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

1. должны ли индексы быть уникальными? или просто первичный ключ? потому что было бы несколько пользователей с одинаковым местоположением.

2. @дотошный: Обычные индексы могут быть уникальными или нет. В этом случае вы, вероятно, не хотите, чтобы это было. Я добавил ссылку на документацию в свой ответ. Первичные ключи всегда являются уникальными индексами.

3. а, ладно! я просто подумал, что по какой-то причине все индексы должны быть уникальными. это отлично отвечает на мои вопросы.

Ответ №2:

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

Не забудьте также добавить правильный индекс в вашу таблицу users.

 CREATE TABLE locations (
    locationId INT PRIMARY KEY AUTO_INCREMENT
) ENGINE=INNODB;

CREATE TABLE users (
    userId INT PRIMARY KEY AUTO_INCREMENT,
    location INT,
    INDEX ix_location (location)
) ENGINE=INNODB;
  

Или только добавить индекс

 ALTER TABLE users ADD INDEX ix_location(location);
  

Ответ №3:

Вы слышали о внешнем ключе?

получите подробную информацию из многих таблиц tables, используя join.

Вы также можете использовать вложенный запрос.

Как вы сказали, есть две таблицы users и locations.

Сохраняйте userid в качестве внешнего ключа в locations и извлекайте его на основе этого.

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

1. внешний ключ, похоже, еще больше ускорит работу. Я бы сделал location внешним ключом в users, если бы хотел, чтобы в каждом местоположении было несколько пользователей, верно?

2. @дотошный ключ: Внешний ключ — это просто другой вид индекса в MySQL, больше информационный. Они явно поддерживаются только в том случае, если вы используете InnoDB. Это скорее концепция, чем реальная часть MySQL.

3. @дотошный вы не можете сделать местоположение внешним ключом. сделайте идентификатор местоположения внешним ключом. смотрите, например, brisbane находится в США, и он находится в AUS, поэтому хорошей идеей будет указать id и сделать его внешним ключом. В вашем случае этого может и не произойти. но это хорошая практика

Ответ №4:

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

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

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