人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

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





●質問者: makocan
●カテゴリ:インターネット ウェブ制作
✍キーワード:GROUP MAX mixi MySQL SELECT
○ 状態 :終了
└ 回答数 : 4/4件

▽最新の回答へ

1 ● jirepo
●23ポイント

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

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


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

urlはダミーです

◎質問者からの返答

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

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

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


2 ● うぃんど
●23ポイント

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

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

◎質問者からの返答

相当高速化されました!

ありがとうございます。


3 ● ながの
●22ポイント

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

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

というものがあります。

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


4 ● iku7
●22ポイント

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

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...

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ