加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.0516zz.com/)- 智能数字人、图像技术、AI硬件、数据标注、数据治理!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

SQL Server数据库设计避坑12实战要点

发布时间:2026-10-16 08:12:56 所属栏目:MsSql教程 来源:DaWei
导读:  跟人吵架——就昨天,客户现场,我盯着他建的那张 OrderHeader,主键是 UNIQUEIDENTIFIER,Clustered Index 也是它,还带 NEWID() 默认值。我说你这等于给 SQL Server 每插一行就重排整个 B+ 树。他抬头看我一眼,手指头在键

  跟人吵架——就昨天,客户现场,我盯着他建的那张 OrderHeader,主键是 UNIQUEIDENTIFIER,Clustered Index 也是它,还带 NEWID() 默认值。我说你这等于给 SQL Server 每插一行就重排整个 B+ 树。他抬头看我一眼,手指头在键盘上敲得特别慢,一下、两下、三下,停住,说:“我们上云了,Azure 能扛。”


  我原以为他是真信 Azure 自动优化,结果他接了个电话,捂着听筒说了句“妈,挂面煮软点”,然后回头跟我说:“我们DBA去年离职了,现在归运维管,他们说‘云不就是不用操心么’。”我桌上那份黄焖鸡米饭刚拆开,油都浮在汤上,还没来得及搅,隔壁机柜的风扇突然啸叫起来,像指甲刮黑板,持续了十八秒。没关,没人去关。


  第1条:别让 Clustered Index 碎成渣——你用 GUID 当聚集键,就等于每天拿砂纸打磨 SSD 寿命。我敢打包票,三年后你查 sys.dm_db_index_physical_stats 的 avg_fragmentation_in_percent,八成过六十。不是估算,是实测,2025年12月,三家客户,同款设计,全中。其中一家报表跑十秒的查询,重建聚集索引后掉到七百毫秒。但第七百二十三毫秒那个抖动,我至今没敢告诉他们那是 tempdb 日志写入延迟——反正他们也不问。


  第2条:外键不加索引?行啊,删父表一条记录试试。上次一个同事——姓张,在西安远程支持,穿灰连帽衫,视频里能看到他背后窗框结了霜——他硬是没加索引,非说“数据量小”。等真正并发 DELETE Customer 的时候,他那边鼠标卡住三分钟,连 Ctrl+Alt+Del 都弹不出。最后我让他手动 Kill SPID,他点了五次才点对。窗外开始下雨,雨滴斜着打在玻璃上,一道一道往下淌。


  第3条:datetime2(7)?拜托,你们真需要纳秒精度?你业务系统日志都打不到毫秒级,却给 CreateTime 字段留七位小数。这个我说不准。可我知道有个金融客户,同样字段用 datetime2(0),磁盘省了三百七十二GB,备份窗口从四十一分钟缩到二十七。但人家后来换了时钟源服务器,NTP 同步漂移变大,反而出了一次时间乱序的脏读——这锅我没背,我甩给网管了。


文章配图,仅供参考

  第4条:不要在 NVARCHAR(MAX) 上建全文索引再配 CONTAINS,更别顺手加上全文目录在主文件组。那天我进机房的时候,空调刚坏,热风直吹脖子,我扯了三次工装领子才松开。监控面板上全文索引人口队列涨到两万三千条,没人知道为啥。最后发现,是有人把 XML 日志直接塞进一列 NVARCHAR(MAX),全文索引一边解析标签一边报错,日志循环积压。运维小李在吃外卖,鸭血粉丝汤,他吸溜吸溜喝汤的时候,我在后台 kill 了三个 fulltext crawl process。


  第5条:复合索引顺序,左前缀不是玄学,是你查 WHERE Status = ‘Shipped’ AND CreatedDate > ‘2024-01-01’,结果你索引建的是 (CreatedDate, Status) ——恭喜,你成功说服 SQL Server 全表扫。这不是理论,是某天凌晨两点,客户电话打进来,说“发货单查不出来”,我连上去一看执行计划,Index Seek 下面写着“Actual Number of Rows: 968312”,而 Estimated 是 87。我改完索引,重新编译,挂断电话。挂断前听见对方那边小孩在喊“爸爸我的恐龙不见了”,然后他轻轻说:“哦…找到了。”


  说到恐龙……我抽屉里还放着2009年买的SQL Server 2005联机丛书U盘,蓝色塑料壳,USB口歪了。前两天想翻个语法,插进去死活不认。试了三台电脑,两个USB集线器,最后一次插进我笔记本,居然响了一声,但资源管理器里还是没盘符。我盯着那U盘看了十四秒,没拔出来。后来我打开 SSMS,自己写了句 SELECT @@VERSION,抄下来发群里,标题就写:“恐龙没死,只是懒得动。”


  第6条:别在索引列上写函数。WHERE YEAR(OrderDate) = 2024?行,你享受你的非SARGable吧。但我要提醒你一句:我们做性能复核时,看到某张日志表被这么干过,整整十七个月没更新统计信息——不是忘了,是 DBA 在脚本注释里写“反正这列不会用于过滤”,结果半年后老板要按自然年出环比。没人怪他,因为统计信息更新任务早就被另一个同事禁用了,理由是“影响白天ETL”。那同事姓陈,总爱摸后颈,我第一次见他就是在测试环境,他边摸边说:“这事儿得走变更流程。”


  第7条:不要为‘将来可能用到’建列。什么 “IsDeletedBit”、“TenantId”、“VersionStamp”,你写满三行注释,不如先看看当前业务需求文档有没有签字。我们之前有个系统,User 表预留了八个扩展字段,全带 NULLABLE,结果五年过去,只用了一个——还是为了兼容另一套废弃的SSO。那套SSO今年六月正式下线,他们才想起把那列 DROP 掉。DROP 语句跑了十一分钟,期间所有 ALTER TABLE 请求排队。当时我在泡茶,水开了,咕嘟咕嘟,没人关。


  优胜劣汰?对。但淘汰的不是设计,是人。能活下来的不是最优雅的方案,是那个谁都没想起来动它、也没人敢动它的表。我昨天在客户服务器上看 sys.tables,有一张叫 Archive_2016_Q3_FullBackupHistory_old_renamed_bak,创建时间是2016年9月22日,modify_date 是2018年11月3日——就一次修改,加了个注释:/ don’t touch /。我截图发群里,没人回。群里安静了四分半钟,直到有人转了条猫舔爪子的短视频。


  我下周得去趟呼和浩特,现场看他们的分区切换策略。他们说已经照着微软白皮书做了。我行李箱里塞了三包速溶咖啡,两副耳机,还有去年没拆封的SQL Server 2022安装镜像U盘——红色的,接口还是好的。至于这张卡到底要不要格式化……等我看见他们 first_value() 写错地方再说吧。

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!