使用LEFT JOIN CASE按顺序查询慢10倍

时间:2014-06-20 11:25:51

标签: mysql sql query-optimization

我有一个相对较长的查询(在下面发布以供参考)。

我试图调试查询为什么这么慢(2秒),我终于找到了原因。

在查询的最后我做:

  ORDER BY 
    -- order by date
    DATE(p.date) DESC, 
    -- order by followed people
    CASE WHEN n.id IS NULL THEN '0' ELSE '1' END DESC -- this case takes the query from 20ms to 2 seconds

如果我删除了CASE顺序,它将在大约20毫秒内执行。

为什么会这样?

当我使用EXPLAIN运行查询时,我注意到CASE将添加"使用临时"进入额外的领域。

请参阅下面的EXPLAIN查询:

顺序解释CASE WHEN n.id IS NULL THEN '0' ELSE '1' END DESC的查询

With the CASE statement in the orderby

顺序解释不带 CASE WHEN n.id IS NULL THEN '0' ELSE '1' END DESC的查询

Without the CASE statement in the order by

完整查询(如果有帮助):

  SELECT 
    -- feed type
    '1' AS feed_type, 
    -- fetch post data
    p.id, 
    p.receiver, 
    p.date, 
    p.message, 
    p.system_msg, 
    p.type AS post_type, 
    -- fetch author data
    u.user_id, 
    u.firstname, 
    u.lastname, 
    u.type, 
    u.permalink, 
    av.file AS avatar_file, 
    -- fetch receiever data
    u2.user_id AS receiver_user_id, 
    u2.firstname AS receiver_firstname, 
    u2.lastname AS receiver_lastname, 
    u2.permalink AS receiver_permalink, 
    u2.type AS receiver_type, 
    -- fetch post comment count
    (
      SELECT 
        COUNT(*) 
      FROM 
        edu_posts pc 
      WHERE 
        pc.comment = p.id 
        AND pc.deleted IS NULL
    ) as commentCount, 
    -- fetch post like count
    (
      SELECT 
        COUNT(*) 
      FROM 
        edu_likes l 
      WHERE 
        l.like_entity = p.id
    ) as likeCount, 
    -- user follow state
    CASE WHEN n.id IS NOT NULL THEN '1' ELSE '0' END as is_following, 
    -- check if user likes post
    CASE WHEN l.like_id IS NOT NULL THEN '1' ELSE '0' END as user_likes 
  FROM 
    edu_posts p
    INNER JOIN -- author information
    edu_users u ON u.user_id = p.author 
    LEFT JOIN -- author avatar
    edu_avatars av ON av.fk = p.author 
    AND av.temp = 0 
    AND av.fk_type = 1 
    LEFT JOIN -- receiver information (if any)
    edu_users u2 ON u2.user_id = p.receiver 
    LEFT JOIN -- check if author/receiver is followed by current user
    edu_notification_list n ON n.user = 1 
    AND n.following = 1 
    AND (
      n.fk = p.author 
      OR n.fk = p.receiver
    ) 
    AND (
      (
        n.type = 5 
        AND p.type = 3
      ) 
      OR (
        n.type = 2 
        AND p.type = 1
      )
    ) 
    LEFT JOIN -- check if user likes the post
    edu_likes l ON l.like_entity = p.id 
    AND l.like_author = 1 
  WHERE
    p.deleted IS NULL 
    AND p.comment IS NULL 
    AND (
      p.id = p.comment 
      OR 1 = 1
    ) 
    AND (
      n.id IS NOT NULL 
      OR p.system_msg = 0
    ) 
  ORDER BY 
    -- order by date
    DATE(p.date) DESC, 
    -- order by followed people
    CASE WHEN n.id IS NULL THEN '0' ELSE '1' END DESC 
  LIMIT 
    20 OFFSET 0

注意:如果您想查看任何其他表格,请告诉我。

1 个答案:

答案 0 :(得分:0)

您执行的操作无法使用索引。而是尝试

ORDER BY DATE(p.date) DESC, 
         n.id IS NULL ASC