MySQLで質問です。


今、mixiのマイページの「新着の更新情報」と同等の機能を実装しているのですが
動作がもっさりしてしまいます。
副クエリを使用して、ユーザー毎の最新の情報を取得しております。

下記の様な形で書いております。
※一部を抜粋しておりますため、間違いがあるかもしれません。

SELECT * FROM メッセージを扱うテーブル名 a
WHERE (a.ユーザーID名,a.日付のフィールド名) IN(SELECT a.ユーザーID名,max(o.日付のフィールド名) FROM メッセージを扱うテーブル名 o GROUP BY o.ユーザーID名)
ORDER BY a.日付のフィールド名 DESC;

ただ、mixiと同様に、公開制限などもあるため、それを副クエリ側に入れております。
何か、良い改善方法はございませんでしょうか?



回答の条件
  • URL必須
  • 1人2回まで
  • 登録:
  • 終了:2010/10/10 11:40:03
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

回答4件)

id:jirepo No.1

回答回数30ベストアンサー獲得回数6

ポイント23pt

a.ユーザーID名,a.日付のフィールド名でindexは作成してありますか?

もし未作成ならば作成することでパフォーマンスが改善します。


http://q.hatena.ne.jp/

urlはダミーです

id:makocan

はい。しております。。。

副クエリ内でも、公開制限などのために、テーブルの連結をしており、

そこももっさりの原因の一つのようです。。

2010/10/03 12:14:03
id:windofjuly No.2

回答回数2625ベストアンサー獲得回数1149

ポイント23pt

サブクエリは一度展開されてしまうので対象レコードを絞り込んだほうがよいように思われます

  WHERE o.ユーザーID名 = a.ユーザーID名

GROUP BYでは対象レコードを総なめしてしまうので、逆から1レコード目だけを取得するほうがよいように思われます

  ORDER BY o.日付のフィールド名 DESC LIMIT 0,1

SELECT * FROM メッセージを扱うテーブル名 a
WHERE a.日付のフィールド名 = (SELECT o.日付のフィールド名 FROM メッセージを扱うテーブル名 o WHERE o.ユーザーID名 = a.ユーザーID名 ORDER BY o.日付のフィールド名 DESC LIMIT 0,1)
ORDER BY a.日付のフィールド名 DESC;

LIMITよりもMAXだけのほうが高速かもしれません

SELECT * FROM メッセージを扱うテーブル名 a
WHERE a.日付のフィールド名 = (SELECT max(o.日付のフィールド名) FROM メッセージを扱うテーブル名 o WHERE o.ユーザーID名 = a.ユーザーID名)
ORDER BY a.日付のフィールド名 DESC;

オリジナルならびに上記2例で比較してみてください

http://dev.mysql.com/doc/refman/5.1/ja/explain.html

id:makocan

相当高速化されました!

ありがとうございます。

2010/10/03 13:29:13
id:nobuchiru No.3

回答回数55ベストアンサー獲得回数3

ポイント22pt

SQLチューニングの手法で、

「INよりもEXISTSの法が速い」

というものがあります。

http://www.geocities.jp/mickindex/database/db_optimize.html#Loca...

id:iku7 No.4

回答回数6ベストアンサー獲得回数1

ポイント22pt

拝見したところこのクエリでは確かに遅い気がします。

MS系のRDBがこの記述でも早かったかと・・

副問合せ

IN(SELECT a.ユーザーID名,max(o.日付のフィールド名)

これをwhere句の中ではなく、

fromの中に入れるとレスポンスが向上します

SELECT * FROM メッセージを扱うテーブル名 a,

(SELECT a.ユーザーID名,max(o.日付のフィールド名) mmax FROM メッセージを扱うテーブル名 o GROUP BY o.ユーザーID名) aa

WHERE (a.ユーザーID名,a.日付のフィールド名) = aa.mmax

ORDER BY a.日付のフィールド名 DESC;

もっと具体的に

SELECT at.ユーザーID名,at.日付のフィールド名,aa.mmaxdt FROM メッセージを扱うテーブル名 a at,

(SELECT a.ユーザーID名,max(o.日付のフィールド名) mmaxdt FROM メッセージを扱うテーブル名 o GROUP BY o.ユーザーID名) aa

WHERE (a.ユーザーID名,a.日付のフィールド名) = aa.mmaxdt

ORDER BY 2 DESC;

※参考イメージで、あくまで一例です。


要はビューを一つ定義し、fromのなかにエイリアスとして配置することです。

※この場合、aaがINの中に入っていたselect文のエイリアスになります。

試してみてください。


http://jibun.atmarkit.co.jp/lskill01/rensai/bronzesql09/bronzesq...

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません