(图拍摄于办公室落地窗口)

周六清晨,东方刚刚露白。

L 早早来到办公室,捎带上最爱的热焦玛。今天会是一场苦战,计划了两个月的上线产品,今天发布。他需要极其敏捷的脑子。另外,只要 L 还在喝着咖啡,说明 DB 肯定是没问题的,也能起到一点安慰军心的作用吧。所以大事件面前,L 总是拿着星巴克晃悠。谁都猜不到他到底是爱喝,还是臭显摆。

F 晃着小脑袋过来了,Release 已经开始了 1 小时,按理 DB 部分部署早该完成。这次稍微超过 L 的预期,但没有告警,大家也就没有太放心上。直到 F 过来找 L, 低头问了下:

“L, 有段更新数字的脚本,跑了40多分钟还没结束。理论上只有100多万数据会被更新,花这么长时间,不知道是否正常?”

F 是个五年陈了,该经历的也都经历了,如今冒出这么个疑问,L 也是慎重起来。“哪段脚本?”

SET NOCOUNT ON ;DECLARE @SalesQuotaKey BigintDECLARE MY_Cur Cursor For
SELECT TOP 1000000 SalesQuotaKey
FROM FactSalesQuotaAudit
WHERE SalesAmountQuota<500000
ORDER BY SalesAmountQuota ASCOPEN MY_Cur
FETCH NEXT FROM MY_Cur INTO @SalesQuotaKeyWHILE(@@FETCH_STATUS = 0 )
BEGIN
UPDATE FactSalesQuotaAudit
SET SalesAmountQuota = SalesAmountQuota + 100000WHERE SalesQuotaKey = @SalesQuotaKey FETCH NEXT FROM MY_Cur INTO @SalesQuotaKey
ENDCLOSE MY_Cur
DEALLOCATE MY_Cur

“嗯,这段貌似会有问题,就看索引是怎么建的”L 常说,trouble shooting 就像是做侦探,有时候,话其实是说给自己听的,“如果在 SalesAmountQuota 上加索引的话,这就有危险”

“果不其然”,L打开 SSMS窗口,找到了索引定义:

CREATE Unique CLUSTERED  index PK_SalesQuotaKey
ON FactSalesQuotaAudit(SalesQuotaKey)CREATE INDEX IDX_SALES_AMT_QUTA
ON FactSalesQuotaAudit(SalesAmountQuota)

为保分析无误,L 还是先看了下现状:

SELECT TOP 1000000 SalesQuotaKey
FROM FactSalesQuotaAudit
WHERE SalesAmountQuota<500000
ORDER BY SalesAmountQuota ASC

“目前来看,这段脚本还在继续跑着”

“但执行计划显示正确跑了 SalesAmountQuota 的索引呢?”F 不解

“其实这里真是这个索引惹的祸”

“索引是用到了,但是每次更新,更新的那行跑到 IDX_SALES_AMT_QUTA 索引后面去了,导致无限在更新 SalesAmountQuota 的值,直到大于 50万”L 觉得平时太强调 seek 索引了,但没有全面透彻的讲解索引其实也有好心办坏事儿的时候。所以索引要给 F 画个脑图:

“更新完的数据又排回索引了,而游标一直在往前读满足条件的数据,你可以细想下这个有趣的过程”看到 F 频频点头,L 自以为已经讲的很明晰了。

"终于跑完了," F 眼见监控 Dashboard 上的那个超长 session 消失了,脸色也开始和悦起来。

“大错即将发生”L 一盆冷水浇过去,F 又不惑,90后小姑娘的脸色,真是跟天气一样,瞬间都能千变万化。

SELECT COUNT(*)
FROM FactSalesQuotaAudit WITH(NOLOCK)
WHERE SalesAmountQuota<500000

“你看,结果是0,肯定不是你想要的结果吧。你原意肯定是在不满50万额度的那些销售上,再加十万,现在全部都加到了50万。这是典型的 Halloween 问题”

“那,怎么办?”F 面对这段让她面红耳赤的游标,简直奔溃

“用临时表,先把数据更新对了,再找最优解决方法”

"那什么是 Halloween 问题?"

故事发生在 50年前的一个晚上,1970年左右,IBM 的一群研究员决定给不满25000美金年薪的雇员,增加10% 的薪水。

他们写了一段 SQL,大意是这样的:

update Employee
Set Salary = Salary * (1 + 10%)
where Salary < 25000

结果等他们运行完毕,发现所有的年薪不满 25000 美金的雇员,他们的薪水统统加到了 25000.

例如,原本是 15000薪水的雇员和 8000 美金年薪的雇员,他们的薪水更新完了之后,都到了25000 美金。这一天正好是 10月31日,Halloween Day. 所以被称为 Halloween Problem.

--完--

往期精彩:

本号精华合集(三)

外企一道 SQL 面试题,刷掉 494 名候选人

我在面试数据库工程师候选人时,常问的一些题

零基础 SQL 数据库小白,从入门到精通的学习路线与书单

禁用 SQL 游标,告诉你外面听不到的原因相关推荐

  1. PL/SQL 游标

    本随笔不是原创,只是学习笔记,用于加深记忆,原创地址PL/SQL --> 游标 一.游标的相关概念和特性 1.定义: 映射到结果集中的某一行的特定位置,类似与C语言中的指针.即通过游标方式定位到 ...

  2. SQL游标的使用与语法

    2019独角兽企业重金招聘Python工程师标准>>> 以[master].[dbo].[spt_values] 这个表为例子 === declare @name nvarchar( ...

  3. SQL游标原理和使用方法(转)

    SQL游标原理和使用方法 在数据库开发过程中,当你检索的数据只是一条记录时,你所编写的事务语句代码往往使用SELECT INSERT 语句.但是我们常常会遇到这样情况,即从某一结果集中逐一地读取一条记 ...

  4. sql游标 while_用SQL Server中的排名函数替换SQL While循环和游标,以提高查询性能

    sql游标 while SQL While loop and cursor are the most common approach to repeat a statement on conditio ...

  5. sql 会话_在特定会话中禁用SQL Server中的触发器

    sql 会话 This article will focus on the various ways to disable triggers in SQL Server so they won't i ...

  6. Library Cache优化与SQL游标

    点击查看全文 Dear 跟着小编一起读好书运动开始啦!咱们作为DBA不仅要外部打扮自己,更要从内部武装.近期,小编将分享冷菠老师的<Oracle高性能自动化运维>一部分精选章节分享给大家. ...

  7. oracle的游标 sql语句,sql游标

    sql游标 游标的类型: 1.静态游标(不检测数据行的变化) 2.动态游标(反映所有数据行的改变) 3.仅向前游标(不支持滚动) 4.键集游标(能反映修改,但不能准确反映插入.删除) 游标使用顺序: ...

  8. 如何创建和使用 SQL 游标

    文章目录 一.游标 二.使用游标 2.1 创建游标 2.2 使用游标 2.3 关闭游标 三.小结 本文介绍什么是 SQL 游标,为什么使用游标,如何使用游标.你使用的 DBMS 可能会提供某种形式的游 ...

  9. SQL 游标使用示例

    SQL游标(cursor)详细说明及内部循环使用示例 定义 游标(cursor)是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果.每个游标区都有一个名字,用户可以用SQL语句逐一从游标中获取 ...

  10. SQL游标——PL/SQL教程(三)

    SQL游标 /* 在执行执行增删改查语句的时候,Oracle都会开辟一块内存空间, 用来暂时存放收到SQL语句影响的数据. 这块内存空间就被称为游标区域,我们可以借助于游标来分析这些受到影响的数据 * ...

最新文章

  1. 我的车模我做主 - 精美的车模作品
  2. 图像处理(三)图像分割(1)Random Walks分割
  3. 操作系统:基本分段存储管理方式
  4. c++和opengl实现gis_从零开始的图形学学习(零):一切的开始 —— 自建OpenGL开发框架
  5. android 绘制5格电量,Android 如何把状态栏信号格改为5格
  6. 服务管理-文件服务器
  7. 基于DDDLite的权限管理OpenAuth.net 1.0版正式发布
  8. Win11系统如何解除网络限制
  9. dns服务器v6解析 windows_04:缓存DNS、Split分离解析、电子邮件通信、Web服务器项目实战...
  10. python特征选择后显示选取的特征名_python实现求特征选择的信息增益
  11. Python的文件锁使用
  12. swift 动画合集
  13. python线程监控_Python多线程的事件监控
  14. 树变二叉树结点数计算
  15. java比较炫的小程序_有人不建议学Java,有人不建议学Python,该怎么选择
  16. clousx6机器人怎么导入词库_clousx6词库编程从零入门:变量总结
  17. 【代码笔记】多线程游戏开发——伏魔记:第一步——开始游戏界面实现(一)...
  18. 如何对关键工序进行质量控制,以保证产品高可靠性
  19. MFC通过CImage绘制透明图层的png图片
  20. 云更新网吧系统服务器,网吧云更新系统使用图文教程

热门文章

  1. 详述支付网关的设计原则
  2. QIIME 2教程. 03老司机上路指南Experience(2021.2)
  3. 【SEO网络推广】会被百度K站的原因
  4. 独立站SaaS建站模式是什么
  5. selenium模拟登陆163邮箱
  6. Ubuntu 20.04 安装企业微信
  7. 16g电脑内存有什么好处_16G电脑运行内存可以达到什么样子。
  8. python制作股票图表-专题:Python matplotlib 绘制股票走势图
  9. 看云烟袅袅,薄如纱衣
  10. SCU2016-05 I题 trie图 + 大数dp