MySql内连接需要10秒以上

时间:2014-02-14 18:05:09

标签: php mysql sql

我有两个表格帖子和帖子

posts (id,userid,post,timestamp) 30 000 rows 

followings(id_me,userid) 90 000 rows

我希望根据我关注的人和我的帖子

获取lattest 10个帖子表格
SELECT p.*
 FROM posts as p INNER JOIN
     followings as f
     ON (f.id_me=(my user id) AND p.userid=f.userid )
        OR 
        p.userid=(my user id)
ORDER BY id DESC LIMIT 10

但返回需要大约10-15秒。提前谢谢!

6 个答案:

答案 0 :(得分:0)

在SQL中使用OR是性能杀手,试试这个:

SELEC p.*
FROM posts as p INNER JOIN
 followings as f
 ON (f.id_me=(my user id) AND p.userid IN (f.userid,(my user id)))
ORDER BY id DESC LIMIT 10

答案 1 :(得分:0)

使用union执行此查询:

(SELECT p.*
 FROM posts p INNER JOIN
      followings f
      ON (f.id_me=(my user id) AND p.userid=f.userid
)
union
(select p.*
 from posts p
 where p.userid=(my user id)
)
ORDER BY id DESC
LIMIT 10

如果两个条件从不重叠,则改为使用union all

答案 2 :(得分:0)

这样的OR条件会阻止查询优化器使用索引。改为使用UNION

SELECT *
FROM (SELECT p.*
      FROM posts as p 
      INNER JOIN followings as f
      ON f.id_me=(my user id) AND p.userid=f.userid

      UNION

      SELECT *
      FROM posts
      WHERE userid = (my user id)) u
ORDER BY id DESC
LIMIT 10

答案 3 :(得分:0)

可能只是我,但我认为你的WHERE条款位置效率低下:

SELECT
    p.*
FROM
    posts p
    INNER JOIN
        followings f
        ON p.userid=f.userid
WHERE
    MyUserID IN (p.userid, f.id_me)
ORDER BY
    id DESC
LIMIT
    10

答案 4 :(得分:0)

首先,从join子句中删除过滤器,让连接只关联连接表。

(
SELECT p.*
 FROM posts as p
  INNER JOIN followings as f ON p.userid=f.userid
  where f.id_me=(my user id)
UNION
SELECT p.*
 FROM posts as p
  where p.userid=(my user id)
)
ORDER BY id DESC LIMIT 10

第二,验证你的索引是否没有索引它不能对两个表的每个笛卡尔积进行全表扫描(比较30k x 90k = ~3700k对)

第三,如果你不遵循自己,你需要一个你正在关注的帖子和你的帖子

答案 5 :(得分:0)

我在评论中读到你有所需的索引。问题是查询。将ORJOIN组合在一起会使穷人和(通常)愚蠢的优化者感到困惑。 LIMIT 10应该会有所帮助,但优化程序还不够聪明,无法制定最佳计划。

尝试此查询:

  ( SELECT p.*
    FROM posts AS p
      JOIN followings AS f
         ON  f.id_me = (my_user_id) 
         AND p.userid = f.userid
    ORDER BY p.id DESC 
    LIMIT 10
  ) 
UNION ALL
  ( SELECT p.*
    FROM posts AS p
    WHERE p.userid = (my_user_id) 
    ORDER BY p.id DESC 
    LIMIT 10
  ) AS x
ORDER BY id DESC
LIMIT 10 ;