在临时表上创建主键 - 何时?

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表中,Col1Col4会弥补我的主键.

更新:就我而言,我正在复制源表的主键.我知道构成我的主键的字段将始终是唯一的.如果我在最后添加主键,我不关心失败的alter table.

虽然,除此之外,我的问题仍然存在,假设两者都会成功,这个问题会更快吗?

PS如果这是重复,我很抱歉.它可能是基本的,但我找不到类似的东西.

Cad*_*oux 17

取决于很多.

如果在加载后使主键索引成为聚簇,则整个表将被重写,因为聚簇索引实际上不是索引,它是数据的逻辑顺序.插入时的执行计划将取决于确定计划时的索引,如果聚簇索引到位,它将在插入之前进行排序.您通常会在执行计划中看到这一点.

如果您将主键设置为一个简单约束,它将是一个常规(非聚集)索引,并且该表将简单地以优化程序确定的任何顺序填充并更新索引.

我认为(加载临时表的这个过程)总体上最快的性能通常是将数据写为堆,然后应用(非群集)索引.

但是,正如其他人所指出的那样,索引的创建可能会失败.此外,临时表不是孤立存在的.据推测,有一个最佳索引可以从下一步读取数据.该索引需要就位或创建. 是你必须在这里权衡速度的可靠性(首先应用PK和任何其他约束)和以后的速度(如果你将要有一个聚类索引).


Pet*_*hia 6

如果数据库的恢复模型设置为简单或批量记录,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有很好的建议:在之前或之后.