11

句を発見したばかりですTABLESAMPLEが、驚くべきことに、指定した行数が返されません。

私が使用したテーブルには約 14M 行があり、10000 行の任意のサンプルが必要でした。

select * from tabData TABLESAMPLE(10000 ROWS)

10000 ではなく、実行するたびに異なる数値 (8000 から 14000 の間) を取得します。

ここで何が起こっているのですか? の意図された目的を誤解していTABLESAMPLEますか?

編集

デビッドのリンクはそれをかなりよく説明しています。

これは、効率的な方法で常に 10000 個のほぼランダムな行を返します。

select TOP 10000 * from tabData TABLESAMPLE(20000 ROWS);

このREPEATABLEオプションは、常に同じものを取得するのに役立ちます(データが変更されていない限り)

select TOP 10000 * from tabData TABLESAMPLE(10000 ROWS) REPEATABLE(100);

TABLESAMPLE正しい行番号を取得するために (?) 多数の行を使用する方がコストがかかるかどうかを知りたかったので、測定しました。

1.ループ(20回):

select TOP 10000 * from tabData TABLESAMPLE(10000 ROWS);

(9938 row(s) affected)
(10000 row(s) affected)
(9383 row(s) affected)
(9526 row(s) affected)
(10000 row(s) affected)
(9545 row(s) affected)
(9560 row(s) affected)
(9673 row(s) affected)
(9608 row(s) affected)
(9476 row(s) affected)
(9766 row(s) affected)
(10000 row(s) affected)
(9500 row(s) affected)
(9941 row(s) affected)
(9769 row(s) affected)
(9547 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(9478 row(s) affected)
First batch(only 10000 rows) completed in: 14 seconds!

2.ループ(20回):

select TOP 10000 * from tabData TABLESAMPLE(10000000 ROWS);

(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
(10000 row(s) affected)
Second batch(max rows) completed in: 13 seconds!

3.ループ: ORDER BY NEWID() を使用して 100% ランダムな行でカウンターチェック:

select TOP 10000 * from tabData ORDER BY NEWID();

(10000 row(s) affected)

23 分間の 1 回の実行後にキャンセルされました

結論

したがって、驚くべきことに、exactTOP句と多数の in を使用したアプローチは遅くTABLESAMPLEはありません。ORDER BY NEWID()したがって、行が行ごとにランダムではなく、ページ レベルごとにランダムであることが問題にならない場合 (テーブルの各 8K ページにはランダムな値が与えられます)の非常に効率的な代替手段です。

4

4 に答える 4

5

こちらの記事をご覧ください。必要な行数を取得するには、top 句を追加するか、repeatable オプションを使用する必要があります。

于 2012-05-23T18:39:42.633 に答える
3

ドキュメントから。

返される実際の行数は、大幅に異なる場合があります。5 などの小さい数値を指定すると、サンプルで結果が得られない場合があります。

http://msdn.microsoft.com/en-us/library/ms189108(v=sql.90).aspx

于 2012-05-23T18:59:23.717 に答える
1

私は同じことを観察しました。

ページの説明は間違いなく理にかなっており、ベルを鳴らします-行サイズが固定されていると、はるかに予測可能な行数が表示されるはずです。null許容列または可変長列のないテーブルで試してください。

実際、私はそれを使用して更新することについての理論を証明するために使用しました(おそらく、私と同じ質問に拍車がかかりました)。TABLESAMPLE(50000 ROWS)を選択すると、実際には49,849行に影響しました。

于 2012-05-23T18:54:14.297 に答える
1

この動作は以前に文書化されています。ここに良い記事があります

毎回同じシードで REPEATABLE を渡すことで修正できると思います。以下は、記事の抜粋です。

...毎回異なる数の行が返されることに気付くでしょう。データを変更せずに、同じクエリを再実行すると、異なる結果が得られ続けます。これは、TABLESAMEPLE 句の非決定的な要因です。テーブルが静的で行が変更されていない場合、実行ごとに異なる数の行を返す理由が考えられます。係数は 10 です。PERCENT は、テーブルの行またはテーブルのレコードのパーセンテージではなく、テーブルのデータ ページのパーセンテージです。データのサンプル ページが選択されると、選択したページのすべての行が返されます。そのページからサンプリングされる行の数は制限されません。すべてのページの FILL FACTOR は、テーブルのデータによって異なります。これにより、スクリプトは実行されるたびに結果セットで異なる行数を返します。REPEATABLE オプションを指定すると、選択したサンプルが再度返されます。REPEATABLE が同じ repeat_seed 値で指定されている場合、テーブルに変更が加えられていない限り、SQL Server は同じ行のサブセットを返します。REPEATABLE が別の repeat_seed 値で指定されている場合、SQL Server は通常、テーブル内の行の別のサンプルを返します。.

于 2012-05-23T18:39:33.683 に答える