【问题标题】:Fetch row and its foreign key rows in one query vs many queries在一个查询与多个查询中获取行及其外键行
【发布时间】:2012-01-09 12:42:12
【问题描述】:

假设我有三张表(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语法,我没有根据真实数据库检查过,这只是设计问题,谢谢

【问题讨论】:

标签: php mysql database foreign-keys


【解决方案1】:

我只会考虑两种选择:

  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 听起来不错。

【讨论】:

    【解决方案2】:

    这实际上取决于许多特定项目、数据库大小、数据大小、使用情况、并发查询数.....

    我建议您尝试(以提高性能)每种方法并应用最适合您的要求/需要的方法。

    我会在 99% 的时间里使用单个查询 - 如果您拥有所有相关索引,IMO 发送单个查询的速度要快得多....在编码、服务器响应和制作方面更快更容易阅读 - 您可以通过查看连接来理解数据库结构 - 您可以在另一个查询中使用不同的别名,这可能看起来令人困惑。

    【讨论】:

      【解决方案3】:

      这个问题没有简单的答案,因为很大程度上取决于您的架构。找出答案的最佳方法是在您的架构中对这两种解决方案进行基准测试。但是,考虑到一个查询和多个查询之间的选择,只要您的表被正确索引,那么我会选择一个查询解决方案。这样您将节省数据库连接和文件读取的开销。

      【讨论】:

        【解决方案4】:

        更多选项:

        选项 3:两个查询。首先获取所有用户:

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

        然后获取 所有 用户的标签(并在 PHP 中结合 2 个查询):

        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;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-09-14
          • 2019-03-15
          • 1970-01-01
          • 2012-05-22
          • 2018-09-01
          • 2011-02-19
          • 2011-05-09
          • 1970-01-01
          相关资源
          最近更新 更多