读书频道 > 网站 > 网页设计 > SQL Server性能调优实战
3.5.2 UPDATE语句与事务影响
15-11-02    下载编辑
收藏    我要投稿   

本文所属图书 > SQL Server性能调优实战

本书是一线DBA技术专家精心之作,积作者多年的经验结晶和最佳实践,也是目前市场上为数不多通过存储原理来讲解性能优化,剖析SQL Server架构,从而帮助读者快速高效调优数据库的图书。书中首先简要介绍了SQL S立即去当当网订购

UPDATE语句会更新符合过滤条件的数据行,SQL Server为了保证数据的完整性,在UPDATE语句的执行过程中,会给语句中所涉及的表和数据加上适当的更新锁或排他锁(关于锁的详细信息,后续章节会详细介绍)。由于更新锁/排他锁相对于共享锁的锁兼容性较低,因此当UPDATE语句存在性能问题时,将对SELECT操作造成阻塞。所以需要注意,编写UPDATE语句时,对于小数据量的更新,笔者会建议使用主键或唯一键字段来过滤需要更新的数据。

在默认事务级别中,UPDATE语句进行查询时会添加更新锁(U锁),若找到了需要更新的数据,就会将更新锁转换(Convert)为排他锁(X锁)。由于更新锁和排他锁的兼容性弱,在需要较长执行时间的更新语句或事务中,容易造成阻塞。为了避免造成大量阻塞,应尽量保证更新语句的效率,适当建立索引。

笔者经常会被问道:“A表被更新了,写错过滤条件,有办法恢复吗?”或者“B表被更新了,忘了写过滤条件,有办法恢复吗?”其实,有许多方法可以避免这类问题,例如后面会讲到的OUTPUT子句,以及在更新数据前显式设置一个事务,等等。

在进行数据维护时,经常会遇到一些查询或更新频率非常高的表数据被更新或新字段初始化,对于7×24小时运作的数据库环境来说,长时间的更新维护通常会造成表被锁,从而影响业务功能,无法正常运作,不得不停机操作。笔者常用的一个方法是预先计算好结果,然后分批更新。分批更新时,还需要注意一些小细节。例如,对于比较复杂的计算,预先计算好结果,然后再更新物理表,这样就可避免在更新物理表时再进行计算,从而影响更新时间。下面提供一段示例代码:

--创建临时表,保存需要更新的数据主键

SELECT
 TOP(0) sod.SalesOrderID,
 sod.SalesOrderDetailID,
 sod.ProductID,
 sod.UnitPrice
INTO #SalesOrderNeedUpdate
FROM Sales.SalesOrderDetail AS sod;

--创建聚集,唯一索引,以使后续的删除操作尽量快速

ALTER TABLE #SalesOrderNeedUpdate ADD CONSTRAINT PK_#SalesOrderNeedUpdate PRIMARY KEY(SalesOrderDetailID,SalesOrderID);

--初始化临时表,将需要更新的数据的主键初始化到临时表中。本示例中,需要更新所有的数据

INSERT INTO #SalesOrderNeedUpdate (
 SalesOrderID,
 SalesOrderDetailID,
 ProductID
)
SELECT
 sod.SalesOrderID,
 sod.SalesOrderDetailID,
 sod.ProductID
FROM Sales.SalesOrderDetail AS sod;

--初始化需要更新的字段

UPDATE sonu
SET UnitPrice=p.ListPrice
FROM #SalesOrderNeedUpdate AS sonu
JOIN Production.Product AS p ON sonu.ProductID = p.ProductID;

--创建临时表,保存需要更新的当前小集合

SELECT
 TOP(0) sod.SalesOrderID,
 sod.SalesOrderDetailID,
 sod.UnitPrice
INTO #SalesOrderPagedData
FROM Sales.SalesOrderDetail AS sod;

--开始分批更新数据

WHILE EXISTS(SELECT 1 FROM #SalesOrderNeedUpdate AS sonu)
BEGIN
 INSERT INTO #SalesOrderPagedData (
  SalesOrderID,
  SalesOrderDetailID,
  UnitPrice
 )
 SELECT
  TOP(3000) sonu.SalesOrderID,
  sonu.SalesOrderDetailID,
  sonu.UnitPrice
 FROM #SalesOrderNeedUpdate AS sonu;

 UPDATE sod
 SET sod.UnitPrice=godp.UnitPrice
 FROM Sales.SalesOrderDetail AS sod
 JOIN #SalesOrderPagedData AS sopd ON sod.SalesOrderDetailID = sopd.SalesOrderDetailID AND sod.SalesOrderID = sopd.SalesOrderID;

 DELETE sonu
 FROM #SalesOrderNeedUpdate AS sonu
 JOIN #SalesOrderPagedData AS sopd ON sonu.SalesOrderDetailID = sopd.SalesOrderDetailID AND sonu.SalesOrderID = sopd.SalesOrderID;
END

 

点击复制链接 与好友分享!回本站首页
分享到: 更多
您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力  
上一篇:1.3 功能
下一篇:1.5 小结
相关文章
图文推荐
JavaScript网页动画设
1.9 响应式
1.8 登陆页式
1.7 主题式
排行
热门
文章
下载
读书

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做最好的IT技术学习网站