1

私はSQLとデータベース全般にかなり慣れていません。SQL Server 2008 Mgmt Studio を使用しています。

セットベースの操作を使用する方が RBAR よりも優れていることを読みました (今日それを学びました!)。

すぐに、2 つの同等の (と思う) クエリを紹介します。どちらがより効率的かを確認しようとしています。

最初の試み:

DECLARE @persID int
DECLARE @mag    float
DECLARE @temp TABLE (pID int PRIMARY KEY)

INSERT INTO @temp
SELECT persID FROM Person

WHILE (SELECT COUNT(pID) FROM @temp) > 0
BEGIN
   SELECT TOP 1 @persID = pID FROM @temp    
   SELECT @mag = SQRT(SUM(value*value)) FROM PersonWord 
      WHERE PersonWord.persID = @persID

   UPDATE Person
   SET magnitude = @mag
      WHERE persID  = @persID
   DELETE @temp WHERE pID = @persID
END

2 回目の試行:

DECLARE @temp TABLE (pID int PRIMARY KEY, mag float)

INSERT INTO @temp
   SELECT persID, SQRT(SUM(value*value)) FROM PersonWord
      GROUP BY persID

MERGE INTO Person AS p
USING @temp AS t
   ON p.persID = t.pID
WHEN MATCHED
THEN UPDATE
   SET magnitude = t.mag

これらは、実行時にストアド プロシージャおよび推定実行プランとして保存されます。

exec FirstAttempt
exec SecondAttempt

FirstAttempt のバッチの 32% と SecondAttempt の 68% を示しています

PersonWordテーブルには約 4,100 万件のレコードが含まれています...テーブルPersonには約 170,000件のレコードが含まれています

どんな考えやアドバイスも大歓迎です。お時間を割いていただきありがとうございます。初心者の質問がどれほどイライラするかを知っています (以前は Yahoo で数学のヘルプを作成していました)。

編集::

約 130 万のレコードを持つ PersonWord と約 3000 の Person でそれらを実行すると、マージのあるバージョンの実行には約 1.3 秒かかりました。while ループを含むバージョンは 6 分で、ジョブの ~15% しか完了していませんでした。

こういうのはRBARじゃなくてセットベース!

4

1 に答える 1

3

その数のレコードにテーブル変数を使用しないでください。これらは小さなデータセット用です。代わりに一時テーブルを使用してインデックスを作成します。また、更新するレコードの数を制限する方法を個人的に探しています。これは単純な更新であるため、とにかくマージを使用している理由がわかりません。以下のコードは機能するはずです。

Update P
set   SET magnitude = t.mag
from Person AS p
join  #temp AS t
   ON p.persID = t.pID
WHERE magnitude <> t.mag

そして、これを行う頻度に応じて、この計算を保存して、レコードごとに 1 回だけ実行するようにします (値が変更された場合は、rtigger を使用して更新を維持します): SQRT(SUM(value) *価値))

ところで、正確ではないため、丸め誤差が発生する可能性があるため、数学計算のために浮動小数点を使用することはお勧めできません。

于 2013-05-14T21:30:02.147 に答える