1

使用しているクエリがありますORDER BY RAND()が、時間がかかりすぎて、データが大きくなるにつれて悪化しています。

クエリは 2 つのテーブルを結合し、5 つのランダムな製品と各製品のランダムな画像を返します

表 1 - 製品

product_id - pk auto-inc
name 
description

データ

1 - product 1 - description
2 - product 2 - description

表 2 - 製品イメージ

image_id   - pk auto-inc
product_id - fk index
filename

データ

1 - 1 - product 1 image
2 - 1 - product 1 image
3 - 1 - product 1 image
4 - 2 - product 2 image

...

これこれを読みましたが、クエリを最適化する方法が見つからないため、助けを求めています。前もって感謝します。

4

1 に答える 1

5

ORDER BY RAND()DBMS はすべての行を読み取り、すべての行を並べ替えて、数行だけを保持する必要があるため、処理が遅くなります。したがって、このクエリのパフォーマンスはテーブル内の行数に大きく依存し、行数が増えると低下します。

それを最適化する方法はありません。

ただし、代替手段があります。

6 つのクエリを実行することで、 「5 つのランダムな行を取得」を実装できます。

  • テーブル内の行数を取得します (これをキャッシュできます)
  • で5つのクエリを実行しますOFFSET <random offset from 0 to $number_of_rows-1> LIMIT 1(つまり、ランダムなオフセットから1行だけを読み取って返します)

    例: SELECT * FROM Products OFFSET 42 LIMIT 1(注: 今のところ、参加せずに)

    このようなクエリは非常に高速で、テーブルのサイズとは実質的に無関係な時間で実行されます。

これはよりもはるかに高速ですORDER BY RAND()


ここで、ランダムな製品ごとにランダムな画像を取得するには:

SELECT *
FROM (
    SELECT *
    FROM Products
    OFFSET 42 LIMIT 1
) p
JOIN ProductImages pi
ON   pi.product_id = p.id
ORDER BY RAND()
LIMIT 1

内側のクエリは依然として高速であり、外側のクエリは数行しか並べ替えていないため (製品ごとの画像が少ないと仮定して)、rand() による順序を引き続き使用できます。

于 2013-05-27T17:22:39.020 に答える