with (Nolock)
を追加すると、テンポラリテーブルから選択する際に競合が減るのですか?またはSQL Serverが最初の場所にテンポラリテーブルの競合を作成しないほどスマートですか?SQL Server 2008のテンポラリテーブルでnolock
PS:はい私はREADUNCOMMITTEDの危険性を認識しています。
select * from #myTempTable with (nolock) --is this faster?
with (Nolock)
を追加すると、テンポラリテーブルから選択する際に競合が減るのですか?またはSQL Serverが最初の場所にテンポラリテーブルの競合を作成しないほどスマートですか?SQL Server 2008のテンポラリテーブルでnolock
PS:はい私はREADUNCOMMITTEDの危険性を認識しています。
select * from #myTempTable with (nolock) --is this faster?
(私はこれがグローバルだと思うよう開発マシン上で)あなたはそれが当然違いの多くを作る自分のためにグローバルな一時テーブルの場合
SET NOCOUNT ON;
CREATE TABLE ##T
(
X INT
)
INSERT INTO ##T
SELECT number
FROM master..spt_values
CREATE TABLE #T
(
X INT
)
INSERT INTO #T
SELECT *
FROM ##T
/*Run the commands first with the trace flag off so the locking
info is less full of irrelevant stuff about plan compilation
*/
GO
PRINT '##T Read Committed'
SELECT COUNT(*) FROM ##T
PRINT '##T NOLOCK'
SELECT COUNT(*) FROM ##T WITH (NOLOCK)
PRINT '##T Finished'
GO
PRINT '#T Read Committed'
SELECT COUNT(*) FROM #T
PRINT '#T NOLOCK'
SELECT COUNT(*) FROM #T WITH (NOLOCK)
PRINT '#T Finished'
GO
DBCC TRACEON(-1,3604)
DBCC TRACEON(-1,1200)
GO
PRINT '##T Read Committed'
SELECT COUNT(*) FROM ##T
PRINT '##T NOLOCK'
SELECT COUNT(*) FROM ##T WITH (NOLOCK)
PRINT '##T Finished'
GO
PRINT '#T Read Committed'
SELECT COUNT(*) FROM #T
PRINT '#T NOLOCK'
SELECT COUNT(*) FROM #T WITH (NOLOCK)
PRINT '#T Finished'
GO
DBCC TRACEOFF(-1,3604)
DBCC TRACEOFF(-1,1200)
DROP TABLE ##T
DROP TABLE #T
を取り出してロックを確認するためにトレースフラグ1200を使用することができます。
ローカル#temp
テーブルのロックのタイプにはまだ小さな違いがあります。私は
#T Read Committed
Process 56 acquiring IS lock on OBJECT: 2:301244128:0 (class bit0 ref1) result: OK
Process 56 acquiring S lock on OBJECT: 2:301244128:0 (class bit0 ref1) result: OK
Process 56 releasing lock on OBJECT: 2:301244128:0
#T NOLOCK
Process 56 acquiring Sch-S lock on OBJECT: 2:301244128:0 (class bit0 ref1) result: OK
Process 56 acquiring S lock on HOBT: 2:9079256880114171904 [BULK_OPERATION] (class bit0 ref1) result: OK
Process 56 releasing lock on OBJECT: 2:301244128:0
編集以下の出力の一部を再現:上記の結果は、ヒープのためのものです。クラスタード・インデックスを持つ一時テーブルの場合、結果は以下のとおりです。
#T Read Committed
Process 55 acquiring IS lock on OBJECT: 2:1790629422:0 (class bit0 ref1) result: OK
Process 55 acquiring S lock on OBJECT: 2:1790629422:0 (class bit0 ref1) result: OK
Process 55 releasing lock on OBJECT: 2:1790629422:0
#T NOLOCK
Process 55 acquiring Sch-S lock on OBJECT: 2:1790629422:0 (class bit0 ref1) result: OK
Process 55 releasing lock on OBJECT: 2:1790629422:0
#T Finished
ヒープバージョンのBULK_OPERATION
ロックの理由はexplained hereです。しかし、ロックオーバーヘッドは非常に最小限であることがわかります。
対
select * from #myTempTable
一時テーブルのスコープが同じ接続であるので、それは大きな違いを作る可能性は低いです。
あなたは同じ接続であなた自身とロックを競合しています。一時テーブルを読んでいるのであれば、おそらく唯一のものです。
通常、SQL Serverクエリエンジンが過度に最適化されず、信頼性が高いとは限りません。何かを修正しようとする前に問題が生じるまで待ってください。
EDIT(ややオフトピック):(更新されたリンク)が
しかし、あなたは一時テーブルを作成のtempdb全体への影響の周りにいくつかの議論があります。 - see options here(ただしこれは古い記事 - SQL Server 6.5/7.0)とその可能性の高いSQL Server 2000の上位バージョンは、このシナリオを自動的に処理する可能性があります。
もう一度問題が発生するまでお待ちくださいあなたのソリューションは複雑です。
ps - 私はすでに最適化の問題があります:) – dan
これは、クエリによって大きく異なる場合があります。 私はテンポラリテーブルにWITH(NO LOCK)を追加するだけで、クエリ実行時間を1295から590に減らしました。結果は異なる場合があります。
非常に良い答え。私はこの有用なトレースフラグについて知らなかった!スクリプトは、テストの最後に3604を不必要に無効にすることに注意してください。私はこのフラグを私の開発者ボックスで起動可能にしました。セッションスコープで使うべきだと思います。何らかの理由で、これは1200で動作しませんでした。 1200はなぜグローバルでなければならないのですか? – usr
私は 'DBCC TRACEON'と' DBCC TRACEOFF'に渡したパラメータのうち、最初のパラメータとしてトレースフラグを渡し、最後のパラメータとしてグローバルフラグを渡すべきです。なぜあなたは最初のものとして '-1'を入れますか? –
@OgrishManどのような順序でも同じように動作します。 –