【问题标题】:Optimize query: Select in Select优化查询:Select in Select
【发布时间】:2011-12-15 16:48:44
【问题描述】:

假设我有一个表来存储每个用户的博客(表名是博客)。 但也有一个表来存储用户喜欢的其他用户的博客(表名是likedBlogs),是吗?

所以要检索它们,我只是这样做: - 选择用户的博客。 - 添加他喜欢的博客。

    $q = mysql_query("
SELECT id 
FROM blogs 
WHERE (iduser = $id) 
      OR id IN 
       (SELECT idblog 
        FROM likedBlogs 
        WHERE iduser='$id') 
      AND (id > 0) 
ORDER BY id DESC 
LIMIT 20
") or die(mysql_error());

我可以做得更好吗? (你在这个查询中的表现如何?)

谢谢

【问题讨论】:

    标签: mysql sql select query-optimization


    【解决方案1】:

    我相信你可以更好地重构它使用 EXISTS 而不是 IN。

    IN 要求返回整个结果集然后开始搜索值,但EXISTS 逐行检查并在找到第一次出现时中断内部查询。

    SELECT id  
    FROM blogs  
    WHERE (iduser = $id)        
    OR EXISTS
          (SELECT idblog         
           FROM likedBlogs          
           WHERE iduser='$id' AND idblog = id)
    AND (id > 0)  
    ORDER BY id 
    DESC  LIMIT 20 
    

    Optimizing IN/=ANY Subqueries

    非常有用的优化是“通知”子查询,唯一的 感兴趣的行是内部表达式 inner_expr 所在的行 等于outer_expr。这是通过按下适当的 子查询的 WHERE 子句中的相等性。也就是说,比较是 转换为: EXISTS (SELECT 1 FROM ... WHERE subquery_where AND external_expr=inner_expr)

    【讨论】:

    • @Toni Michel Caubet:是的,在大型数据集上非常重要。查看我提供的链接,我相信您可以在 Intrawebs 中搜索EXISTS vs IN MySql,您会发现很多评论
    • 在 SQL Server 2005+ EXISTSIN 评估相同,谢天谢地。
    • @JNK :哇,很高兴知道,谢谢!刚刚尝试查看 MSDN 关于 IN 并没有发现任何相关信息,您的意思是会生成相同的执行计划?
    • @sll - 是的,通常它比JOIN 更快,因为它会短路。我使用IN 评估单个字段,使用EXISTS 比较多个字段。
    • 有趣!所以@JNK,您会建议对此查询进行任何更改吗?
    【解决方案2】:

    通常你会使用join 而不是嵌套的select

    select blogs.id
    from blogs inner join likedBlogs on (blogs.iduser = likedBlogs.iduser and blogs.id  = likedBlogs.idblog)
    where blogs.iduser = $id
    and blogs.id > 0
    order by blogs.id desc limit 20
    

    upd第一次没有正确阅读任务说明

    select blogs.id 
    from blogs left join likedBlogs on (blogs.id = likedBlogs.idblog)
    where blogs.iduser = $id or likedBlogs.iduser = $id;
    

    【讨论】:

    • INNER JOIN 是否适用于 likedBlogs 中没有条目的情况?
    • 很抱歉造成混淆。 left join 是我们在这种情况下需要的。更新了我的答案。
    • @Андрей Татаринов : 现在好多了:)
    【解决方案3】:

    您的查询对我来说看起来不错。为了提高性能,您应该确保在数据库表中的 id 列上有索引。

    【讨论】:

    • uf,我还没有使用索引......我还没有找到任何容易理解的东西......
    【解决方案4】:

    我认为工会可能会更好地为您服务

    SELECT id 
    FROM blogs 
    WHERE iduser = $id AND id > 0
    UNION 
    SELECT idblog AS id 
    FROM likedBlogs 
    WHERE iduser='$id' AND idblog > 0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-12
      • 2011-11-24
      • 1970-01-01
      • 1970-01-01
      • 2019-12-15
      • 2016-06-02
      • 2016-12-01
      相关资源
      最近更新 更多