4

約 700 万のレコードを保持するテーブルから 4 つのランダムな結果を取得しようとしています。さらに、同じテーブルから、カテゴリ別にフィルター処理された 4 つのランダム レコードも取得したいと考えています。

ここで、この大きなテーブルでランダムな並べ替えを実行すると、クエリに数秒かかることが想像できますが、これは理想的ではありません。

結果セットについて私が考えたもう1つの方法は、non-filteredPHPに1〜7,000,000程度の乱数を選択させIN(...)、クエリを実行してそれらの行のみを取得することです-そして、はい、このメソッドにはその ID を持つレコードが存在しなくなった場合、4 未満になる可能性があることに注意してください。

ただし、PHP はどのレコード番号がどのカテゴリに属しているかがわからないため、選択するレコード番号を選択できないため、上記の方法は明らかにカテゴリ フィルタリングでは機能しません。

これを行うことができるより良い方法はありますか?私が考えることができる唯一の方法は、各カテゴリのレコード ID を別のテーブルに保存し、そこからランダムな結果を選択してから、セカンダリ クエリでメイン テーブルからそれらのレコード ID のみを選択することです。しかし、もっと良い方法があると確信しています!?

4

4 に答える 4

2

もちろん、 (カテゴリに対して) andRAND()を使用してクエリで関数を使用することもできます。ただし、ご指摘のとおり、特にデータ量が多いため、データベースのスキャンに時間がかかります。LIMITWHERE

ご指摘のとおり、別のテーブルに id/category_id を保存する別の方法は、少し高速になる可能性がありますが、そのテーブルには、マスター テーブルと同じ量のレコードも含まれるLIMITandが必要です。WHERE

別のアプローチ (該当する場合) は、カテゴリごとにテーブルを作成し、その中に ID を格納することです。カテゴリが固定されているか、それほど頻繁に変更されない場合は、そのアプローチを使用できるはずです。その場合WHERE、句からを効果的に削除し、各カテゴリ テーブルでを取得するRAND()と、メイン テーブルのレコードのサブセットが含まれるため、高速になります。LIMIT

他のいくつかの代替手段は、その操作のためだけにキーと値のペアのデータベースを使用することです。MongoDb や Google AppEngine はこれに役立ち、非常に高速です。

MySQL でマスター/スレーブのアプローチに進むこともできます。スレーブはリアルタイムでコンテンツをレプリケートしますが、負荷の高いクエリを実行する必要がある場合は、マスターではなくスレーブにクエリを実行して、負荷を別のマシンに渡します。

最後に、インストールと保守がはるかに簡単な Sphinx を使用できます。次に、これらの各カテゴリ クエリをドキュメント検索として扱い、Sphinx に結果をランダム化させることができます。このようにして、この高価な操作を別のレイヤーにオフセットし、MySQL に他の操作を続行させます。

考慮すべき問題がいくつかあります。

于 2012-09-10T17:45:44.363 に答える
1

まず、行数を取得する必要があります...このようなもの

select count(1) from tbl where category = ? 次に、乱数を選択します

$offset = rand(1,$rowsNum); オフセットのある行を選択します

select * FROM tbl LIMIT $offset, 1

このようにして、IDの欠落を回避します。唯一の問題は、2番目のクエリを数回実行する必要があることです。この場合、ユニオンが役立つ可能性があります。

于 2012-09-10T17:54:06.573 に答える
1

乱数アプローチの作業

  • データベースの最大 ID を取得します。
  • 一致を保存する一時テーブルを作成します。
  • 次のように n 回ループします。
    • 1 から maxId までの乱数を生成します
    • 乱数より大きいレコード ID を持つ最初のレコードを取得し、それを一時テーブルに挿入します
  • 一時テーブルにランダムな結果が含まれるようになりました。

または、ユニオンを使用して sql を動的に生成し、1 つのステップでクエリを実行することもできます。

   SELECT * FROM myTable WHERE ID > RAND() AND Category = zzz LIMIT 1
   UNION
   SELECT * FROM myTable WHERE ID > RAND() AND Category = zzz LIMIT 1
   UNION
   SELECT * FROM myTable WHERE ID > RAND() AND Category = zzz LIMIT 1
   UNION
   SELECT * FROM myTable WHERE ID > RAND() AND Category = zzz LIMIT 1

注:私はmySqlの人ではないので、私のSQLは有効ではないかもしれませんが、理論は正しいはずです

于 2012-09-10T17:52:05.963 に答える
-1

MySQlの場合、使用できます

ランド()

SELECT column FROM table
ORDER BY RAND()
LIMIT 4
于 2012-09-10T17:45:04.377 に答える