php + mysql でランダムデータの抽出方法


DBからランダムデータを10個抽出するのに

SELECT id,contents FROM table ORDER BY rand() LIMIT 10;

みたいな書き方をしていたんですが、

最初のうちはよかったんですが、
テーブルが1万越えてきたあたりからやったら遅くなってきて、
Copying to tmp table連発で激重+コネクション圧迫が
ひどくなってきたので改善することに。

とりあえず当該テーブルで explain するとこんなかんじ

EXPLAIN SELECT id,contents FROM table ORDER BY rand() LIMIT 10

table 	        table
type 	        ALL
possible_keys 	NULL
key 	        NULL
key_len 	NULL
ref 	        NULL
rows 	        29302
Extra	        Using temporary; Using filesort

rows :29302 なので全件走査(良く考えたら当たり前か。。)
なので Using temporary してるわけで、
SQLでなんかできるかなというのは無理だったので、
phpで対応することに。
対応っていっても、簡単にこんな感じで直しただけで劇的に速度が上がりました。

//件数を取得して $count にいれて、
SELECT count(*) as count FROM table;

//0 ~ $count までの配列を作ってそれをランダムに10個取り出して , で join してIN句に突っ込む
"SELECT id,contents FROM table WHERE id IN (".join(',',array_rand(range(0,$count),10));"

Leave a Reply