2016-09-13 19 views
0

最初のものが最初です:私は同様の質問を探しましたが、何が私が行っていることが悪い習慣であるのかを説明するものは何も見つかりませんでした。非常に基本的なもの。非常に大量のデータを含むSQLクエリを最適化する

DBに負荷がかかりすぎているとの苦情を受けましたが、最適化の方法がわからないので、ここで助けを求めています。

私は下部に取り組んでいる構造の写真を添付し​​ました。私は何をしようとしているのですか: 特定のuserActionを実行した人のリストを取得する必要があります( 'viewProduct'と言い、userAge、国および大陸に関するその人の情報を追加してください)

select u.userId, u.userAge, c.countryName, co.name, ul.createdTime, 
     ul.userAction 
    from user_log as ul 
    left join user as u ON u.userId = ul.userId 
    left join country as c ON c.id = u.userCountryId 
    left join continent as co ON co.id = c.continentId 
    where ul.createdTime > '2016-06-01' 
     and u.userAge > 40 
     and (ul.userAction like 'viewProduct' 
       or ul.userAction like 'storeProduct' 
       or ul.userAction like 'addProduct' 
      ); 

そして、これは明らかに十分ではありませんので、私は心から誰かがこれをより効率的にする方法について助けることができるかもしれないことを願って、私は非常にテーブルを扱うには慣れていない:以下を書か

アイブ何百万ものエントリがあります。

ありがとうございました!

db structure

+1

'join'sと' where'で使用するカラムにインデックスがありますか? – Shnugo

+0

ユーザデータは毎回4つのテーブルすべてに存在するか、それともそれが依存しているかです。不適切な方法で使用している別のものは、検索条件に従ってテキストの前後に%記号を使用します。クエリプランを最適化するための – Susang

+0

が役に立ちます。 1つの質問はあなたのIDにあなたが参加しているIDにインデックスがあるかどうかです。 – Nebi

答えて

0

は、クエリ内の夫婦の問題があります。

  1. あなたが制限なしのインデックスを持っていない場合 - MySQLは結果を与えるUSER_LOGからすべての億件のレコードをチェックします。処理されるレコードの量を減らすには、 "ul.createdTime"と "ul.userAction"にインデックスを追加します。これは合成されたインデックス(createdTime、userAction)でさえできます。
  2. "ul.userAction like 'viewProduct'"は "ul.userAction = 'viewProduct'"と等しくなります。 "viewProduct '、" storeProduct "、" addProduct ")でul.userActionにリファクタリングすることができます。
  3. " u.userAge> 40 "を結合条件に移動します。また、 "u.userAge"のインデックスも多くの助けになります。
  4. 私はあなたのデータに依存しているかどうかはわかりませんが、時には "inner join user as u"が速く、 "left join user as u"の方が速く動作するかもしれません。あなたはここで遊ぶことができます。 (ただし、クエリのロジックは変更されます)

100000000個のレコードを持つテーブルにインデックスを追加する作業は長い作業です。だから、テスト目的のために、最後の1000000レコードだけを持つ "user_log"のコピーを作成し、そのパフォーマンスを測定します。上記のすべてのインデックスを追加して、このクエリをテストします:

select u.userId, u.userAge, c.countryName, co.name, ul.createdTime,  ul.userAction 
from user_log as ul 
left join user as u 
    on u.userId = ul.userId and u.userAge > 40 
left join country as c 
    on c.id = u.userCountryId 
left join continent as co 
on co.id = c.continentId 
where ul.createdTime > '2016-06-01' and 
ul.userAction in('viewProduct', 'storeProduct', 'addProduct'); 

..と比較パフォーマンス。

お願いします。お手伝いしますか?

+0

これを反転させます - '(userAction、createdTime)'。インデックスの使用は、最初の "範囲"( 'createdTime> ...') –

+0

また、' = 'で始まり、それから範囲は'(userId、userAge) 'で始まります。 –

関連する問題