基于另一个表缓慢地将值更新到表

时间:2010-11-09 16:49:27

标签: sql performance tsql

我想知道为什么当将值从一个表更新到另一个表而不是从一个表到另一个表中选择值时,我的select语句比我的update语句快几个数量级。下面的例子说明了我的问题,我可以很快地运行我的select语句

select customers.name, countries.country
from customers
inner join countries on customers.countrycode = countries.countrycode

然而,我写的更新声明(我相当确定是相同的)需要更长的时间才能完成。

update customers
set customers.country = countries.country
from customers
inner join countries on customers.countrycode = countries.countrycode

有什么建议吗?

更新:

以下是SELECT语句的计划

  |--Hash Match(Inner Join, HASH:([countries].[countrycode])=([Testing].[dbo].[customers].[countrycode]), RESIDUAL:(@countries.[countrycode] as [countries].[countrycode]=[Testing].[dbo].[customers].[countrycode]))
       |--Table Scan(OBJECT:(@countries AS [countries]))
       |--Table Scan(OBJECT:([Testing].[dbo].[customers]))  

以下是UPDATE语句的计划

  |--Table Update(OBJECT:([Testing].[dbo].[Customers]), SET:([Testing].[dbo].[Customers].[Country] = @countries.[country] as [countries].[country]))
       |--Top(ROWCOUNT est 0)
            |--Stream Aggregate(GROUP BY:([Bmk1000]) DEFINE:([countries].[country]=ANY(@countries.[country] as [countries].[country])))
                 |--Nested Loops(Inner Join, WHERE:(@countries.[countrycode] as [countries].[countrycode]=[Testing].[dbo].[Customers].[countrycode]))
                      |--Table Scan(OBJECT:([Testing].[dbo].[Customers]))
                      |--Table Scan(OBJECT:(@countries AS [countries]))

3 个答案:

答案 0 :(得分:3)

首先,UPDATE改变了表格。如果在更新期间发生检查点,这意味着在事务日志和数据文件本身上有大量I/O

DML操作绝不比查询快。

其次,你如何衡量速度? SQL Server可以比所有记录更早(甚至不成比例地)返回第一条记录,具体取决于所使用的查询计划以及缓存的填充方式。

<强>更新

从您的计划中我可以看到UNIQUE没有定义countries.countrycode个密钥。

SQL Server必须找到要分配给countrycode的每个customers的单个值(即使实际上只有一个值),并为此执行Stream Aggregate

PRIMARY KEY上创建countries.countrycode

答案 1 :(得分:1)

索引

如果customers上有多个索引,则每个更新的行都会更新每个索引。这是一个资源密集型过程。索引加速选择但减慢更新/插入(通常)。

答案 2 :(得分:0)

选择has(如果数据尚未在内存中)I / O out of Disk。

更新具有读I / O,写入记录I / O和写入存储器I / O.所以我想它应该需要更长的时间。

但是如果你可以选择一个纤细的聚簇索引键,你应该尝试创建一个聚簇索引,这可能会加快速度。