繁体   English   中英

使用ORDER BY datetime时,MYSQL查询非常慢

[英]MYSQL Query very slow when using ORDER BY datetime

我在社交网络上运行以下查询。 该查询从数据库中获取帖子(例如Facebook帖子)。

SELECT P.*, 
   P.id_post id_p, 
   PM.meta_content video_title, 
   PM2.meta_content video_views, 
   PM3.meta_content racebooking_views, 
   Greatest(P.creation_date, Coalesce(Max(C.date), P.creation_date)) AS 
   last_activity, 
   P.creation_date creation_date, 
   (SELECT Count(*) 
    FROM   likes 
    WHERE  post_id = P.id_post 
           AND post_type = 'P') 
   likes_count, 
   (SELECT Count(*) 
    FROM   likes L 
    WHERE  post_id = P.id_post 
           AND post_type = 'P' 
           AND L.id_profile = 2796) 
   do_i_like 
FROM   posts P 
       LEFT JOIN comments C 
              ON P.id_post = C.post_id 
                 AND C.post_type = 'P' 
                 AND C.id_profile != P.id_profile 
       LEFT JOIN post_meta PM 
              ON PM.id_post = P.id_post 
                 AND PM.meta_type = 'T' 
       LEFT JOIN post_meta PM2 
              ON PM2.id_post = P.id_post 
                 AND PM2.meta_type = 'V' 
       LEFT JOIN post_meta PM3 
              ON PM3.id_post = P.id_post 
                 AND PM3.meta_type = 'W' 
GROUP  BY P.id_post 
ORDER  BY last_activity DESC 
LIMIT  41, 10 

每个帖子可能有或没有评论。 我希望查询首先获取具有最新活动的帖子。 因此,如果帖子中有评论,我将使用最新评论的日期。 如果帖子没有评论,我将以帖子的创建日期为准。

该工作由Greatest(P.creation_date, Coalesce(Max(C.date), P.creation_date)) ,该工作将在注释日期(如果存在注释)与创建帖子的日期之间获取greates值。

然后, ORDER BY last_activity DESC进行排序。

问题

查询真的很慢。 运行需要8秒钟。 posts表具有8K行,comments表具有8K行。

我不明白的是,如果我用此ORDER BY P.id_post替换ORDER BY子句,则需要0.5秒才能运行。 但是,如果我再次用ORDER BY P.creation_date替换ORDER BY子句,则需要8秒钟。 似乎不喜欢约会...

其他资讯

  • posts表在creation_date上有一个索引。
  • 评论表上有日期索引
  • 服务器在CentOS Linux 6.6上运行LAMP
  • 像这样尝试了其他解决方案,但它们没有用

如何解决该查询以提高运行速度?

select子句中的相关子查询可能会杀死您。 相反,请加入一个计算喜欢统计信息的子查询:

SELECT P.*, 
    P.id_post id_p, 
    PM.meta_content video_title, 
    PM2.meta_content video_views, 
    PM3.meta_content racebooking_views, 
    GREATEST(P.creation_date, COALESCE(MAX(C.date), P.creation_date)) AS last_activity, 
    P.creation_date creation_date,
    t.likes_count,
    t.do_i_like
FROM posts P
LEFT JOIN
(
    SELECT
        post_id,
        SUM(CASE WHEN post_type = 'P' THEN 1 ELSE 0 END) AS likes_count,
        SUM(CASE WHEN post_type = 'P' AND L.id_profile = 2796
                 THEN 1 ELSE 0 END) AS do_i_like
    FROM likes
    GROUP BY post_id
) t
    ON t.post_id = P.id_post 
LEFT JOIN comments C 
    ON P.id_post = C.post_id AND
       C.post_type = 'P' AND
       C.id_profile != P.id_profile 
LEFT JOIN post_meta PM 
    ON PM.id_post = P.id_post AND
       PM.meta_type = 'T' 
LEFT JOIN post_meta PM2 
    ON PM2.id_post = P.id_post AND
       PM2.meta_type = 'V' 
LEFT JOIN post_meta PM3 
    ON PM3.id_post = P.id_post AND 
       PM3.meta_type = 'W' 
ORDER BY
    last_activity DESC 
LIMIT 41, 10

另外,在编辑查询后,我看不到在外部查询中使用GROUP BY的原因,因此我将其删除。 您应该在适当的地方使用索引,尽管我的直觉是仅凭我的建议就可以显着提高性能。

有一个MAX(C.Date)将需要一个group by子句,但是它也可以代替我认为的子查询:

SELECT P.*, 
    P.id_post id_p, 
    PM.meta_content video_title, 
    PM2.meta_content video_views, 
    PM3.meta_content racebooking_views, 
    GREATEST(P.creation_date, COALESCE(max_c_date, P.creation_date)) AS last_activity, 
    P.creation_date creation_date,
    t.likes_count,
    t.do_i_like
FROM posts P
LEFT JOIN
(
    SELECT
        post_id,
        SUM(CASE WHEN post_type = 'P' THEN 1 ELSE 0 END) AS likes_count,
        SUM(CASE WHEN post_type = 'P' AND L.id_profile = 2796
                 THEN 1 ELSE 0 END) AS do_i_like
    FROM likes
    GROUP BY post_id
) t
    ON t.post_id = P.id_post 
LEFT JOIN (
      SELECT
        comments.post_id,
        MAX(comments.date) max_c_date
      FROM comments
      inner join posts ON comments.post_id = posts.id_post
      where  comments.post_type = 'P' AND
             comments.id_profile != posts.id_profile 
      GROUP BY comments.post_id
) C 
    ON P.id_post = C.post_id AND
LEFT JOIN post_meta PM 
    ON PM.id_post = P.id_post AND
       PM.meta_type = 'T' 
LEFT JOIN post_meta PM2 
    ON PM2.id_post = P.id_post AND
       PM2.meta_type = 'V' 
LEFT JOIN post_meta PM3 
    ON PM3.id_post = P.id_post AND 
       PM3.meta_type = 'W' 
ORDER BY
    last_activity DESC 
LIMIT 41, 10

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM