テーブルの内容をランダム化し、それらをテーブルに保存する
-
16-10-2019 - |
質問
少なくとも100万のレコードが入っているテーブルがあります。これらの行は、いくつかのSharePointサイトコレクションを読み取り、テーブルにアイテムURLを保存するカスタムアプリによって作成されました。現在、サイトコレクションをシリアル方法で読んでいるので、最初の数千の行が最初のサイトコレクションに属し、次の数千が2番目のサイトコレクションなどに属します。
このテーブルを連続的に読み取る別のアプリがあります。ただし、このようにして、HTTPリクエストを同じサイトコレクションに長時間送信することになります。
2番目のアプリでテーブルからランダムな結果を得ることができることは知っています。しかし、それはオプションではありません。 2番目のアプリの仕組みを変更することはできません。
さて、問題は次のとおりです。テーブル内のすべての行を取り、それらをシャッフルしてテーブルに保管するにはどうすればよいですか?
更新:SQL Server 2008 R2は私のデータベースサーバーです
解決
呼び出しアプリがクエリで特定の注文を明示的に設定している場合(MSSQLを実行している場合は、アプリが実行中にプロファイラーセッションを実行しても確認できます。他のDMBSには同様のロギングオプションがあります)そうでない場合は、特定の順序を完全に保証することはできません。
句ごとの明示的な順序が与えられない場合、データは公式に「未定義」の順序で出てきます - それは、サーバーが最も納得させるものを注文するものです。単一のテーブルクエリの場合、これはおそらく主キーの順序です。 Clustered Indexがある場合、MSSQLでは、結果が1つのテーブルクエリのためにその順序で出てくる可能性が高いです。マルチテーブルクエリの場合、クエリプランナーの周りのどの方向があなたの結果を得るために選択したかに依存するため、さらに明確にカットされていません(明示的なインデックスのヒントは、テーブル内のデータのバランスとして、サーバーが保持するインデックス統計、変更)。
テーブルにクラスター化されたインデックスまたはプライマリキーがない場合、データはデータが挿入された順序に似た任意の順序で出てくる可能性があります。この場合、あなたは試すことができます:
SELECT * INTO temp_table FROM table_to_be_reordered
DELETE table_to_be_reordered
INSERT table_to_be_reordered SELECT * FROM temp_table ORDER BY NEWID()
または、これはより速いかもしれません
INSERT table_to_be_reordered SELECT * FROM temp_table ORDER BY NEWID()
DROP TABLE table_to_be_reordered
EXEC sp_rename 'temp_table', 'table_to_be_reordered'
上記のnewID()はMSSQLの関数であり、UUIDを返し、デフォルトで順次IDSではなくランダムを使用します - 他のDMBSで使用できる同様の機能を見つける必要があります。選択に注意してください。たとえば、MSSQLの下では、rand()関数はクエリごとに1回、行ごとに回避されるため、行ごとに回避されるため、 SELECT * FROM somewhere ORDER BY RAND()
巧妙な効果はありません(あなたはそのようなものを実行することによってなぜわかります SELECT RAND(), * FROM some_table
).
MSSQLを使用している場合(質問はターゲットにしているDBMSを記載していません)、テーブルにクラスター化されたインデックスがまだなく、十分にランダムな列(たとえばUUID列)があるか、動揺せずに追加することができます。通話アプリでは、上記にselect / delete / selectを選択するよりも速くなるクラスターインデックスにクラスター化されたインデックスを作成できます。しかし、繰り返しますが、これはあります 効果はまったくありません アプリが特定の順序で結果を明示的に要求している場合、 とにかく何の効果がないかもしれません そうでなければ。
他のヒント
どのデータベースを指定しませんが、Oracleでは次のことを行うことができます。
CREATE TABLE RAND_TABLE AS (SELECT * FROM ORIG_TABLE ORDER BY DBMS_RANDOM.RANDOM());
並べ替えに対処するには、温度表に十分なスペースが必要になります。次に、テーブルの名前を変更できます ORIG_TABLE
と RAND_TABLE
それらを交換します。テーブルを「インプレース」にシャッフルすることはできないと思います。