配列の読み取りとシャッフルには、多くの不要なデータ移動が含まれます。
ここにいくつかのアイデアがあります:
1: ランダムなサブセットが必要だと言うとき、このコンテキストでの「ランダム」とは正確には何を意味しますか? つまり、レコードは特定の順序になっていますか、それともランダム化しようとしているものに関連する順序ですか?
私の最初の考えは、レコードが適切な順序になっていない場合、合計サイズをサンプルサイズで割って計算し、n 番目のレコードごとに選択するだけでランダムに選択できるということです。たとえば、5,300 万件のレコードがあり、200 万件のサンプルが必要な場合、5,300 万 / 200 万 ~= 26 となり、26 番目のレコードごとに読み取ります。
2: それが十分でない場合、より厳密な解決策は、0 から 5,300 万の範囲で 200 万の乱数を生成して、重複がないことを保証することです。
2-A: レコードの総数に比べてサンプル サイズが小さい場合、たとえば、数百または数千を選択する場合のように、多数のエントリの配列を生成し、エントリごとに、それを以前のすべてのエントリと比較して重複をチェックします。重複している場合は、一意の値が見つかるまでループして再試行します。
Two-B: 数値が単なる例ではなく実際の値であると仮定すると、サンプル サイズは母集団全体に比べて大きくなります。その場合、最新のコンピューターに十分なメモリがある場合、false に初期化された 5,300 万個のブール値の配列を作成することで、これを効率的に行うことができます。もちろん、それぞれが 1 つのレコードを表します。次に、ループを 200 万回実行します。反復ごとに、0 ~ 5,300 万の乱数を生成します。配列内の対応するブール値を確認します。false の場合は、true に設定します。正しい場合は、別の乱数を生成して再試行してください。
3: または、待ってください。割合が比較的大きいことを考えると、さらに良いアイデアがあります。含めるレコードの割合を計算します。次に、すべてのレコードのカウンターをループします。それぞれについて、0 から 1 までの乱数を生成し、それを目的のパーセンテージと比較します。少ない場合は、そのレコードを読み取り、サンプルに含めます。それより大きい場合は、レコードをスキップします。
サンプル レコードの正確な数を取得することが重要な場合は、各レコードの割合を再計算できます。たとえば、例を単純にするために、100 レコード中 10 レコードが必要であると仮定しましょう。
10 / 100 = .1 から始めると、乱数が生成され、.04 になるとします。.04<.1 なので、レコード #1 を含めます。
ここで、パーセンテージを再計算します。残りの 99 レコードのうち、あと 9 レコードが必要です 9/99~=.0909 が得られます 乱数が .87 であるとします。それは大きいので、レコード #2 をスキップします。
再計算します。残りの 98 件のレコードのうち、まだ 9 件のレコードが必要です。つまり、マジック ナンバーは 9/98 です。等。
必要な数のレコードを取得すると、将来のレコードの可能性はゼロになるため、決して超えません。終わりに近づいて十分なレコードを取得していない場合、確率は 100% に非常に近くなります。同様に、まだ 8 つのレコードが必要で、8 つのレコードしか残っていない場合、確率は 8/8=100% になるため、次のレコードを取得することが保証されます。