Php 提高SQL查询的效率

Php 提高SQL查询的效率,php,mysql,Php,Mysql,我有一个可以运行的查询,但是运行它至少需要3秒钟,所以我认为它可能会更快。它用于填充新线程列表,并显示每个线程中有多少未读帖子。在将查询字符串放入$db->query\u read()之前,我会生成查询字符串。为了只从有效论坛获取结果,$ids是一个字符串,最多有50个值由逗号分隔 userthreadviews表已经存在了一周,其中大约有9500行。我不确定是否需要设置一个cron作业来定期清除一周以上的线程视图,或者是否可以让它增长 以下是当前的查询: SELECT `thread

我有一个可以运行的查询,但是运行它至少需要3秒钟,所以我认为它可能会更快。它用于填充新线程列表,并显示每个线程中有多少未读帖子。在将查询字符串放入
$db->query\u read()
之前,我会生成查询字符串。为了只从有效论坛获取结果,
$ids
是一个字符串,最多有50个值由逗号分隔

userthreadviews
表已经存在了一周,其中大约有9500行。我不确定是否需要设置一个cron作业来定期清除一周以上的线程视图,或者是否可以让它增长

以下是当前的查询:

SELECT 
    `thread`.`title` AS 'r_title', 
    `thread`.`threadid` AS 'r_threadid', 
    `thread`.`forumid` AS 'r_forumid', 
    `thread`.`lastposter` AS 'r_lastposter', 
    `thread`.`lastposterid` AS 'r_lastposterid', 
    `forum`.`title` AS 'f_title', 
    `thread`.`replycount` AS 'r_replycount', 
    `thread`.`lastpost` AS 'r_lastpost', 
    `userthreadviews`.`replycount` AS 'u_replycount', 
    `userthreadviews`.`id` AS 'u_id',
    `thread`.`postusername` AS 'r_postusername', 
    `thread`.`postuserid` AS 'r_postuserid' 
FROM 
    `thread` 
INNER JOIN 
    `forum` 
    ON (`thread`.`forumid` = `forum`.`forumid`) 
LEFT JOIN 
    (`userthreadviews`) 
    ON (`thread`.`threadid` = `userthreadviews`.`threadid` 
    AND `userthreadviews`.`userid`=$userid) 
WHERE 
    `thread`.`forumid` IN($ids) 
    AND `thread`.`visible`=1 
    AND `thread`.`lastpost`> time() - 604800
ORDER BY `thread`.`lastpost` DESC LIMIT 0, 30
另一个加入
post
表的查询(只显示用户发布的线程)实际上是两倍的速度,所以我认为这里有一些东西可以更改以加快速度。有人能提供一些建议吗

编辑:对不起,我把解释放在了另一个查询前面。以下是正确的输出: 根据要求,以下是EXPLAIN SELECT生成的输出:

如果表未索引,请尝试为其编制索引

如果表未索引,请尝试为其编制索引

请查看该语句。它为您提供查询的执行计划

一旦知道了计划,就可以检查计划中涉及的字段是否有索引。如果没有,创建它们

也许该计划揭示了有关如何以另一种方式编写查询的详细信息,从而使查询更加优化。

请查看该语句。它为您提供查询的执行计划

一旦知道了计划,就可以检查计划中涉及的字段是否有索引。如果没有,创建它们


也许该计划揭示了有关如何以另一种方式编写查询的详细信息,从而使查询更加优化。

要在连接/where上没有索引(explain上的used key=NULL),这就是查询速度慢的原因。您应该以以下方式对它们进行索引:

CREATE INDEX thread_forumid_index ON thread(forumid);
CREATE INDEX userthreadviews_forumid_index ON userthreadviews(forumid);

文档

在join/where上没有索引(解释时使用key=NULL),这就是查询速度慢的原因。您应该以以下方式对它们进行索引:

CREATE INDEX thread_forumid_index ON thread(forumid);
CREATE INDEX userthreadviews_forumid_index ON userthreadviews(forumid);
文档

建议:

  • 将条件从WHERE子句移动到JOIN子句
  • 将具有条件的联接放在另一个联接之前
  • 确保您有适当的索引,并且它们正在查询中使用(创建您需要的索引…索引太多可能和索引太少一样糟糕)
以下是我对这个问题的建议:

SELECT 
    `thread`.`title` AS 'r_title',
    `thread`.`threadid` AS 'r_threadid',
    `thread`.`forumid` AS 'r_forumid',
    `thread`.`lastposter` AS 'r_lastposter',
    `thread`.`lastposterid` AS 'r_lastposterid',
    `forum`.`title` AS 'f_title',
    `thread`.`replycount` AS 'r_replycount',
    `thread`.`lastpost` AS 'r_lastpost',
    `userthreadviews`.`replycount` AS 'u_replycount',
    `userthreadviews`.`id` AS 'u_id',
    `thread`.`postusername` AS 'r_postusername',
    `thread`.`postuserid` AS 'r_postuserid' 
FROM
    `thread` 
    INNER JOIN (`forum`)
        ON ((`thread`.`visible` = 1)
        AND (`thread`.`lastpost` > $time)
        AND (`thread`.`forumid` IN ($ids))
        AND (`thread`.`forumid` = `forum`.`forumid`))
    LEFT JOIN (`userthreadviews`)
        ON ((`thread`.`threadid` = `userthreadviews`.`threadid`)
        AND (`userthreadviews`.`userid` = $userid))
ORDER BY
    `thread`.`lastpost` DESC
LIMIT
    0, 30
这些是很好的索引候选项:

- `forum`.`forumid`
- `userthreadviews`.`threadid`
- `userthreadviews`.`userid`
- `thread`.`forumid`
- `thread`.`threadid`
- `thread`.`visible`
- `thread`.`lastpost`
看起来你已经有很多索引了。。。因此,确保保留您真正需要的,并移除无用的。

建议:

  • 将条件从WHERE子句移动到JOIN子句
  • 将具有条件的联接放在另一个联接之前
  • 确保您有适当的索引,并且它们正在查询中使用(创建您需要的索引…索引太多可能和索引太少一样糟糕)
以下是我对这个问题的建议:

SELECT 
    `thread`.`title` AS 'r_title',
    `thread`.`threadid` AS 'r_threadid',
    `thread`.`forumid` AS 'r_forumid',
    `thread`.`lastposter` AS 'r_lastposter',
    `thread`.`lastposterid` AS 'r_lastposterid',
    `forum`.`title` AS 'f_title',
    `thread`.`replycount` AS 'r_replycount',
    `thread`.`lastpost` AS 'r_lastpost',
    `userthreadviews`.`replycount` AS 'u_replycount',
    `userthreadviews`.`id` AS 'u_id',
    `thread`.`postusername` AS 'r_postusername',
    `thread`.`postuserid` AS 'r_postuserid' 
FROM
    `thread` 
    INNER JOIN (`forum`)
        ON ((`thread`.`visible` = 1)
        AND (`thread`.`lastpost` > $time)
        AND (`thread`.`forumid` IN ($ids))
        AND (`thread`.`forumid` = `forum`.`forumid`))
    LEFT JOIN (`userthreadviews`)
        ON ((`thread`.`threadid` = `userthreadviews`.`threadid`)
        AND (`userthreadviews`.`userid` = $userid))
ORDER BY
    `thread`.`lastpost` DESC
LIMIT
    0, 30
这些是很好的索引候选项:

- `forum`.`forumid`
- `userthreadviews`.`threadid`
- `userthreadviews`.`userid`
- `thread`.`forumid`
- `thread`.`threadid`
- `thread`.`visible`
- `thread`.`lastpost`


看起来你已经有很多索引了。。。因此,请确保保留您真正需要的,并删除无用的。

您是否查看了EXPLAIN语句的输出?看到了吗?你能发布解释选择的输出吗?我正在试图找到一种发布解释结果的方法。我想我必须做一个屏幕截图。我想这表明我在加入
userthreadview
时需要一个额外的参数。我不知道那会是什么。你好,来自未来!目前,
userthreadviews
表中有188482行,没有发生任何错误。一切仍在顺利进行。索引太神奇了。你看过EXPLAIN语句的输出了吗?看到了吗?你能发布解释选择的输出吗?我正在试图找到一种发布解释结果的方法。我想我必须做一个屏幕截图。我想这表明我在加入
userthreadview
时需要一个额外的参数。我不知道那会是什么。你好,来自未来!目前,
userthreadviews
表中有188482行,没有发生任何错误。一切仍在顺利进行。指数太惊人了。为什么要投否决票?这是真的!一个评论多于一个答案好吧,但这是真的,我+1只是因为下一票为什么下一票?这是真的!一个评论多于一个答案好吧,但这是真的,我+1只是因为downvoteI对不起,在我自学SQL的过程中,我完全错过了关于创建和使用索引的部分。你能给我一个文档链接,让我更好地理解你的建议吗?我在userthreadviews表中添加了一个关于userid的索引,现在我得到了:查询时间:0.00984406471252对不起,在我自学SQL的过程中,我完全错过了关于创建和使用索引的部分。你能提供一个指向文档的链接以便我更好地理解你的建议吗?我在userthreadviews表中添加了一个关于userid的索引,现在我得到:查询时间:0.00984406471252SY你的查询(在变量位置使用有效数字)不起作用。没有sql错误,它刚刚开始加载,我还没有得到结果。在尝试运行此查询后,我必须重新启动服务器。哦,对不起。我已经检查过了,当我在
LEFT JOIN
子句中包含条件时,我真的做了一件蠢事。。。因为作为一个左连接,它将包含所有记录!请尝试新查询-我希望它的性能会更好。:-)请注意,如果您可以在PHP中计算查询之外的
$time
,这是另一个小型性能改进。。。您确实需要
userthreadviews.userid=$useri