2017-10-12 28 views
1

我有以下查詢在社交網絡上運行。該查詢從數據庫中提取帖子(如Facebook帖子)。使用ORDER BY時MYSQL查詢非常慢datetime

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秒。它似乎不喜歡日期...

其他相關信息

  • 職位表上CREATION_DATE的索引。
  • 意見表上的日期索引
  • 服務器上的CentOS Linux上運行LAMP 6.6
  • 我嘗試過其他的解決方案上SO like this one但他們沒有工作

我怎樣才能解決這個查詢運行更快?

+0

你嘗試創建列的索引'CREATION_DATE '? –

+0

@餘加瑤在問題中,我寫了「posts table有一個關於creation_date的索引」。你是指那個還是別的? –

+0

您使用'last_activity'組,但是last_activity是動態生成的,我認爲這樣的索引在這種情況下不起作用,可能將'last_activity'添加爲posts表的列? –

回答

2

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是,所以我刪除它。你應該在適當的時候使用索引,儘管我的預感是我的建議本身應該會顯着提升性能。

+0

'COALESCS'輕微的錯字? =>'COALESCE' ;-) –

+0

感謝您的回答!現在,我使用了一個可怕的解決方法,只是爲了使網站正常工作。 週二我會測試你的解決方案並給你一個反饋! –

0

有一個MAX(C.Date)將由條款需要一組,但是它也可以代替子查詢,我相信:

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