Выбрать строку и строки внешнего ключа в одном запросе против множества запросов - PullRequest
2 голосов
/ 30 ноября 2011

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

create table user_tag(
 user_id int unsigned not null,
 tag_id int unsigned not null,
 primary_key (user_id, tag_id)
);

Я хочу выйти изБаза данных полный список пользователей (или, по крайней мере, многие из них) вместе с тегами, которые они связали.Я использую PHP как серверный язык для этого.

Итак, мой вопрос: лучше ли выполнить один SQL-запрос, извлекая всю информацию, например так:

select user.name, user.image, ..., tag.name from user, tag, user_tag
   where user.user_id = user_tag.user_id and tag.tag_id = user_tag.tag_id;

или лучшевыполнить один первый запрос для пользователей, а затем получить их теги:

select user.name, user.image, ... from user;

, а затем для каждого пользователя:

select tag.name from tag, user_tag where tag.tag_id = user_tag.tag_id
   and user_tag.user_id = $USERID;

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

Что лучше?Плюсы и минусы?Другие способы?

Спасибо

PS: пожалуйста, не принимайте во внимание синтаксис SQL, я не проверял его на реальной базе данных, это всего лишь вопрос дизайна, спасибо

Ответы [ 4 ]

2 голосов
/ 30 ноября 2011

Я бы рассмотрел только два варианта:

  1. Один запрос:

    SELECT user.user_id, user.name, user.image, ..., tag.tag_id, tag.name
    FROM user
    LEFT JOIN user_tag ON user.user_id = user_tag.user_id
    LEFT JOIN tag ON user_tag.tag_id=tag.tag_id
    
  2. Два запроса:

    SELECT user_id, name, image, ...
    FROM user
    
    SELECT user_tag.user_id, tag.tag_id, tag.name
    FROM user_tag
    INNER JOIN tag ON user_tag.tag_id=tag.tag_id
    

Если у вас 100 пользователей, нет смысла выдавать идентичный запрос 100 раз.

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

1 голос
/ 30 ноября 2011

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

1 голос
/ 30 ноября 2011

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

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

Я бы 99% времени использовал один запрос - если у вас есть все соответствующие индексы, IMO, то гораздо быстрее отправить один запрос .... быстрее с точки зрения кодирования, ответа сервера, а также делает вещи немного легче для чтения - вы можете понимать структуру базы данных, как вы видите соединения - вы можете использовать разные псевдонимы в другом запросе, и это может показаться странным.

0 голосов
/ 30 ноября 2011

Дополнительные параметры:

Вариант 3: два запроса. Сначала выберите всех пользователей:

select user.name, user.image, ... 
from user
ORDER BY user_id;

, а затем получить теги для всех пользователей (и объединить 2 запроса в PHP):

select user_tag.user_id, tag.name 
from tag
  JOIN user_tag 
    ON tag.tag_id = user_tag.tag_id
GROUP BY tag.user_id 
ORDER BY tag.user_id
       , tag.name;

Вариант 4. получить все в одном запросе, по одной строке на пользователя:

SELECT user.name, user.image, ... 
     , GROUP_CONCAT(tag.name ORDER BY tag_name SEPARATOR ' ') AS tags
FROM user
  LEFT JOIN user_tag
    ON user_tag.user_id = user.user_id 
  LEF JOIN tag 
    ON tag.tag_id = user_tag.tag_id
GROUP BY user.user_id 
ORDER BY user.user_id;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...