3

私の現在のクエリはそのように見えます

SELECT *
FROM uploads
WHERE approved = 1
    AND (up-down) >= 3
ORDER BY RAND()
LIMIT 10

これは、DB から少なくとも 3 つ以上の好きなものが嫌いなものよりも多い 10 個のエントリをランダムに選択することです。

問題は、DB に 40,000 を超えるエントリがあり、このクエリに少なくとも 1 秒かかるためです。

私はグーグルでたくさん読みましたが、これまでのところ何も見つかりませんでした。

私の場合、あなたが推奨する代替手段はありますか?

4

2 に答える 2

1

一致するすべてのレコードをメモリにロードしていて、それらがあまり多くない場合、最も簡単な答えはorder by、SQL に をドロップし、アプリケーション ソフトウェアでそれらをランダムに並べ替えることです。たとえば、PHP を使用している場合は、単純にそれらすべてを配列にロードしてから を呼び出すことができますarray_rand()

これが適切な答えではない場合でも、DB でそれらをソートする必要があります。order by rand()速度が遅すぎる場合 (つまり、大量のデータがあるほとんどの場合)、私が知っている最善の解決策は次のとおりです。次のとおりです。

テーブルに新しい列を追加し、各レコードの主キーの MD5 ハッシュを事前に入力します。そして、新しいフィールドで並べ替えるインデックスを追加します。

これにより、テーブルの均等に分散されたランダムな並べ替え順序が得られます。order byの代わりに単にこのフィールドrand()

于 2012-09-16T17:02:27.687 に答える
0

最適なアプローチは、さまざまな要因によって異なります。ここにいくつかのアイデアがあります。

インデックスがないと仮定すると、クエリの現在のバージョンは、テーブル全体のスキャンを実行し、行を抽出し、乱数を割り当て、行を並べ替え、これらの最初の 10 個を選択します。

テーブル全体のスキャンは最初は遅いかもしれませんが、テーブルがメモリに収まると仮定すると、その後はかなり速くなるはずです。パフォーマンスの問題は、クエリの最初のインスタンスではなく、テーブルが既にページ キャッシュにあるインスタンスに関係していると仮定します。

「承認済み」が非常に選択的である場合 (たとえば、行の 1% が承認されている場合)、承認済みのインデックスを作成することでクエリを高速化できる場合があります。

次の代替案は、「アップ - ダウン」の列を追加し、承認済みと UpMinusDown の 2 つのキーにインデックスを作成することです。これが選択的であると仮定すると、速度が低下する可能性があります。

rand()次の質問は、 を他の基準 (たとえば、最新の 10 件) に置き換えることができるかどうかです。その場合は、UploadID などの主キーを含めて、それを並べ替えに使用できます。それはより速く行くでしょう。

最後に、レコードが非常に広い場合は、時間がかかる可能性があります。この場合、次のバージョンのクエリのパフォーマンスが向上するかどうか疑問に思います。

SELECT *
FROM uploads u left outer join
     (select UploadID
      from uploads
      WHERE approved = 1
            AND (up-down) >= 3
     ORDER BY RAND()
     LIMIT 10
    ) random
    on u.UploadID = random.UploadID

(これは、UploadID というテーブルに主キーがあることを前提としています。)

このバージョンでは、UpLoadID でのみ並べ替えを実行し、インデックスを使用して元のデータに結合する必要があります。

于 2012-09-16T16:58:32.807 に答える