質問: `goods`.`artist_id`\ WHERE (`events`.`created_at` BETWEEN '2017-01-01' AND '2017-07-30')\ AND (`goods`.`created_at` BETWEEN '2017-01-01' AND '2017-07-30')\ GROUP BY artists.user_id, artists.staff_id; ``` SQLの速度改善をしたいのですが、これ以上絞り込む条件がないため、 SQL文の見直しにより、改善できる方法を探しております。 尚、バッチ処理にするという案は今回の要件上NGでした。 生のSQL文で記述しておりますが、実際はRuby on Railsのアプリケーション上で実行します。 その為、非同期処理というのも模索しておりますが、今回、集計した結果をDBにINSERTするため、 非同期処理にすると、本来データが入ってほしいレコードにデータが入らないという恐れを懸念しております。 INNER JOIN を LEFT OUTER JOIN にしたり等、不勉強ながら試行錯誤しておりますが、なかなか改善につながりません。 理想は1~2分で完了してほしいです。 また、この集計処理は、期間を変えて実行することはあっても、同じSQL文を何度も使うということはないので、 クエリキャッシュをするというのもあまり意味がないと思っております。 また、外部キー周りにindexキーはつけております。 宜しくお願い致します。
回答: 最近、似たような形のSQLチューニングの仕事しました。 (同じ人が作ったSQLですか?と思ってしまうくらい似てます。 元々1時間以上かかる処理で、その方も理想は1~2分での完了が希望で、 ダメならバッチ処理を検討してました。) その仕事では、意図する抽出結果のSQLを作成して、 1秒以内に終わる処理にチューニングしたので、 ちゃんとチューニングしてあげれば、 恐らく数秒程度で終わるSQLになります。 あと、記載されているSQLだと、抽出結果が意図しない結果になる可能性が非常に高いです。 artistsテーブルの1行に対して、 events.sumとgoods.sumがそれぞれ複数存在する場合を考慮していないSQLです。 explainをすると、おそらく「Block Nested Loop」あたりが出てくると思いますが、 まずは、チューニングの前に、意図した抽出結果になるSQLを作ることをお勧めします。