我们有一个"谢谢"我们论坛上实施的系统。我们还有一个"看到你最近的感谢"页面,现在变得慢得多,因为"谢谢"桌子增长到数百万。
这是"谢谢"的结构。表:
Field Type Null Key Default Extra
id int(10) NO PRI NULL auto_increment
userid int(10) NO MUL NULL
username varchar(50) NO NULL
date int(10) NO NULL
postid int(10) NO MUL NULL
关于"最近的感谢"页面,为当前用户运行以下查询($ uid):
SELECT post_thanks.postid, post_thanks.date, post_thanks.username, post_thanks.userid, thread.title
FROM " . TABLE_PREFIX . "post_thanks AS post_thanks
LEFT JOIN " . TABLE_PREFIX . "post AS post
ON post_thanks.postid = post.postid
LEFT JOIN " . TABLE_PREFIX . "thread AS thread
ON thread.threadid = post.threadid
WHERE post.userid = '$uid'
ORDER BY post_thanks.id DESC
LIMIT 20
这导致最近20个帖子感谢该用户。现在post_thanks表超过一百万行,此查询需要一秒钟才能完成。有时它来自缓存更快,但我一直在尝试不断优化它,因为用户通常只查看他们的"谢谢"当他们有新通知时(即缓存会发生变化)。
我的第一个问题是此查询使用Filesort而不是Index。鉴于表格结构,不应该使用索引?或者使用索引?
我的第二个问题是,我不需要查询500万行只是为了得到最新的谢意。整个论坛每周通常有5,000个感谢。如果用户没有检查论坛一周,那么他们最近的感谢可能已经消失了。所以我修改了这样的查询(只改变了行#2)
SELECT post_thanks.postid, post_thanks.date, post_thanks.username, post_thanks.userid, thread.title
FROM (SELECT * FROM " . TABLE_PREFIX . "post_thanks ORDER BY id DESC LIMIT 5000) AS post_thanks
LEFT JOIN " . TABLE_PREFIX . "post AS post
ON post_thanks.postid = post.postid
LEFT JOIN " . TABLE_PREFIX . "thread AS thread
ON thread.threadid = post.threadid
WHERE post.userid = '$uid'
ORDER BY post_thanks.id DESC
LIMIT 20
即使禁用缓存,此查询也会始终以小于.001秒的速度运行。
这是解决我们的性能问题的好方法吗?或者是否有更好的方法来加速此查询而不忽略旧数据?我仍然对为什么没有使用索引感到困惑。
答案 0 :(得分:1)
尝试使用inner join
而非left join
:
SELECT post_thanks.postid, post_thanks.date, post_thanks.username, post_thanks.userid, thread.title
FROM " . TABLE_PREFIX . "post_thanks post_thanks INNER JOIN
" . TABLE_PREFIX . "post AS post
ON post_thanks.postid = post.postid INNER JOIN
" . TABLE_PREFIX . "thread AS thread
ON thread.threadid = post.threadid
WHERE post.userid = '$uid'
ORDER BY post_thanks.id DESC
LIMIT 20;
接下来,我注意到where
条件是post.userid = '$uid'
。这可能是真的还是:post_thanks.userid ='$ uid'?
我建议使用内部联接,where post_thanks.userid = '$uid'
和索引:post_thanks(userid, id)
。