ランダムな行を選択することは常に注意が必要であり、妥協を伴わない完璧なソリューションはありません。パフォーマンスを妥協するか、ランダムな配布を妥協するか、重複を選択する可能性を妥協するなど。
@JakeGouldが言及しているように、ORDER BY RAND()
を使用したソリューション うまくスケーリングしません。テーブルの行数が増えると、ファイルソートでテーブル全体をソートするコストはますます悪化します。ソート順がランダムな場合、クエリをキャッシュできないというジェイクは正しいです。しかし、私は通常、とにかくクエリキャッシュを無効にするので、それほど気にしません(独自のスケーラビリティの問題があります)。
これは、rownum列を作成し、一意の連続する値を割り当てることによって、テーブル内の行を事前にランダム化するためのソリューションです。
ALTER TABLE products ADD COLUMN rownum INT UNSIGNED, ADD KEY (rownum);
SET @rownum := 0;
UPDATE products SET rownum = (@rownum:[email protected]+1) ORDER BY RAND();
これで、インデックスルックアップによってランダムな行を取得できます。なし 並べ替え:
SELECT * FROM products WHERE rownum = 1;
または、次のランダムな行を取得できます:
SELECT * FROM products WHERE rownum = 2;
または、一度に10個のランダムな行、または重複することなく他の任意の数を取得できます。
SELECT * FROM products WHERE rownum BETWEEN 11 and 20;
いつでも再ランダム化できます:
SET @rownum := 0;
UPDATE products SET rownum = (@rownum:[email protected]+1) ORDER BY RAND();
ランダムソートを実行するにはまだコストがかかりますが、すべてのSELECTクエリで実行する必要はありません。スケジュールどおりに、できればオフピーク時に行うことができます。