質問: tlst.name and wlst.inserted < tlst.inserted and tlst.inserted < wlst.inserted + 259200) ) ); ``` と、書いて結果は得られるのですが非常に遅く、ネットなどで検索するとMySQLのin+サブクエリーは遅いのでjoinに書き換えた方が良いといった意見なども見受けられました。 AWSのRDS(large)などでテストしても各テーブルが数千件を超えるとまともに結果が返却されない(数十分かかってタイムアウト)といった状態です。 nameが同一で、3日以内のレコードが1件以上存在する(0<)ということを条件にしてweb_listからidを列挙してきているのですが......、もっと高速にSQLを書き換えられないものでしょうか。 質問のために一部SQLを変更していましたが、自己検証を繰り返しているうちに端折っているINSERT文+INの組み合わせが非常に時間を掛けていることが分かってきました。この点も踏まえてコメントをいただけるとありがたいです。 master, web_list, tel_listのidを主キーにして速度が上がりました。しかしながら、まだかなり遅い印象で、まだ速くなる余地はないでしょうか。(tell_list, web_list共に2万件で1分ほど掛かります) **web_list** ``` id|name|inserted 11|bob |2016/09/01 12:00 12|mary|2016/09/01 13:00 15|mary|2016/09/05 10:00 16|bob |2016/09/06 15:00 ``` **tel_list** ``` id|name|inserted 13|bob |2016/09/02 17:00 14|bob |2016/09/03 15:00 17|bob |2016/09/07 15:00 18|bob |2016/09/07 18:00 19|mary|2016/09/10 10:00 ``` 上記のようなイメージです。 この場合、INのサブクエリーで得られるID一覧は 11, 16 となります。
回答: **updateが遅いとしたら** masterのレコード数が膨大でidにindexが無いためか、単純に件数が膨大過ぎる場合でしょう「update master set flag=1 where ....」ですからね。基本的にwhere句以前には改善点がありません。 物理的に更新行が多すぎるなら改善は難しいです。PCスペックを上げるとか? **目的のIDを抽出するsql** 多分次のように成ると思いますが、これは早いでしょうか? ``` SELECT w.id FROM web_list AS w LEFT JOIN tell_list AS t ON w.name = t.name WHERE w.inserted < t.inserted AND t.inserted <= w.inserted + INTERVAL 3 DAY GROUP BY w.id ``` これが早いなら、in句が遅いか、冒頭で書いたようにmasterのレコード数が膨大な上indexが適当でないかのどちらかが原因かと思います。EXISTSに変更してみるか、masterのidにindex(プライマリキーにしているなら不要)を作成してみると良いかも知れません。 逆にこれが遅いならweb_listかtell_listのレコード数が膨大でindexが適切でないためだと思います。 nameに重複が少ないならname、またinsertedへのindexの作成を検討する必要があるかも知れません。 in句やdistinctはmysql5.1 以前だとやたら遅くなるケースがあったように思います。ただ特定のケースでindexが使えて無いことに起因してたように思うので、そもそもindexを作成していないなら関係無いと思いますし、5.4以降だとそんなことも無い気がします...