Hatena::ブログ(Diary)

naoyaのはてなダイアリー

November 18, 2005

MySQL の order by rand()

MySQL のレコード取り出しの際に、ソートをランダムにできないものかと調べていたら、あった。

SELECT * FROM table ORDER BY RAND()

こんな感じで。ソートを RAND にすれば良いという…

MySQL でランダム表示 - Ceekz Logs

そうそう、僕もこれは最近知ったんですが。Haropy でエントリーをランダムに取り出すのにも order by rand() を使ってます。Class::DBI::mysql に retrieve_random というメソッドがあって、ランダムに一見取り出すことができるという。これも中では order by rand() limit 1 をやってます。

ただ、この rand() はデータ量が大きいテーブルには使いづらいという罠。

mysql> explain select id from entry order by rand() limit 1 ?G
*************************** 1. row ***************************
        table: entry 
        type: indexpossible_keys: NULL  
        key: PRIMARY
        key_len: 32  
        ref: NULL
        rows: 3794
        Extra: Using index; Using temporary; Using filesort
1 row in set (0.00 sec)

インデックスをかけてるテーブルでも、結局ランダムなので全件捜査してから値を返す。プライマリーキーに対して rand() する場合でも O(1) ではないのですよね。なんか回避する方法があったりするのかな。

追記

limit 1 のあとの「?G」に見えるのはなんか Mac のターミナルからコピるとこうなっちゃう罠。ほんとはバックスラッシュ。どうやって直すのこれ。

bakelattabakelatta 2005/11/18 13:50 Firefoxを使えば化けないはずです。
http://i.hatena.ne.jp/idea/6258

askadnaaskadna 2005/11/19 03:24 PostgreSQLでやってみました。
aska=# select *, random() from post order by random;
id | tid | random
----+-----------+---------------------
5 | {1,2,5} | 0.00763613777590736
1 | {1} | 0.0908717699772081
6 | {1,2,5,6} | 0.248818963416302
3 | {1,2,3} | 0.583180555879688
2 | {1,2} | 0.667497599808265
4 | {1,2,3,4} | 0.948708495566951
(6 rows)

TigerTiger 2005/11/19 20:13 もしかして、OS 古くないですか A^^;

nawatobinawatobi 2006/01/18 22:47 order by rand()を使ったらいいんじゃないか会議が、
いましがた社内で行われたのですが、
naoya氏のこの情報にぶちあたってあきらめました。

naoyanaoya 2006/01/19 06:21 order by rand() で会議。。。