我有一个案例,我需要更新一个非常大的表中的 10-50k 条目。桌子是这样的
int id PK
varchar username
boolean active
int category
and other random columns
有用户名和类别的索引。我必须更新类别 1 的 2 万条记录。我们可能还有 50 万条未触及的其他类别的记录。
我们在 jtds 驱动程序上使用 spring jdbc,仍然使用 SQL Server。问题是我们认为哪种方法会更快。
update table set active = 1 where username = ? and category = 1
insert into #temp values ?
然后一大:
update table set active = 1 from #temp join table on #temp.username = table.username and category = 1
有什么猜测一般来说哪种方法会更快吗?我可以为我运行测试,但这适用于其他人,有些拥有更快的数据库,有些较慢,有些通过网络,有些更快。
谢谢!
如果您有一种有效的方法将所有用户名输入 SQL,我会采用该方法并立即更新所有内容。虽然单个更新语句的开销并不大,但在 20k 次更新的过程中,这些开销将会增加。另外,如果您一次执行一个操作,则该操作不是原子操作,如果中途失败,这可能会或可能不会成为问题。
您可以做的一个选择是将所有用户名作为 json (或 xml,甚至是分隔字符串)传递,然后解压值并更新用户名是解压值之一的行。就我个人而言,我会选择 JSON,因为它是最简洁且安全的,不会出现分隔符引起的问题。
以下是一些如何在 SQL 中实现这一目标的示例。所有这些都假设您格式化某种序列化的用户名字符串。
使用 JSON:
declare
@UsernamesJSON nvarchar(max) = N'[ "alice", "bob", "charlie" ]',
@Category int = 1
update t
set Active = 1
from MyTable t
inner join openjson(@UsernamesJSON) s
on t.Username = s.Value
where t.Category = @Category
使用分隔字符串
-- These are your input parameters from your app
declare
@Usernames nvarchar(max) = N'Alice|Bob|Charlie|Deborah|Eggbert',
@Category int = 1
update t
set Active = 1
from MyTable t
inner join string_split(@UserNames, '|') s
on t.Username = s.Value
where Category = @Category
使用XML
declare @UsernamesXML xml = N'
<names>
<name>alice</name>
<name>bob</name>
<name>charlie</name>
</names>
'
update t
set Active = 1
from MyTable t
inner join @UsernamesXML.nodes('names/name') as a(c)
on t.username = a.c.value('.', 'varchar(50)')
where Category = @Category