2017-03-03 9 views
0

私は約400kの行を持つユーザーテーブルを持っていて、他のテーブルで複数のJOINSを実行している間に、そのうちのいくつか(最大100)を取得する必要があります。 (mysqlの使用)どのようにこの低速のSQLクエリを最適化できますか?

私の問題は、クエリの実行時間が現在約800ms(46msフェッチ)であることです。私の目標は、この実行時間を短縮するためにクエリを最適化することです。

私の最初のクエリは次のようになります。

SELECT iduser, imageurl, birthdate, active, last_active, created, gender_idgender, orientation_idorientation, region_idregion, moji.moji_idmoji as moji_idmoji, status.value as status, requests.value as requestsRecv, requestssent.value as requestsSent, username.value as username, likecount.value as likeCount, reportcount.value as reportCount 
FROM user u 
    JOIN user_has_moji moji ON (u.iduser = moji.user_iduser) 
    JOIN user_has_data status ON (u.iduser = status.user_iduser AND status.datatype_iddatatype = 1) 
    JOIN user_has_data requests ON (u.iduser = requests.user_iduser AND requests.datatype_iddatatype = 3) 
    JOIN user_has_data requestssent ON (u.iduser = requestssent.user_iduser AND requestssent.datatype_iddatatype = 4) 
    JOIN user_has_data username ON (u.iduser = username.user_iduser AND username.datatype_iddatatype = 5) 
    JOIN user_has_data likecount ON (u.iduser = likecount.user_iduser AND likecount.datatype_iddatatype = 6) 
    JOIN user_has_data reportcount ON (u.iduser = reportcount.user_iduser AND reportcount.datatype_iddatatype = 7) 
WHERE banned = 0 AND active = 1 AND u.reviewstatus_idreviewstatus = 3 AND DATEDIFF(last_active,'2017-03-03 10:06:36') >=0 AND DATEDIFF(birthdate, '1999-03-03 15:06:36') >= 0 AND DATEDIFF(birthdate, '1967-03-03 15:06:36') <= 0 ORDER BY last_active DESC LIMIT 100 

私は長い実行時間のためにその理由が、私はこのアプローチを試してみましたので、クエリを実行する前に、それは他のテーブルと全体のユーザーテーブルを結合するために持っているということであると思いました:

SELECT iduser, imageurl, birthdate, active, last_active, created, gender_idgender, orientation_idorientation, region_idregion, moji.moji_idmoji as moji_idmoji, status.value as status, requests.value as requestsRecv, requestssent.value as requestsSent, username.value as username, likecount.value as likeCount, reportcount.value as reportCount 
FROM (SELECT * FROM user WHERE banned = 0 AND active = 1 AND reviewstatus_idreviewstatus = 3 AND DATEDIFF(last_active,'2017-03-03 10:01:30') >=0 AND DATEDIFF(birthdate, '1999-03-03 15:01:30') >= 0 AND DATEDIFF(birthdate, '1967-03-03 15:01:30') <= 0 ORDER BY last_active DESC LIMIT 100) as u 
    JOIN user_has_moji moji ON (u.iduser = moji.user_iduser) 
    JOIN user_has_data status ON (u.iduser = status.user_iduser AND status.datatype_iddatatype = 1) 
    JOIN user_has_data requests ON (u.iduser = requests.user_iduser AND requests.datatype_iddatatype = 3) 
    JOIN user_has_data requestssent ON (u.iduser = requestssent.user_iduser AND requestssent.datatype_iddatatype = 4) 
    JOIN user_has_data username ON (u.iduser = username.user_iduser AND username.datatype_iddatatype = 5) 
    JOIN user_has_data likecount ON (u.iduser = likecount.user_iduser AND likecount.datatype_iddatatype = 6) 
    JOIN user_has_data reportcount ON (u.iduser = reportcount.user_iduser AND reportcount.datatype_iddatatype = 7) 

結合する必要がある行の数が大幅に削減され、実行時間が短縮されると考えます。この変更はちょっと役に立ったようですが、クエリがまだ低すぎます。

誰かが遅い実行の他の理由を見ることができますか?

+2

合理的な応答時間のようです... – jarlh

+1

クエリは固いと思われ、インデックスの改善を提案します... – JohnHC

答えて

3

あなたは非常に合理的な応答時間を持っているため、テーブルのインデックスが適切に表示されます。しかし、のはWHERE句(私は推定表の別名を追加しました)を見てみましょう:

WHERE u.banned = 0 AND u.active = 1 AND 
     u.reviewstatus_idreviewstatus = 3 AND 
     DATEDIFF(u.last_active,'2017-03-03 10:06:36') >=0 AND 
     DATEDIFF(u.birthdate, '1999-03-03 15:06:36') >= 0 AND 
     DATEDIFF(u.birthdate, '1967-03-03 15:06:36') <= 0 

まず、datediff()を削除し、単純な比較を行います。

WHERE u.banned = 0 AND u.active = 1 AND 
     u.reviewstatus_idreviewstatus = 3 AND 
     u.last_active >= '2017-03-03 10:06:36' AND 
     u.birthdate >= '1999-03-03 15:06:36' AND 
     u.birthdate <= '1967-03-03 15:06:36' 

が、私は最後の三つの条件について少し怪しいんだけど、 datediff()を使用して混乱して:私はあなたがこれをしたいと思います。それが単純な比較がより良い理由の1つです。

次の2つの指標の一つを示唆している、すぐにこれらの行を見つける必要がある:

users(banned, active, reviewstatus_idreviewstatus, last_active, birthdate) 

または

users(banned, active, reviewstatus_idreviewstatus, birthdate, last_active) 

これは、より多くのデータをダウンwhittlesいるに依存します。私の推測は、last_activeがより重要であるということです。また、最初の3つのキーは、最初の3つのキーであれば、どのような順序でも構いません。

これは役に立ちますが、壮大な改善が見られるのではないかと思います。

+0

ありがとうございましたacutally少し助けてくれました:) –

+0

どのくらい速いですか? –

+0

100〜200 ms速く –

関連する問題