1〜400の番号が付けられた400行の次のヒープテーブルがあるとします。
DROP TABLE IF EXISTS dbo.N;
GO
SELECT
SV.number
INTO dbo.N
FROM master.dbo.spt_values AS SV
WHERE
SV.[type] = N'P'
AND SV.number BETWEEN 1 AND 400;
および次の設定:
SET NOCOUNT ON;
SET STATISTICS IO, TIME OFF;
SET STATISTICS XML OFF;
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
次のSELECT
文は約6秒で完了します(demo、plan):
DECLARE @n integer = 400;
SELECT
c = COUNT_BIG(*)
FROM dbo.N AS N
CROSS JOIN dbo.N AS N2
CROSS JOIN dbo.N AS N3
WHERE
N.number <= @n
AND N2.number <= @n
AND N3.number <= @n
OPTION
(OPTIMIZE FOR (@n = 1));
注:@このOPTIMIZE FOR
節は、さまざまな理由で発生する可能性のあるカーディナリティーの誤推定など、実際の問題の本質的な詳細をキャプチャした合理的なサイズの再現を作成するためのものです。
単一行の出力がテーブルに書き込まれるとき、19秒かかります(demo、plan):
DECLARE @T table (c bigint NOT NULL);
DECLARE @n integer = 400;
INSERT @T
(c)
SELECT
c = COUNT_BIG(*)
FROM dbo.N AS N
CROSS JOIN dbo.N AS N2
CROSS JOIN dbo.N AS N3
WHERE
N.number <= @n
AND N2.number <= @n
AND N3.number <= @n
OPTION
(OPTIMIZE FOR (@n = 1));
実行計画は、1行の挿入を除いて同一に見えます。
余分な時間はすべてCPU使用率によって消費されるようです。
INSERT
声明がなぜそんなに遅いのですか?