2012-03-13 32 views
1

私は、MySQLクエリでひどい時間を過ごしています。私は週末のほとんどを今日過ごしました。そして今日、このクエリを少し早く実行しようとしている今日のほとんどの日です。私はそれをかなり速くしましたが、私はそれをより良くすることができます。MySQLクエリの最適化 - ランダムレコード

SELECT m.id,other_fields,C.contacts_count FROM marketingDatabase AS m 
LEFT OUTER JOIN 
(SELECT COUNT(*) as contacts_count, rid 
    FROM contacts 
    WHERE status = 'Active' AND install_id = 'XXXX' GROUP BY rid) as C 
ON C.rid = m.id 
WHERE (RAND()*2612<50) 
    AND do_not_call != 'true' 
    AND `ACTUAL SALES VOLUME` >= '800000' 
    AND `ACTUAL SALES VOLUME` <= '1200000' 
    AND status = 'Pending' 
    AND install_id = 'XXXXX' 
ORDER BY RAND() 

は、私が「install_id」、「カテゴリ」と「状態」が、EXPLAIN、それは9100行に基づいてソートされた番組にインデックスを持っています。

私の説明はここにある: https://s3.amazonaws.com/jas-so-question/Screen+Shot+2012-03-13+at+12.34.04+AM.png

誰もが、私はこれは少し速く作るために何ができるか上の任意の提案がありますか?クエリの全ポイントは、販売数量、ステータス、do_not_callなどの特定の条件に一致するアカウントレコード(install_id)からランダムレコードを選択することです。私は現在、25のレコードを集めてキャッシュしています(PHPを使用しているため)。このクエリは25回のリクエストごとに1回だけ実行する必要がありますが、すでに1日あたり何千ものリクエストを処理しています。現在、実行には0.2秒かかります。 ORDER BY RAND()を使用することで、すでに大きなパフォーマンスを達成していますが、25行をソートするだけです。

ご協力いただきありがとうございます。

**編集: 'contact_sort'インデックスは 'contacts'テーブルにあり、インデックスはinstall_id、status、およびridです。 (レコードIDはmarketingDatabase内のレコードIDを参照して、連絡先がどのレコードに属するかを知るようにします。

** EDIT 2:クエリの2612番号は、条件に一致するmarketingDatabase内の行の数を表します(install_id、status、私はあなたのインデックス定義が表示されていないので、ボリュームなど)

+0

http://dev.mysql.com/doc/refman/5.0/en/group-by-optimization.htmlをご覧ください。 GROUP BYとインデックスを使用する際に発生する制限と複雑さがあります。マニュアルを引用する "GROUP BYの索引を使用するための最も重要な前提条件は、すべてのGROUP BY列が同じ索引の属性を参照し、索引がそのキーを順番に保管することです(たとえば、これはBTREE索引であり、HASHインデックス)インデックスされていないフィールドでグループ化し、サブクエリでテーブル全体を選択して並べ替えます。 RAND()による並べ替えも悪い考えだと思います。 – fred2

+0

ORDER BY RAND()は非常に、非常に[悪い考えです](http://www.webtrenches.com/post.cfm/avoid-rand-in-mysql)です。 – budwiser

+0

ORDER BY RAND()が25行しか注文していないので、読んだことはありますが、それは悪い考えです。それはそれほど大きな問題ではありません。私が間違っている? これを修正するにはどうすればよいですか?ギャップなしで自動インクリメントの列を持っていません...私のID列は自動インクリメントですが、行が削除されたギャップがあります。 – user1265617

答えて

0

私はいくつかのクエリをいじって、私はあなたがインデックス付きクエリを取得することができるでしょうとは思わないのコンポジットインデックス(install_id、ステータス、 `実際の販売VOLUME`)特にWHERE句とORDER BY句の両方でRAND()を使用している場合は、RAND()を使用します。可能であれば、私のPHPロジックにランダム要素を導入し、2つの単純なクエリがかなり複雑なものよりも理にかなっているかどうかを見てみましょう。それに加えて、ランダムな結果セットでLEFT OUTER JOINがあります。これにより、多くの作業を増やす必要があります。

要約すれば、私の推測は、RANDを除外するように書き直して、LEFT OUTER JOINを取り除くことができるかどうかを見てください。その間に少しのPHPを持つ2つの直接的な索引付き問合せが、より良い可能性があります。

+0

これは意味があります。このことについてどうすればいいですか?条件を満たすDBのすべてのレコードを照会し、array_rand()を使用してランダムな要素を選択しますか? – user1265617

+0

私はあなたがなぜランダムな要素を必要としているのか本当にわからないので、言うのは難しいですが、それは妥当と思えます。あなたは2612のエントリしか持っていないので、テーブル全体を返すことはそれほどひどくはありません。少なくともクエリはキャッシュされるので、それはMySQLとおそらくはPHPの見方からの落とし穴になります。 – fred2

1

、私は彼らが正しいか確認していないクエリは次のインデックスの恩恵を受ける:。

  1. 複合指数(install_id、ステータス、除外)については、contacts

  2. marketingDatabase

+0

うん、それはまさに私が現在インデックスのために持っているものです。 – user1265617