Fra*_*k V 24 sql-server indexing temp-tables primary-key
我有一个使用大量数据的存储过程.我将数据插入到临时表中.事件的总体流程是这样的
CREATE #TempTable (
Col1 NUMERIC(18,0) NOT NULL, --This will not be an identity column.
,Col2 INT NOT NULL,
,Col3 BIGINT,
,Col4 VARCHAR(25) NOT NULL,
--Etc...
--
--Create primary key here?
)
INSERT INTO #TempTable
SELECT ...
FROM MyTable
WHERE ...
INSERT INTO #TempTable
SELECT ...
FROM MyTable2
WHERE ...
--
-- ...or create primary key here?
Run Code Online (Sandbox Code Playgroud)
我的问题是什么时候是在#TempTable表上创建主键的最佳时机?我推断在插入所有数据后我应该创建主键约束/索引,因为索引需要在创建主键信息时重新组织.但我意识到我强调的假设可能是错误的......
如果它是相关的,我使用的数据类型是真实的.在#TempTable表中,Col1并Col4会弥补我的主键.
更新:就我而言,我正在复制源表的主键.我知道构成我的主键的字段将始终是唯一的.如果我在最后添加主键,我不关心失败的alter table.
虽然,除此之外,我的问题仍然存在,假设两者都会成功,这个问题会更快吗?
PS如果这是重复,我很抱歉.它可能是基本的,但我找不到类似的东西.
Cad*_*oux 17
这取决于很多.
如果在加载后使主键索引成为聚簇,则整个表将被重写,因为聚簇索引实际上不是索引,它是数据的逻辑顺序.插入时的执行计划将取决于确定计划时的索引,如果聚簇索引到位,它将在插入之前进行排序.您通常会在执行计划中看到这一点.
如果您将主键设置为一个简单约束,它将是一个常规(非聚集)索引,并且该表将简单地以优化程序确定的任何顺序填充并更新索引.
我认为(加载临时表的这个过程)总体上最快的性能通常是将数据写为堆,然后应用(非群集)索引.
但是,正如其他人所指出的那样,索引的创建可能会失败.此外,临时表不是孤立存在的.据推测,有一个最佳索引可以从下一步读取数据.该索引需要就位或创建. 这是你必须在这里权衡速度的可靠性(首先应用PK和任何其他约束)和以后的速度(如果你将要有一个聚类索引).
如果数据库的恢复模型设置为简单或批量记录,SELECT ... INTO ... UNION ALL可能是最快的解决方案.SELECT .. INTO是批量操作,批量操作记录最少.
例如:
-- first, create the table
SELECT ...
INTO #TempTable
FROM MyTable
WHERE ...
UNION ALL
SELECT ...
FROM MyTable2
WHERE ...
-- now, add a non-clustered primary key:
-- this will *not* recreate the table in the background
-- it will only create a separate index
-- the table will remain stored as a heap
ALTER TABLE #TempTable ADD PRIMARY KEY NONCLUSTERED (NonNullableKeyField)
-- alternatively:
-- this *will* recreate the table in the background
-- and reorder the rows according to the primary key
-- CLUSTERED key word is optional, primary keys are clustered by default
ALTER TABLE #TempTable ADD PRIMARY KEY CLUSTERED (NonNullableKeyField)
Run Code Online (Sandbox Code Playgroud)
否则,Cade Roux有很好的建议:在之前或之后.