Sql server 两个查询中哪一个更有效?

Sql server 两个查询中哪一个更有效?,sql-server,database,oracle,db2,Sql Server,Database,Oracle,Db2,我有一个表,其中有user_id、email和default列。默认存储“Y”或“N”,具体取决于电子邮件是否为用户默认电子邮件。每个用户只能有一封默认电子邮件 当用户在表上执行更新或插入操作时,在我的SP中,我检查用户是否已将isDefault传递为“Y”。如果是这样,我需要更新该用户的所有条目,使其成为默认的“N”。我的问题是:考虑到不存在锁定问题(不会有多个线程为特定用户从表中请求数据),以下查询中哪一个最耗时: update table set default = 'N' where u

我有一个表,其中有user_id、email和default列。默认存储“Y”或“N”,具体取决于电子邮件是否为用户默认电子邮件。每个用户只能有一封默认电子邮件

当用户在表上执行更新或插入操作时,在我的SP中,我检查用户是否已将isDefault传递为“Y”。如果是这样,我需要更新该用户的所有条目,使其成为默认的“N”。我的问题是:考虑到不存在锁定问题(不会有多个线程为特定用户从表中请求数据),以下查询中哪一个最耗时:

update table
set default = 'N'
where user_id = 'abc'
and default = 'Y'
(其中默认值的开销='Y'检查)


(为用户更新所有记录的开销)

查询的速度取决于多个因素,如表中的行数、索引、检查约束以及外键和主键


至少在SQL Server中,确定哪个更快的最好方法是在运行查询时使用include client statistics and execution plan。比较每种方法的时间,选出最好的。

为什么不自己尝试一下呢。在SQL Management Studio中,依次运行这两个查询并启用“包含实际执行计划”。百分比越高,查询速度越慢。

这里没有明确的答案。在第一种情况下,如果大多数记录的默认值为'N',则效率最高。在第二种情况下,在大多数情况下,如果default='Y'最好


因此,如果大多数用户只有一个电子邮件地址,请使用第二个查询。如果大多数用户至少有2个,那么使用第一个。

99%确定地说,第一个查询将更有效

很可能您的集群键是user_id,因此您的UPDATE语句将很快找到要更新的行。在SQL Server中,更新在逻辑上实现为先删除,然后插入,因此这可能是一个相当昂贵的操作(相对于简单的查找)


再加上更新需要对记录进行独占锁定,所有迹象都指向语句1。

在Oracle方面,我选择选项1。有点

我会有一个唯一的索引,强制每个用户只有一个默认条目,然后我会使用该索引中的函数作为更新的一部分。只更新需要更新的行。另外,唯一索引最大限度地减少了为给定用户获取默认电子邮件所需的工作量,不仅仅是更新,还包括使用该功能获取行的任何位置

drop table user_email;

create table user_email 
(userid varchar2(4) not null, default_ind varchar2(1) not null, 
email varchar2(30));

create unique index ue_x on user_email 
  (userid, decode(default_ind,'Y','Y',email));

insert into user_email (userid, default_ind, email) values ('fred','N','a');
insert into user_email (userid, default_ind, email) values ('fred','N','b');
insert into user_email (userid, default_ind, email) values ('fred','Y','c');

update user_email
set default_ind = 'N'
where userid = 'fred'
and decode(default_ind,'Y','Y',email) = 'Y';

update user_email
set default_ind = 'Y'
where userid = 'fred'
and email = 'a';

PS.“where default='Y'check'的开销非常小,因为您需要访问该列来更新它。

单独查询的速度不是最相关的因素-您需要考虑一个事实,即不必要的更新会导致更重的锁定,以及更新,即使他们实际上没有更改字段的值,也可以触发表中定义的任何更新触发器。是的,好的。在我之前的评论之前,我应该阅读你的答案。“我向你卓越的理解致敬,先生。”亚伦·奥尔顿:当然。不仅要获取行上的排他锁,而且在Oracle的情况下,要将块的预更改副本复制到撤消(pka回滚),所有这些更改都会记录在重做日志中。一般来说,不要更新不需要更新的行,除非您有充分的理由这样做。
drop table user_email;

create table user_email 
(userid varchar2(4) not null, default_ind varchar2(1) not null, 
email varchar2(30));

create unique index ue_x on user_email 
  (userid, decode(default_ind,'Y','Y',email));

insert into user_email (userid, default_ind, email) values ('fred','N','a');
insert into user_email (userid, default_ind, email) values ('fred','N','b');
insert into user_email (userid, default_ind, email) values ('fred','Y','c');

update user_email
set default_ind = 'N'
where userid = 'fred'
and decode(default_ind,'Y','Y',email) = 'Y';

update user_email
set default_ind = 'Y'
where userid = 'fred'
and email = 'a';