SQLの最小限のロギング条件


9

このページhttp://technet.microsoft.com/en-us/library/dd425070(v=sql.100).aspxで行われた要求をテストするためのスクリプトを作成しました。最小限のロギングが行われるか、行われません。

このスクリプトを使用すると、さまざまな種類の挿入ごとのログレコード長の合計は次のようになります。

  • ヒープが空でタブロックなし60000
  • タブロック56000でヒープが空
  • ヒープは空ではなく、タブロックはありません60000
  • タブロック56000でヒープが空ではない
  • ヒープとインデックスが空でタブロックがない126188
  • ヒープとタブロック114188で空のインデックス
  • ヒープとインデックスが空ではないタブロックなし138696
  • タブロック112000でヒープとインデックスが空ではない
  • 空のクラスターがタブロックなしで注文された64168
  • タブロック56168で空のクラスターを注文
  • クラスターが空で順序付けられていないタブロックなし73388
  • タブロック65388でクラスタが空の順序なし
  • クラスターが空ではなくタブロックがない63912
  • タブロック55944で空でないクラスター
  • クラスターとインデックスが空でタブロックがない124336
  • クラスターとタブロックで空のインデックス108336
  • クラスターとインデックスが空ではないタブロックなし123876
  • タブロック107924でクラスターとインデックスが空ではない

これらの数値のいくつかは、technetページの表と一致していないようです。特に:

  • 空のテーブルへの挿入と空でないテーブルへの挿入の間にロギングに違いはないようですが、タブロックなしで非空のクラスターに挿入すると完全なロギングがあるはずですとページは主張します
  • tablockを使用して、indexを使用してヒープまたはクラスターに挿入すると、ロギングが削減されるように見えますが、ページでは完全なロギングが必要であると主張しています。
  • 挿入のSELECT INTOメソッドを使用する場合、fn_dblogには操作が挿入である行はありませんが、ページにはこのメソッドが、表に記載されている動作を持つはずのバルクロード操作としてリストされています。

参考までに、これはSQL Expressデータベースで実行されました。DBCCTRACESTATUS(610)を実行すると、すべてが0です。

なぜ私がこれらの矛盾を目にする可能性があるのか​​を説明するのを手伝ってくれる人はいますか?

参考までに、コードを以下に示します。

SET NOCOUNT ON

CREATE TABLE numbers (num INT)
CREATE TABLE numbersUnordered (num INT)

Declare @cnt int
Select @cnt=0
while (@cnt<500)
BEGIN
INSERT INTO NUMBERS(num) SELECT @cnt
SELECT @cnt=@cnt+1
END

Select @cnt=0
while (@cnt<250)
BEGIN
INSERT INTO numbersUnordered(num) SELECT @cnt*2
SELECT @cnt=@cnt+1
END

Select @cnt=0
while (@cnt<250)
BEGIN
INSERT INTO numbersUnordered(num) SELECT @cnt*2+1
SELECT @cnt=@cnt+1
END


---- heap empty without tablock
CREATE TABLE noKey1 (val INT)

INSERT INTO noKey1 (val)
SELECT * FROM numbers

DECLARE @heapEmptyNoTablock INT

SELECT @heapEmptyNoTablock = SUM([Log Record Length])
FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%noKey1%'
AND operation like '%insert%'

---- heap empty with tablock
CREATE TABLE noKey2 (val INT)

INSERT INTO noKey2 WITH(TABLOCK) (val)
SELECT * FROM numbers

DECLARE @heapEmptyTablock INT

SELECT @heapEmptyTablock = SUM([Log Record Length])
FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%noKey2%'
AND operation like '%insert%'

---- heap non empty without tablock
CREATE TABLE noKey3 (val INT)

INSERT INTO noKey3 WITH(TABLOCK) (val)
SELECT * FROM numbers

INSERT INTO noKey3 (val)
SELECT num+5 FROM numbers

DECLARE @heapNonEmptyNoTablock INT

SELECT @heapNonEmptyNoTablock = SUM(a.[Log Record Length])
FROM 
(SELECT TOP 500 * FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%noKey3%'
AND operation like '%insert%'
ORDER BY [Current LSN] desc) a

---- heap non empty with tablock
CREATE TABLE noKey4 (val INT)

INSERT INTO noKey4 WITH(TABLOCK) (val)
SELECT * FROM numbers

INSERT INTO noKey4 WITH (TABLOCK) (val)
SELECT num+5 FROM numbers

DECLARE @heapNonEmptyTablock INT

SELECT @heapNonEmptyTablock = SUM(a.[Log Record Length])
FROM 
(SELECT TOP 500 * FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%noKey4%'
AND operation like '%insert%'
ORDER BY [Current LSN] desc) a

--- heap plus index empty without tablock
CREATE TABLE noKey5 (val INT)
CREATE INDEX MSindex1
ON noKey5 (val)

INSERT INTO noKey5 (val)
SELECT * FROM numbers

DECLARE @heapIndexEmptyNoTablock INT

SELECT @heapIndexEmptyNoTablock = SUM([Log Record Length])
FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%noKey5%'
AND operation like '%insert%'


--- heap plus index empty with tablock
CREATE TABLE noKey6 (val INT)
CREATE INDEX MSindex2
ON noKey6 (val)

INSERT INTO noKey6 WITH(TABLOCK) (val)
SELECT * FROM numbers

DECLARE @heapIndexEmptyTablock INT

SELECT @heapIndexEmptyTablock = SUM([Log Record Length])
FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%noKey6%'
AND operation like '%insert%'

--- heap plus index non empty without tablock
CREATE TABLE noKey7 (val INT)
CREATE INDEX MSindex3
ON noKey7 (val)

INSERT INTO noKey7 WITH(TABLOCK) (val)
SELECT * FROM numbers

INSERT INTO noKey7 (val)
SELECT num+5 FROM numbers

DECLARE @heapIndexNonEmptyNoTablock INT

SELECT @heapIndexNonEmptyNoTablock = SUM(a.[Log Record Length])
FROM 
(SELECT TOP 1000 * FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%noKey7%'
AND operation like '%insert%'
ORDER BY [Current LSN] desc) a

--- heap plus index non empty with tablock
CREATE TABLE noKey8 (val INT)
CREATE INDEX MSindex4
ON noKey7 (val)

INSERT INTO noKey8 WITH(TABLOCK) (val)
SELECT * FROM numbers

INSERT INTO noKey8 WITH(TABLOCK) (val)
SELECT num+5 FROM numbers

DECLARE @heapIndexNonEmptyTablock INT

SELECT @heapIndexNonEmptyTablock = SUM(a.[Log Record Length])
FROM 
(SELECT TOP 1000 * FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%noKey8%'
AND operation like '%insert%'
ORDER BY [Current LSN] desc) a

--- cluster empty ordered without tablock
CREATE TABLE withKey1 (val INT PRIMARY KEY)

INSERT INTO withKey1 (val)
SELECT * FROM numbers

DECLARE @clusterEmptyNoTablock INT

SELECT @clusterEmptyNoTablock = SUM([Log Record Length])
FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%withKey1%'
AND operation like '%insert%'

--- cluster empty ordered with tablock
CREATE TABLE withKey2 (val INT PRIMARY KEY)

INSERT INTO withKey2 WITH(TABLOCK) (val)
SELECT * FROM numbers

DECLARE @clusterEmptyTablock INT

SELECT @clusterEmptyTablock = SUM([Log Record Length])
FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%withKey2%'
AND operation like '%insert%'

--- cluster empty unordered without tablock
CREATE TABLE withKey5 (val INT PRIMARY KEY)

INSERT INTO withKey5 (val)
SELECT * FROM numbersUnordered

DECLARE @clusterEmptyNoTablockUnordered INT

SELECT @clusterEmptyNoTablockUnordered = SUM([Log Record Length])
FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%withKey5%'
AND operation like '%insert%'

--- cluster empty undordered with tablock
CREATE TABLE withKey6 (val INT PRIMARY KEY)

INSERT INTO withKey6 WITH(TABLOCK) (val)
SELECT * FROM numbersUnordered

DECLARE @clusterEmptyTablockUnordered INT

SELECT @clusterEmptyTablockUnordered = SUM([Log Record Length])
FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%withKey6%'
AND operation like '%insert%'

--- cluster non empty no tablock
CREATE TABLE withKey7 (val INT PRIMARY KEY)

INSERT INTO withKey7 (val)
SELECT num FROM numbers

INSERT INTO withKey7 (val)
SELECT num+500 FROM numbers

DECLARE @clusterNonEmptyNoTablock INT

SELECT @clusterNonEmptyNoTablock = SUM(a.[Log Record Length])
FROM 
(SELECT TOP 500 * FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%withKey7%'
AND operation like '%insert%'
ORDER BY [Current LSN] desc) a

--- cluster non empty with tablock
CREATE TABLE withKey8 (val INT PRIMARY KEY)

INSERT INTO withKey8 WITH(TABLOCK) (val)
SELECT num FROM numbers

INSERT INTO withKey8 WITH(TABLOCK) (val)
SELECT num+500 FROM numbers

DECLARE @clusterNonEmptyTablock INT

SELECT @clusterNonEmptyTablock = SUM(a.[Log Record Length])
FROM 
(SELECT TOP 500 * FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%withKey8%'
AND operation like '%insert%'
ORDER BY [Current LSN] desc) a

--- cluster plus index empty no tablock
CREATE TABLE withKey9 (val INT PRIMARY KEY)
CREATE INDEX MSindex5
ON withKey9 (val)

INSERT INTO withKey9 (val)
SELECT * FROM numbers

DECLARE @clusterIndexEmptyNoTablock INT

SELECT @clusterIndexEmptyNoTablock = SUM([Log Record Length])
FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%withKey9%'
AND operation like '%insert%'

--- cluster plus index empty with tablock
CREATE TABLE withKey10 (val INT PRIMARY KEY)
CREATE INDEX MSindex6
ON withKey10 (val)

INSERT INTO withKey10 WITH(TABLOCK) (val)
SELECT * FROM numbers

DECLARE @clusterIndexEmptyTablock INT

SELECT @clusterIndexEmptyTablock = SUM([Log Record Length])
FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%withKey10%'
AND operation like '%insert%'

--- cluster plus index nonempty no tablock
CREATE TABLE withKey11 (val INT PRIMARY KEY)
CREATE INDEX MSindex7
ON withKey11 (val)

INSERT INTO withKey11 (val)
SELECT num FROM numbers

INSERT INTO withKey11 (val)
SELECT num+500 FROM numbers

DECLARE @clusterIndexNonEmptyNoTablock INT

SELECT @clusterIndexNonEmptyNoTablock = SUM(a.[Log Record Length])
FROM 
(SELECT TOP 1000 * FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%withKey11%'
AND operation like '%insert%'
ORDER BY [Current LSN] desc) a

--- cluster plus index nonempty with tablock
CREATE TABLE withKey12 (val INT PRIMARY KEY)
CREATE INDEX MSindex8
ON withKey12 (val)

INSERT INTO withKey12 WITH(TABLOCK) (val)
SELECT num FROM numbers

INSERT INTO withKey12 WITH(TABLOCK) (val)
SELECT num+500 FROM numbers

DECLARE @clusterIndexNonEmptyTablock INT

SELECT @clusterIndexNonEmptyTablock = SUM(a.[Log Record Length])
FROM 
(SELECT TOP 1000 * FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%withKey12%'
AND operation like '%insert%'
ORDER BY [Current LSN] desc) a

--- select into
/*SELECT * 
INTO selectIntoTable
FROM numbers

SELECT * FROM sys.fn_dblog(null, null)
WHERE allocunitname like '%selectIntoTable%'
AND operation like '%insert%'

DROP TABLE selectIntoTable
*/


PRINT 'Heap empty no tablock ' + CAST(@heapEmptyNoTablock AS VARCHAR)
PRINT 'Heap empty with tablock ' + CAST(@heapEmptyTablock AS VARCHAR)
PRINT 'Heap non empty no tablock ' + CAST(@heapNonEmptyNoTablock AS VARCHAR)
PRINT 'Heap non empty with tablock ' + CAST(@heapNonEmptyTablock AS VARCHAR)
PRINT 'Heap plus index empty no tablock ' + CAST(@heapIndexEmptyNoTablock AS VARCHAR)
PRINT 'Heap plus index empty with tablock ' + CAST(@heapIndexEmptyTablock AS VARCHAR)
PRINT 'Heap plus index non empty no tablock ' + CAST(@heapIndexNonEmptyNoTablock AS VARCHAR)
PRINT 'Heap plus index non empty with tablock ' + CAST(@heapIndexNonEmptyTablock AS VARCHAR)
PRINT 'Cluster empty ordered no tablock ' + CAST(@clusterEmptyNoTablock AS VARCHAR)
PRINT 'Cluster empty ordered with tablock ' + CAST(@clusterEmptyTablock AS VARCHAR)
PRINT 'Cluster empty unordered no tablock ' + CAST(@clusterEmptyNoTablockUnordered AS VARCHAR)
PRINT 'Cluster empty unordered with tablock ' + CAST(@clusterEmptyTablockUnordered AS VARCHAR)
PRINT 'Cluster non empty no tablock ' + CAST(@clusterNonEmptyNoTablock AS VARCHAR)
PRINT 'Cluster non empty with tablock ' + CAST(@clusterNonEmptyTablock AS VARCHAR)
PRINT 'Cluster plus index empty no tablock ' + CAST(@clusterIndexEmptyNoTablock AS VARCHAR)
PRINT 'Cluster plus index empty with tablock ' + CAST(@clusterIndexEmptyTablock AS VARCHAR)
PRINT 'Cluster plus index non empty no tablock ' + CAST(@clusterIndexNonEmptyNoTablock AS VARCHAR)
PRINT 'Cluster plus index non empty with tablock ' + CAST(@clusterIndexNonEmptyTablock AS VARCHAR)


DROP TABLE numbers
DROP TABLE numbersUnordered
DROP TABLE noKey1
DROP TABLE noKey2
DROP TABLE noKey3
DROP TABLE noKey4
DROP TABLE noKey5
DROP TABLE noKey6
DROP TABLE noKey7
DROP TABLE noKey8
DROP TABLE withKey1
DROP TABLE withKey2
DROP TABLE withKey5
DROP TABLE withKey6
DROP TABLE withKey7
DROP TABLE withKey8
DROP TABLE withKey9
DROP TABLE withKey10
DROP TABLE withKey11
DROP TABLE withKey12

回答:


12

これらの数値のいくつかは、technetページの表と一致していないようです。

テストで生成されるログレコードのサイズにはわずかな違いがありますが、これらは他の内部ログ動作によるものであり、最小限のログが発生しているかどうかではありません。

最小限のロギングの適切な定義は、ストレージエンジンチームのSunil Agarwalによって提供されています。

個々の行はログに記録さず、ページ割り当て構造への変更のみがログに記録されます

個々の行の変更がログに記録されていることを確認するテスト(例LOP_INSERT_ROWS:)では、関連するアロケーションユニットに対して最小限のログが使用されていません。一部の操作は、1つのアロケーションユニット(たとえば、インデックス)に関して最小限に記録され、別のアロケーションユニットに対して最小限に記録されない場合があります。また、状況によっては、既存のページへの挿入は最小限のログに記録されない場合がありますが、新しく割り当てられたページへの変更はログに記録される場合があります。

詳細のほとんどは、一連のストレージエンジンチームのブログ投稿にあります。

調査されていない詳細の1つは、最小限のログ(SQL Server 2008以降)を使用INSERT...SELECTするには、bツリー構造への変更でDMLRequestSortクエリプランオペレータープロパティをtrueに設定する必要があることです。これは、データ読み込みパフォーマンスガイドに「依存」と表示されている状況に当てはまります。クエリプランでは、ワイド(インデックスごと)メンテナンスを使用する必要がありますDMLRequestSort=true

これについては、INSERT…SELECTとFast Load Contextを使用し最小ロギングで詳しく説明しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.