0

+100,000,000(1億)レコードのインデックスからランダムな結果を取得した経験はありますか?

目標は、少なくとも1秒間に100回、ランダムに並べられた30の結果を取得することです。

実際、私のレコードはMySQLにありますが、巨大なテーブルからORDER BY RAND()を選択するのが、MySQLを強制終了する最も簡単な方法です。

Sphinxsearchまたはあなたがお勧めするものは何ですか?

4

1 に答える 1

1

私は試す大きなインデックスを持っていません。

barry@server:~/modules/sphinx-2.0.1-beta/api# time php test.php -i gi_stemmed --sortby @random --select id
Query '' retrieved 20 of 3067775 matches in 0.081 sec.
Query stats:

Matches:
<SNIP>

real    0m0.100s
user    0m0.010s
sys     0m0.010s

これはかなり強力な専用サーバー上にあります-ライブクエリを処理しています(〜20qps)


しかし、正直に言うと、フィルタリングが必要ない場合 (つまり、各クエリに 'WHERE' 句がある場合) は、ランダムな結果を返すシステムをセットアップするだけで済みます。これは mysql で行うことができます。ORDER BY RAND() を使用するだけでは悪です (また、Sphinx は mysql よりもソートに優れていますが、基本的に同じことを行っています)。

あなたのデータはどの程度「まばら」ですか?ほとんどのIDが使用されている場合は、次のようなことができます

$ids = array();
$max = getOne("SELECT MAX(id) FROM table");
foreach(range(1,30) as $idx) {
   $ids[] = rand(1,$max);
}
$query = "SELECT * FROM table WHERE id IN (".implode(',',$ids).")";

(mysql から ID 順に結果を取得する可能性が高いため、後で結果に対して php で shuffle() を使用することをお勧めします)

これははるかに効率的です。穴がある場合は、おそらく 33 行を検索してください。場合によっては必要以上に取得することもありますが (破棄するだけです)、ほとんどの場合は 30 を取得する必要があります。

(もちろん、「$max」をどこかにキャッシュすることもできるので、常に検索する必要はありません。)

それ以外の場合は、専用の「シャッフル」リストをセットアップできます。基本的に、FIFO バッファには 1 つのスレッドがあり、ランダムな結果で満たされ (おそらく上記のシステムを使用して、一度に 3000 個の ID を使用)、消費者はランダムな結果をこのキューから直接読み取ります。

FIFO は、特に mysql で実装するのは簡単ではないため、別のシステムを使用する可能性があります - おそらく redis または memcache だけです。

于 2012-08-17T17:03:02.827 に答える