2017-10-12 6 views
1

私はソーシャルネットワーク上で実行される次のクエリを持っています。クエリは、データベースから投稿(Facebookの投稿など)を取得します。MYSQL ORDER 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, 
    (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 

各投稿にはコメントがある場合とコメントがない場合があります。 最新のアクティビティが最初にある投稿を取得するクエリが必要です。 投稿にコメントがある場合は、最新のコメントの日付をとります。投稿にコメントがない場合、私は投稿の作成日を取る。

ジョブがコメントの日付の間greates値(コメントが存在する場合)とポストの作成日をピックアップGreatest(P.creation_date, Coalesce(Max(C.date), P.creation_date))によって行われます。

その後、ORDER BY last_activity DESCはソート仕事をしていません。

PROBLEM

クエリが本当に遅いです。実行には8秒かかります。投稿テーブルには8K個の行があり、コメントテーブルには8K個の行があります。私は理解していない何

は、私がこのORDER BY P.id_postでORDER BY句を交換する場合、それは実行に0.5秒かかるということです。しかし、ORDER BY句をORDER BY P.creation_dateに置き換えると、8秒かかります。

追加に関する情報

  • ポストテーブルはCREATION_DATEにインデックスを持っている...それは日付が好きではないようです。
  • コメントテーブルは
  • サーバーは、私はSO like this one上の他のソリューションを試みたが、彼らは私が実行するには、このクエリを修正することができますどのよう

を動作しませんでしたCentOSのLinuxの6.6

  • にLAMPを実行した日付にインデックスを持っていますもっと早く?

  • +0

    あなたは、列 'CREATION_DATEにインデックスを作成しようとしてください'? –

    +0

    @YuJiaao質問では、私は "投稿テーブルはcreation_dateのインデックスを持っている"と書いています。あなたはそれか他の何かを意味しますか? –

    +0

    'last_activity'でgroupを使用していますが、last_activityが動的に生成されています。そのような場合にインデックスが役立たないと思います。おそらく' last_activity'を投稿テーブルのカラムとして追加しますか? –

    答えて

    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

    group by句を必要とする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 
    
    関連する問題