如何使用多个表优化SQL查询

时间:2014-02-17 22:27:15

标签: php mysql sql

我在这里有这个SQL查询,它抓住了5个最新的新闻帖子。我想这样做它也可以在同一个查询中抓取总喜欢和总新闻评论。但是当我处理大量数据时,我所做的查询似乎有点慢,所以我试图看看我是否能找到更好的解决方案。它在下面:

SELECT *, 
`id` as `newscode`, 
(SELECT COUNT(*) FROM `likes` WHERE `type`="newspost" AND `code`=`newscode`) as `total_likes`,
(SELECT COUNT(*) FROM `news_comments` WHERE `post_id`=`newscode`) as `total_comments`
FROM `news` ORDER BY `id` DESC LIMIT 5

这也是一个SQLFiddle:http://sqlfiddle.com/#!2/d3ecbf/1

4 个答案:

答案 0 :(得分:1)

我建议在total_likes表中添加total_commentsnews字段,只要添加或删除了喜欢和/或评论,它就会递增/递减。

您的likesnews_comments表格仅用于历史目的。

每次加载页面时都不应执行这种繁重的计数,因为这样会完全浪费资源。

答案 1 :(得分:0)

首先检查列 id post_id 类型,代码的索引。

答案 2 :(得分:0)

我认为这是T-SQL,因为这是我最熟悉的。

首先,我会检查索引。如果那看起来不错,那我就检查声明。查看您的查询地图,了解它如何填充您的结果。

SQL向后工作,因此它从您上一个AND语句开始,然后从那里开始。它会将它们全部按代码分组,然后输入,最后给你一个计数。

现在,无论日期如何,您都会使用某些代码抓取所有内容。当你说你想要最新版本时,我假设某处有一个日期栏。

为了加快速度,请在AND添加另一个WHERE并说明日期。无论是过去24小时,还是上周,无论如何。

答案 3 :(得分:0)

你可以使用连接重写它,MySQL已经知道子查询的问题,特别是在处理大型数据集时:

SELECT  n.*, 
        `id` as `newscode`, 
        COALESCE(l.TotalLikes, 0) AS `total_likes`,
        COALESCE(c.TotalComments, 0) AS `total_comments`
FROM    `news` n
        LEFT JOIN
        (   SELECT  Code, COUNT(*) AS TotalLikes
            FROM    `likes` 
            WHERE   `type` = "newspost" 
            GROUP BY Code
        ) AS l
            ON l.`code` = n.`id`
        LEFT JOIN
        (   SELECT  post_id, COUNT(*) AS TotalComments
            FROM    `news_comments` 
            GROUP BY post_id
        ) AS c
            ON c.`post_id` = n.`id`
ORDER BY n.`id` DESC LIMIT 5;

原因是当你使用上面的连接时,MySQL会在第一次需要时实现子查询的结果,例如在这个查询开始时,mySQL会把结果放在:

SELECT  post_id, COUNT(*) AS TotalComments
FROM    `news_comments` 
GROUP BY post_id

进入内存表并使用hash post_id进行更快速的查找。然后,对于news中的每一行,只需从此散列表中查找TotalComments,当您使用相关子查询时,它将为news中的每一行执行一次查询, news很大会导致大量执行。如果初始结果集很小,您可能看不到性能优势,而且可能更糟。

SQL小提琴上的示例

最后,您可能希望为news_commentslikes中的相关字段编制索引。对于此特定查询,我认为以下索引将有所帮助:

CREATE INDEX IX_Likes_Code_Type ON Likes (Code, Type);
CREATE INDEX IX_newcomments_post_id ON news_comments (post_id);

虽然您可能需要将第一个索引拆分为两个:

CREATE INDEX IX_Likes_Code ON Likes (Code);
CREATE INDEX IX_Likes_Type ON Likes (Type);