SE の雑記

SQL Server の情報をメインに Microsoft 製品の勉強内容を日々投稿

TABLESAMPLE と TOP 句を組み合わせる場合の注意点

leave a comment

以前、TABLESAMPLE 句のデータ取得はどのように動作しているか という投稿をしました。

この TABLESAMPLE と TOP 句を組み合わせる場合の注意点について少し書いてみたいと思います。

■TOP 句と組み合わせる場合の注意点


以下のようなクエリを実行してみます。

USE TEST
GO
DROP TABLE #tmp
SELECT * INTO #tmp FROM Table_1 WHERE 1=0
GO
INSERT INTO #tmp SELECT TOP 1 * FROM Table_1 TABLESAMPLE (100 ROWS)
GO 10
SELECT
    *
FROM
    Table_1
    CROSS APPLY
        sys.fn_PhysLocCracker(%%physloc%%)
WHERE
    Col1 IN (SELECT Col1 FROM #Tmp)

 

一時テーブルに TABLESAMPLE で 100 行取得した結果のうち TOP 1 件のみを格納するという処理を 10 回実行しています。
この時の結果ですが以下のようになります。
image

実行するごとに異なるページが取得されるのですが、[slot_id] は 常に 0 になります。

SQL Server のページですが単純な構成として書くと以下のように各行が格納されます。
# 実際にはオフセットで各行を認識しています。
image

TABLESAMPLE はページをサンプリングして情報の取得を行います。
そのため ORDER BY で適切なソートをしないとページの最初のスロット (slot_id = 0) が取得される確率が高いと思います。
# TOP 1 なので最初のスロットが取得された状態になります。

スロットをランダムで取得したい場合は、

USE TEST
GO
DROP TABLE #tmp
SELECT * INTO #tmp FROM Table_1 WHERE 1=0
GO
INSERT INTO #tmp SELECT TOP 1 * FROM Table_1 TABLESAMPLE (100 ROWS) ORDER BY NEWID()
GO 10
SELECT
    *
FROM
    Table_1
    CROSS APPLY
        sys.fn_PhysLocCracker(%%physloc%%)
WHERE
    Col1 IN (SELECT Col1 FROM #Tmp)

というように NEWID でソートをするというようなクエリにする必要があると思います。
このクエリを実行するとスロットが分散して取得されます。
image

TABLESAMPLE でデータを取得する場合は、どのスロットのデータが取得されているかを意識したほうが良さそうですね。

Share

Written by Masayuki.Ozawa

4月 20th, 2012 at 6:48 pm

Posted in SQL Server

Tagged with

Leave a Reply