我试图找出将记录插入单个表的最佳方法,但前提是该项目尚不存在.在这种情况下,KEY是NVARCHAR(400)字段.对于此示例,我们假设它是牛津英语词典中单词的名称/在此处插入您的fav词典.另外,我猜我需要将Word字段作为主键.(该表也将具有唯一标识符PK).
所以...我可能会得到这些我需要添加到表格中的单词...
例如.
猫
狗
富
酒吧
PewPew
等等...
所以传统上,我会尝试以下(伪代码)
SELECT WordID FROM Words WHERE Word = @Word IF WordID IS NULL OR WordID <= 0 INSERT INTO Words VALUES (@Word)
即.如果该单词不存在,则插入它.
现在..我担心的问题是我们得到了大量的命中..所以有可能这个词可以从SELECT和INSERT之间的另一个进程插入...这会引发一个约束错误?(即比赛条件).
然后我想我可能会做以下事情......
INSERT INTO Words (Word) SELECT @Word WHERE NOT EXISTS (SELECT WordID FROM Words WHERE Word = @Word)
基本上,当它不存在时插入一个单词.
除了错误的语法之外,我不确定这是坏还是好因为它如何锁定表(如果它确实)并且不是表上的表现,它会获得大量读取和大量写入.
那么 - 你的Sql大师怎么想/做什么?
我希望有一个简单的插入和"捕获",任何错误抛出.
你的解决方案
INSERT INTO Words (Word) SELECT @Word WHERE NOT EXISTS (SELECT WordID FROM Words WHERE Word = @Word)
......几乎和它一样好.你可以简化它:
INSERT INTO Words (Word) SELECT @Word WHERE NOT EXISTS (SELECT * FROM Words WHERE Word = @Word)
...因为EXISTS实际上不需要返回任何记录,因此查询优化器不会费心查看您要求的字段.
但是,正如您所提到的,这不是特别高效,因为它会在INSERT期间锁定整个表.除此之外,如果你添加一个唯一索引(它并不需要是主键)到Word,然后它会只需要锁定相关页面.
您最好的选择是模拟预期的负载并使用SQL Server Profiler查看性能.与任何其他领域一样,过早优化是一件坏事.定义可接受的性能指标,然后在执行任何其他操作之前进
如果仍然没有给你足够的性能,那么数据仓库领域的一系列技术可能有所帮助.
我想我找到了一个更好的(或至少更快的)答案。创建一个像这样的索引:
CREATE UNIQUE NONCLUSTERED INDEX [IndexTableUniqueRows] ON [dbo].[table] ( [Col1] ASC, [Col2] ASC, )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = ON, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
包括所有定义唯一性的列。重要的部分是IGNORE_DUP_KEY = ON。这会将非唯一插入内容转换为警告。SSIS会忽略这些警告,您仍然可以使用fastload。