🪟 第2章 SQL Server数据库环境搭建
📄 一句话概括

SQL Server 从 2008 到 2022 走了七代,每一代只多加一样东西:分页、JSON、Linux、智能查询。 Express 版免费,但四条硬限制摆在那儿:单库 10 GB、缓冲池 1410 MB、四核、没有代理。 产品名和版本号不是一回事——「2008」的内部版本号是 10.0,2008 R2 是 10.50。

📝 本章和前面几章的关系

教材 2.1 只有一页,讲 SQL Server 是什么、有哪几个版本。 这一节短,但它定了后面所有代码的天花板——你装的版本决定了能用哪条语法、库能长到多大。 上一节 1.4 把四个产品摆在一起比过,这一节只看 SQL Server 自己:它是什么血统、分成几档、 免费的那一档差在哪。 演示里真跑了「版本对照表」:拿一个版本号去比每一项功能的最低要求,直接告诉我哪条语法能用、 哪条不能。

一、七个版本,一代一样新东西

版本 内部版本号 最值得记的新功能
2008 10.0 表值参数、MERGE、稀疏列
2012 11.0 序列、OFFSET/FETCH 分页、AlwaysOn
2014 12.0 内存优化表(全内存跑 OLTP)
2016 13.0 JSON、行级安全、动态数据脱敏、Query Store
2017 14.0 Linux 版、STRING_AGG、图数据库
2019 15.0 大数据群集、Java 扩展、智能查询处理
2022 16.0 参数敏感计划优化、GENERATE_SERIES

这七行里,真正改变了「能干什么」的是三行。 2012 加了 OFFSET/FETCH,在这之前分页只能靠 ROW_NUMBER() 套子查询; 2016 加了 JSON 函数,在这之前存 JSON 只能当字符串; 2017 能装在 Linux 上,在这之前它只能在 Windows 上跑。 其余几代更多是「内部变快」:查询优化器更聪明、并行更细、内存管得更好。这些改动不影响你写 SQL, 影响的是同一条 SQL 跑多久。 教材用的是 2019。 如果你手上的库是 2012 或更早,第 8 章的分页、第 7 章的 STRING_AGG 都要改写法。 这不是「新版本更好」,是「旧版本根本没有这个函数」。

二、Express 版:免费的四条限制

限制项 数值 撞上了会怎样
单个数据库大小 10 GB 再写就报错,只能拆库或升级
缓冲池内存 1410 MB 超出部分走磁盘,越跑越慢
CPU 1 个插槽或 4 核(取小) 多核机器用不满
SQL Server Agent 没有 定时任务得靠 Windows 计划任务

第一行是最容易撞上的。一个只增不减的日志表,一天写十几万条,两三年就到 10 GB。 到那天的选项只有三个:清历史、拆库、买标准版。 第二行更隐蔽:它不是「超过就报错」,而是「超过就变慢」。1410 MB 的缓冲池装不下热数据, 每次查询都要读盘——你不会收到任何提示,只觉得「最近怎么这么慢」。 第三行的意思是:八核的服务器装了 Express,也只有四核在干活。所以拿 Express 压测出来的 QPS, 不能用来估算标准版的上限。 第四行少了 Agent,影响的是「定时任务」这一类需求:备份、清理、汇总,在标准版里写成作业就行, 在 Express 上得挂到 Windows 计划任务里,用 sqlcmd 调。

三、10 GB 到底够用多久

演示里算了一道除法:一天写 12 万条、每条 320 字节,一天 36.6 MB,10 GB 撑 280 天,约 0.8 年。 这道除法值得每个人自己算一遍,因为「够不够」这件事完全取决于业务。同样是 10 GB, 一个只存订单头的库能用五年,一个存操作日志的库连一年都撑不住。 算完通常有三种结论:够用(那就别升级)、差一点(清历史或归档)、差很多(那就得改架构)。 最不该出现的是第四种:什么都没算,先买了标准版。

四、产品名和版本号不是一回事

@@VERSION 返回的字符串长这样:Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)。 头一段是产品名,第二段才是版本号。排查问题时报「版本号」比报「产品名」有用, 因为产品名有歧义——很多人还在说「SQL Server 2008」,实际装的是 2008 R2,版本号 10.50。 这两者差着一个 Service Pack 的功能集,有时候一条语法在 10.0 上不认、在 10.50 上认。 所以查兼容性的时候,认版本号,不认产品名。 演示里那张「功能 × 最低版本」的对照表就是这个用法:先查出本机版本号,再逐条比对,比翻文档快。

五、动手 Demo:版本谱系与 Express 的边界

这一段把七个版本、六条功能的最低版本要求都写成数据,然后用一次比较算出「在 2016 上哪条能用」。 再用一道除法算 10 GB 能撑多久,最后把 Express 的四条限制列清楚。

import sqlite3

# 七个版本:产品名、内部版本号、代表功能
VER = [(u"2008", u"10.0", u"表值参数、MERGE、稀疏列"),
       (u"2012", u"11.0", u"序列、OFFSET/FETCH 分页、AlwaysOn"),
       (u"2016", u"13.0", u"JSON、行级安全、Query Store"),
       (u"2019", u"15.0", u"大数据群集、智能查询处理"),
       (u"2022", u"16.0", u"GENERATE_SERIES")]

# 六条功能各自的最低版本
FEAT = [(u"OFFSET/FETCH 分页", u"2012"), (u"JSON 函数", u"2016"),
        (u"STRING_AGG", u"2017"), (u"GENERATE_SERIES", u"2022")]

c = sqlite3.connect(u":memory:")
c.execute(u"CREATE TABLE tb_ver (v TEXT, no TEXT, feat TEXT)")
c.executemany(u"INSERT INTO tb_ver VALUES (?,?,?)", VER)

mine = c.execute(u"SELECT no FROM tb_ver WHERE v = ?", (u"2016",)).fetchone()[0]
for name, need in FEAT:
    n = c.execute(u"SELECT no FROM tb_ver WHERE v = ?", (need,)).fetchone()[0]
    print(name, need, u"能" if float(mine) >= float(n) else u"不能")

# Express 的 10 GB 能撑多久
per_day, row_bytes = 120000, 320
daily = per_day * row_bytes / 1024.0 / 1024.0
print(u"一天 %.1f MB,10 GB 撑 %.0f 天" % (daily, 10 * 1024 / daily))

实跑输出:

--------------------------------------------------------------------
版本谱系与 Express 的边界
--------------------------------------------------------------------


  ① 七个版本,每代多一样东西
  --------------------------------------------------------------------
| 版本 | 内部版本号 | 最值得记的新功能 | 备注 |
|---|---|---|---|
| 2008 | 10.0 | 表值参数、MERGE、稀疏列 | 2008 R2 是 10.50 |
| 2012 | 11.0 | 序列、OFFSET/FETCH 分页、AlwaysOn | 第一个支持列存储索引 |
| 2014 | 12.0 | 内存优化表、AlwaysOn 增强 | 第一个能全内存跑 OLTP |
| 2016 | 13.0 | JSON、行级安全、动态数据脱敏、Query Store | 第一个原生支持 JSON |
| 2017 | 14.0 | Linux 版、STRING_AGG、图数据库 | 第一次能装在 Linux 上 |
| 2019 | 15.0 | 大数据群集、Java 扩展、智能查询处理 | 本课教材用的版本 |
| 2022 | 16.0 | 参数敏感计划优化、GENERATE_SERIES | 目前最新 |

  「内部版本号」是 @@VERSION 里那串数字的头一段,
  排查问题时比产品名有用——很多人还在叫「SQL Server 2008」,报上来的版本号却是 10.50。

  ② 版本号决定你能用哪条语法
  --------------------------------------------------------------------
| 功能 | 最低版本 | 在 2016 上能用吗 |
|---|---|---|
| OFFSET/FETCH 分页 | 2012 | 能 |
| 序列 SEQUENCE | 2012 | 能 |
| JSON 函数 | 2016 | 能 |
| 行级安全 RLS | 2016 | 能 |
| STRING_AGG | 2017 | 不能 |
| GENERATE_SERIES | 2022 | 不能 |

  第二列是「最低版本」,第三列是拿本机的 2016 去比的结果。
  这类对照表在升级前必须查一遍——不是所有新语法都能在旧版本上跑。

  ③ Express 版:免费,但有四条硬限制
  --------------------------------------------------------------------
| 限制项 | 数值 | 撞上了会怎样 |
|---|---|---|
| 单个数据库大小 | 10 GB | 再写就报错,只能拆库或升级 |
| 缓冲池内存 | 1410 MB | 超过的查询走磁盘,越跑越慢 |
| CPU | 1 个插槽或 4 核(取小) | 多核机器用不满 |
| SQL Server Agent | 没有 | 定时任务得靠 Windows 计划任务 |

  第一行是最容易撞上的:一个做日志的表,两年就能涨到 10 GB。
  到那天的选项只有三个:清理历史、拆成多个库、或者买 Standard 版。

  ④ 粗算一下:10 GB 够用多久
  --------------------------------------------------------------------
  假设一天写 120000 条日志、每条 320 字节:
  一天 36.6 MB,10 GB 能撑 280 天,约 0.8 年。
  这就是为什么「要不要买标准版」这个问题,答案往往是一道除法题。

  ⑤ 教材用的 2019 在哪一档
  --------------------------------------------------------------------

  [教材原码 · 本沙箱不执行]
  | SELECT @@VERSION;
  | -- Microsoft SQL Server 2019 (RTM) - 15.0.2000.5 (X64)
  这一段在真实例上执行;本沙箱没有实例,只能贴出来。

  看到「15.0」就知道是 2019。教材第 2 章装的就是这个版本。

**版本这件事的实用价值只有两个:查语法能不能用、算限制够不够。**
**前者看「最低版本」,后者看「Express 的四条限制」——两件事都在这张表里。**

第二段那张表是这一节最实用的东西: 第二列是「最低版本」,第三列是拿本机版本去比的结果。升级前查一遍,就知道哪条 SQL 要改。 第三段的四条限制里, 只有第一条会「报错」,其余三条都只是「变慢」或「用不满」。这也是它们容易被忽略的原因—— 变慢不会给你任何提示。 第四段那道除法的结果:一天 36.6 MB,10 GB 撑 280 天,约 0.8 年。 这个数不是给所有人用的,是给「一天十几万条日志」这个场景用的。换成订单表, 同一个 10 GB 能撑十年。 最后一段贴了 SELECT @@VERSION 的原码,本沙箱跑不了。 但版本号那串格式值得记住:产品名 - 版本号 - 补丁号 (平台)。排查问题时,这三个数各有用处。

30 秒实验

  1. 把你手上那个库的 @@VERSION 查出来,看内部版本号是多少。 如果是 10.x,第 8 章的 OFFSET/FETCH 分页就要改成 ROW_NUMBER() 的写法。
  2. 拿真实的日志量算一遍:一天多少条、每条多少字节、10 GB 能撑多久。 算完再看「要不要升级」这个问题——多数时候答案就在这个除法里。
  3. 想一想:如果一个库已经 9.5 GB,除了升级还有哪三条路? 清历史、拆库、归档到另一个库——三条路都不改架构,改的是「数据放哪儿」。

常见误区

  1. 「Express 够用了,反正是学习」。学习确实够。 但要记住它没有 Agent—— 教材第 17 章的定时备份、第 12 章的事件,在 Express 上都得换写法。 不是不行,是得绕着走。
  2. 「装了 2019 就能用所有新语法」。不行。 数据库还有个「兼容级别」(Compatibility Level),从旧版本还原上来的库会保留旧级别, 新语法照样报错。要在库属性里手动升级。
  3. 「Express 版就是精简版,功能一样」。差得比想象多: 没有 Agent、没有 AlwaysOn、没有分区表、没有资源调控器。前两个影响运维, 后两个影响大数据量下的设计。
自测三问(点开对答案) 1. 为什么「版本号」比「产品名」可靠? —— **因为产品名有歧义。** 2008 和 2008 R2 都叫「SQL Server 2008」,但版本号一个是 10.0、 一个是 10.50,功能集不一样。**查兼容性、报 bug 的时候,报 15.0 比报 2019 精确。** 2. Express 的四条限制里,哪一条不会报错? —— **后三条都不会报错。** 缓冲池超了只是变慢,CPU 超了只是用不满,没有 Agent 只是不能建作业。 **只有「单库 10 GB」会真的报错。** 所以「变慢」这类问题,往往查到最后才发现是版本限制。 3. 一天 12 万条、每条 320 字节,10 GB 能撑多久? —— **一天 36.6 MB,10 GB 是 10240 MB,除下来 280 天,约 0.8 年。** **这道题的意义不在答案,在「先算一遍再决定买不买」这个习惯。**

下一篇进 2.2a 安装前的准备。 那一节不讲理论,直接跑一个自检脚本:查系统、查磁盘、查 1433 端口有没有被占——这三项不过, 装到一半就得回退。

相关笔记