如果不存在插入新记录的最快方法,请仔细检查?
Posted
技术标签:
【中文标题】如果不存在插入新记录的最快方法,请仔细检查?【英文标题】:Fastest way to insert a new record if not exists, double check? 【发布时间】:2022-01-14 02:50:03 【问题描述】:这是一个简单的表定义:
CREATE TABLE UserNotificationTokens (
UserID INT NOT NULL,
Token CHAR(36) NOT NULL,
DeviceId VARCHAR(50) NOT NULL,
CONSTRAINT UC_DeviceId UNIQUE (DeviceId)
)
这里,DeviceId 列代表一个物理设备(智能手机)。对于每个设备,用户都有一个令牌(只是一个字符串,没什么大不了的)。如您所见,DeviceId 列上有一个唯一键。如果此设备 (DeviceId) 尚不存在,我想为该设备插入一个新令牌。我可以通过几种方式检查这种存在。但是,关键是 SQL Server 已经通过 Unique Key 检查 DeviceId 是否唯一。这意味着,同一任务需要双重工作。忽略我自己的检查并将其留给 SQL Server 是一种好习惯吗?如果插入将导致错误代码 2601(违反唯一键约束),则意味着 DeviceId 已经存在。抓住这个特定的错误,什么也不做。否则,该行插入成功。
【问题讨论】:
如果您一次只插入 1 行,为什么还要先检查一下,什么时候 SQL Server 会自动处理它并返回一个您可以轻松处理的错误?如果您一次插入多行,并且想要省略重复的行和/或对它们执行其他操作,我只能看到有用性。 这能回答你的问题吗? How to upsert (update or insert) in SQL Server 2005 另见sqlperformance.com/2020/09/locking/upsert-anti-pattern 因为这是一个有条件的insert
没有update
替代,只需使用where not exists()
【参考方案1】:
嗯,有 3 种不同的方法可以做到这一点。各有千秋。
检查,然后插入。在一次交易中。这需要时间(2 个命令,2 次数据库往返),因此会降低吞吐量,尤其是当您需要表锁以确保其 100% 准确时。 使用合并语句一次性编写更改。是的,可行。 只需插入并捕获异常。我会选择后者。它是最快的——只有一次往返,没有表锁,没有服务器延迟)并且捕获异常很快。
如何做到这一点实际上取决于复杂性 - 有时将简单的事情卸载到数据库中才是最有意义的。
【讨论】:
不要使用 MERGE;它非常破碎。 不。这并不是微不足道的,但我正在利用它来获得很大的优势。看,这就是了解限制和阅读文档。 文档没有告诉您迄今为止在 MERGE 中发现的数百个错误。我想知道你是否认为它是原子的?? 另一种方式:忽略索引设置上的重复项,然后检查受影响的行 另一种方式:做UPDATE
,然后检查@@ROWCOUNT
是否做INSERT
【参考方案2】:
您可以使用插入忽略:
例子:
INSERT IGNORE INTO books
(id, title, author, year_published)
VALUES
(1, 'Green Eggs and Ham', 'Dr. Seuss', 1960);
只有在唯一的情况下才会插入使用此查询的值。
【讨论】:
以上是关于如果不存在插入新记录的最快方法,请仔细检查?的主要内容,如果未能解决你的问题,请参考以下文章