2016-07-18 14 views
1
SELECT SQL_CALC_FOUND_ROWS null as `rows` , 
    (SELECT count(*) FROM `ci_user_smiley` where post_id = P.post_id) as smiley, 
    (SELECT count(*) FROM `ci_user_tag` where post_id = P.post_id) as tag, 
    (SELECT count(*) FROM `ci_comments` where post_id = P.post_id) as comment_count, 
    P.*, U.point_1 + U.point_2 + U.point_3 as `total`, F.*, Fi.*, U.* 

FROM `ci_posts` P 

LEFT JOIN `ci_users` U 
    ON P.`user_id` = U.`user_id` 
LEFT JOIN `ci_filters` F 
    ON P.`filter` = F.filter_id 
LEFT JOIN `ci_files` Fi 
    ON P.file = Fi.file_id 

WHERE P.`approve` = 1 AND U.active = 1 AND P.post_type = 'post-color' 
    AND 1 ORDER BY P.post_date DESC LIMIT 0,20 

このクエリは実行に5分かかりますが、どのように改善できますか?それはLEFT JOINまたはSELECTのためですか? テーブルの中には、10Kか​​ら100Kまでの行があることに注意してください。 何か提案がありがとうございます!左結合と選択を含む遅いmysqlクエリ

+1

質問の書式設定方法を学ぶことをお勧めします。その後、結合列にインデックスを追加することをお勧めします。 –

+0

'SQL_CALC_FOUND_ROWSは行としてNULLが無効です.'は奇妙です。 'rows'と呼ばれる結果セットにNULL列を与えます。' SQL_CALC_FOUND_ROWS'項目は、行ではなくクエリ全体の修飾語です。必要があるとわからない限り、省略することもできます。 –

+0

@ tim-biegeleisenヒントのおかげで – sezarsaman

答えて

1

これを最適化するために考慮すべき点はいくつかあります。

全体的には、http://use-the-index-luke.com/

ファーストをお読みください。このようなあなたのサブクエリは速くpost_id上の指標となります。

SELECT count(*) FROM ci_user_smiley where post_id = P.post_id 

第二:賢いプログラマは精力的に代わりに、クエリに必要な列のリストを与え、SELECT ... table.*またはSELECT列ワイルドカードのいずれかの形式*の文字を使用して回避します。クエリプランナは、結果セットからいくつかの列を省略できることがわかっているときにクエリを最適化することがよくあります。

第3位:これは悪名高いクエリの反パターンです。

SELECT lots of columns 
    FROM table JOIN table .... lots of tables 
    ORDER BY column 
    LIMIT small number 

なぜですか?これは、クエリプランナに、莫大な結果セットを生成し、ソートしてから、small number行を除くすべてを破棄するように指示します。これは無駄です。

あなたはこの

WHERE p.post_id IN (SELECT p.post_id 
         FROM ci_posts p 
         JOIN `ci_users` u 
           ON p.`user_id` = u.`user_id` 
         WHERE p.approve = 1 
         AND p.post_type = 'post-color' 
         AND u.active = 1 
         ORDER BY p.post_date DESC LIMIT 20) 

のようなものIN句はちょうど20の面白いpost_id値をフェッチを含むクエリをよりよく行うことができます。ロード/ソート/破棄の操作はpost_idpost_dateの列に制限されますが、これははるかに安くなります。 ci_posts (post_type, approve, post_date, user_id)の化合物指数は、多くの助けになります。

u.active = 1句はとにかくJOINLEFT JOINを回すので、私はJOINの代わりLEFT JOINを使用しました。

+0

それ以外の素晴らしい答えですが、その制限はアクティブなユーザーに基づいているため、まずサブ選択でJOINする必要があります。 – DRapp

+0

@DRappあなたが正しいです。ナイスキャッチ。私は私の答えを編集しました。 –

+0

@OllieJones私はMySQLのエキスパートではないので、サブクエリにインデックスを追加するにはどうすればいいですか? 投稿の制限が改ページに使用されています。 パーフェクトポイントありがとうございました! – sezarsaman

関連する問題