MySQL只查询大表的最近项目?

时间:2014-08-26 11:53:37

标签: mysql sql performance

我们有一个"谢谢"我们论坛上实施的系统。我们还有一个"看到你最近的感谢"页面,现在变得慢得多,因为"谢谢"桌子增长到数百万。

这是"谢谢"的结构。表:

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秒的速度运行。

这是解决我们的性能问题的好方法吗?或者是否有更好的方法来加速此查询而不忽略旧数据?我仍然对为什么没有使用索引感到困惑。

1 个答案:

答案 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)