SQL Server 2019 新增功能 --- 语法知识点及使用方法详解
📅 当前环境 :SQL Server 2019 (15.x) 或兼容版本
📌 适用对象:数据库管理员、开发人员、数据工程师、架构师
一、数据虚拟化与大数据群集(Big Data Clusters, BDC)
SQL Server 2019 引入大数据群集,允许通过 T-SQL 查询 HDFS、Spark、外部关系数据库等异构数据源,实现"数据虚拟化"。
核心组件:
- PolyBase:增强版,支持更多数据源(Oracle, Teradata, MongoDB, ODBC 等)。
- 外部表(External Tables):映射外部数据源的虚拟表。
- 数据池(Data Pool):缓存外部数据,提升性能。
- 存储池(Storage Pool):HDFS 存储层。
1.1 配置 PolyBase(启用)
sql
-- 启用 PolyBase 功能(需重启服务)
EXEC sp_configure @configname = 'polybase enabled', @configvalue = 1;
RECONFIGURE;
GO
-- 验证是否启用
SELECT value_in_use FROM sys.configurations WHERE name = 'polybase enabled';
-- 返回 1 表示已启用
⚠️ 前提:
- SQL Server 2019 企业版或开发版。
- 安装 PolyBase 组件(安装时勾选)。
- 重启 SQL Server 服务。
1.2 创建外部数据源(以 Oracle 为例)
sql
-- 1. 创建数据库作用域凭据(用于连接外部数据库)
CREATE DATABASE SCOPED CREDENTIAL OracleCredential
WITH IDENTITY = 'oracle_user', -- Oracle 用户名
SECRET = 'oracle_password'; -- Oracle 密码
GO
-- 2. 创建外部数据源
CREATE EXTERNAL DATA SOURCE OracleDataSource
WITH (
LOCATION = 'oracle://192.168.1.100:1521', -- Oracle 服务器地址
CREDENTIAL = OracleCredential,
PUSHDOWN = ON -- 允许下推计算到 Oracle
);
GO
-- 3. 创建外部表(映射 Oracle 表)
CREATE EXTERNAL TABLE dbo.ExternalCustomers (
CustomerID INT,
FirstName NVARCHAR(50),
LastName NVARCHAR(50),
Email NVARCHAR(100)
)
WITH (
LOCATION = '[ORCL].[SALES].[CUSTOMERS]', -- Oracle 中的表名(数据库.模式.表)
DATA_SOURCE = OracleDataSource
);
GO
-- 4. 查询外部表(透明查询)
SELECT TOP 10 * FROM dbo.ExternalCustomers;
-- ✅ 执行计划会下推 WHERE、JOIN 到 Oracle(如果支持)
💡 注释:
PUSHDOWN = ON:允许 SQL Server 将过滤、聚合等操作推送到外部数据源执行,减少数据传输。- 外部表不存储数据,仅是元数据映射。
- 支持的数据源:Oracle, Teradata, MongoDB, ODBC, HDFS, Spark 等。
1.3 查询 HDFS 数据(CSV 文件)
sql
-- 1. 创建 HDFS 数据源凭据
CREATE DATABASE SCOPED CREDENTIAL HdfsCredential
WITH IDENTITY = 'HadoopUser', SECRET = 'hadoop_password';
GO
-- 2. 创建 HDFS 外部数据源
CREATE EXTERNAL DATA SOURCE HdfsDataSource
WITH (
TYPE = HADOOP,
LOCATION = 'hdfs://namenode:8020',
CREDENTIAL = HdfsCredential
);
GO
-- 3. 创建外部文件格式(CSV)
CREATE EXTERNAL FILE FORMAT CsvFormat
WITH (
FORMAT_TYPE = DELIMITEDTEXT,
FORMAT_OPTIONS (
FIELD_TERMINATOR = ',',
STRING_DELIMITER = '"',
FIRST_ROW = 2, -- 跳过标题行
USE_TYPE_DEFAULT = TRUE
)
);
GO
-- 4. 创建外部表映射 HDFS 文件
CREATE EXTERNAL TABLE dbo.HdfsSalesData (
SaleID INT,
ProductName NVARCHAR(100),
Quantity INT,
SaleDate DATE
)
WITH (
LOCATION = '/data/sales/sales_2025.csv', -- HDFS 路径
DATA_SOURCE = HdfsDataSource,
FILE_FORMAT = CsvFormat
);
GO
-- 5. 查询 HDFS 数据
SELECT
ProductName,
SUM(Quantity) AS TotalQuantity
FROM dbo.HdfsSalesData
WHERE SaleDate >= '2025-01-01'
GROUP BY ProductName
ORDER BY TotalQuantity DESC;
-- ✅ 可与本地表 JOIN!
🌟 优势:
- 无需 ETL,直接查询原始数据。
- 支持结构化(Parquet, ORC)和非结构化(CSV, JSON)。
- 可结合数据池缓存热数据提升性能。
二、智能数据库(Intelligent Database)
SQL Server 2019 引入多项"智能"查询优化功能,自动提升性能。
2.1 批处理模式内存授予反馈(Batch Mode Memory Grant Feedback)
自动调整批处理模式查询的内存授予,避免内存不足或浪费。
✅ 自动启用,无需语法,适用于批处理模式操作(如 Columnstore Index 查询)。
案例:观察内存授予反馈
sql
-- 创建测试表(含列存储索引)
CREATE TABLE dbo.SalesData (
SaleID INT IDENTITY(1,1),
ProductID INT,
Quantity INT,
SaleAmount DECIMAL(10,2),
SaleDate DATE
);
GO
-- 插入100万行测试数据
INSERT INTO dbo.SalesData (ProductID, Quantity, SaleAmount, SaleDate)
SELECT
ABS(CHECKSUM(NEWID())) % 1000,
ABS(CHECKSUM(NEWID())) % 100,
ABS(CHECKSUM(NEWID())) % 10000 / 100.0,
DATEADD(DAY, ABS(CHECKSUM(NEWID())) % 365, '2024-01-01')
FROM sys.objects a, sys.objects b, sys.objects c
WHERE (SELECT COUNT(*) FROM sys.objects) < 1000000; -- 控制行数
GO
-- 创建聚集列存储索引(触发批处理模式)
CREATE CLUSTERED COLUMNSTORE INDEX CCI_SalesData ON dbo.SalesData;
GO
-- 执行查询(首次可能内存授予不足)
SELECT
ProductID,
SUM(SaleAmount) AS TotalSales
FROM dbo.SalesData
WHERE SaleDate >= '2024-06-01'
GROUP BY ProductID
ORDER BY TotalSales DESC
OPTION (RECOMPILE); -- 强制重新编译,观察反馈
GO
-- 查看执行计划:
-- 1. 在 SSMS 中执行,查看"实际执行计划"
-- 2. 查找"聚集索引扫描"或"哈希匹配"操作符
-- 3. 检查"内存授予"和"警告"信息
-- 4. 如果首次授予不足,第二次执行会自动调整!
-- 查询 DMV 查看内存授予反馈历史
SELECT
qs.query_hash,
qs.query_plan_hash,
qs.last_grant_kb,
qs.last_used_grant_kb,
qs.last_ideal_grant_kb,
qs.is_last_grant_feedback_adjusted -- 1=已调整
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
WHERE st.text LIKE '%SalesData%SaleDate%';
GO
💡 原理:
- 首次执行:根据统计信息预估内存。
- 执行后:对比实际使用内存 vs 授予内存。
- 下次执行:自动调整授予量(增大或减小)。
- 适用于:哈希连接、排序、窗口函数等内存密集操作。
2.2 行模式内存授予反馈(Row Mode Memory Grant Feedback)
将内存授予反馈扩展到行模式查询(传统 B 树索引查询)。
✅ 自动启用,SQL Server 2019 CU8+ 默认开启。
案例:行模式内存反馈
sql
-- 创建行存储表(B树索引)
CREATE TABLE dbo.CustomerOrders (
OrderID INT IDENTITY(1,1) PRIMARY KEY,
CustomerID INT NOT NULL,
OrderDate DATE NOT NULL,
TotalAmount DECIMAL(10,2)
);
GO
-- 创建索引
CREATE INDEX IX_CustomerOrders_CustomerID ON dbo.CustomerOrders(CustomerID);
CREATE INDEX IX_CustomerOrders_OrderDate ON dbo.CustomerOrders(OrderDate);
GO
-- 插入测试数据
INSERT INTO dbo.CustomerOrders (CustomerID, OrderDate, TotalAmount)
SELECT
ABS(CHECKSUM(NEWID())) % 50000,
DATEADD(DAY, ABS(CHECKSUM(NEWID())) % 1000, '2023-01-01'),
ABS(CHECKSUM(NEWID())) % 10000 / 100.0
FROM sys.objects a, sys.objects b;
GO
-- 执行行模式查询(涉及排序)
SELECT
CustomerID,
COUNT(*) AS OrderCount,
AVG(TotalAmount) AS AvgAmount
FROM dbo.CustomerOrders
WHERE OrderDate >= '2024-01-01'
GROUP BY CustomerID
HAVING COUNT(*) > 5
ORDER BY AvgAmount DESC
OPTION (RECOMPILE);
GO
-- 查看是否应用行模式反馈
SELECT
qs.query_hash,
qs.is_row_mode_memory_grant_feedback_used -- 1=已使用行模式反馈
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
WHERE st.text LIKE '%CustomerOrders%OrderDate%';
GO
📌 注意:
- 行模式反馈在 SQL Server 2019 CU8+ 默认开启。
- 适用于:
ORDER BY,GROUP BY,DISTINCT,窗口函数等。- 减少
RESOURCE_SEMAPHORE等待和内存溢出错误。
2.3 适用于 MSTVF 的交错执行(Interleaved Execution for MSTVF)
改进多语句表值函数(MSTVF)的基数估计,避免因错误估计导致性能问题。
✅ 自动启用,无需语法。
案例:MSTVF 交错执行
sql
-- 创建多语句表值函数(MSTVF)
CREATE FUNCTION dbo.GetCustomerOrders(@CustomerID INT)
RETURNS @Orders TABLE (
OrderID INT,
OrderDate DATE,
TotalAmount DECIMAL(10,2)
)
AS
BEGIN
INSERT INTO @Orders
SELECT OrderID, OrderDate, TotalAmount
FROM dbo.CustomerOrders
WHERE CustomerID = @CustomerID;
RETURN;
END;
GO
-- 旧版本问题:MSTVF 始终估计返回 1 行,导致执行计划错误
-- SQL Server 2019:交错执行 --- 先执行函数获取实际行数,再优化外层查询
-- 查询使用 MSTVF
SELECT
c.CustomerID,
o.OrderDate,
o.TotalAmount
FROM dbo.Customers c
CROSS APPLY dbo.GetCustomerOrders(c.CustomerID) o -- 假设有 Customers 表
WHERE c.CustomerID BETWEEN 1 AND 100
ORDER BY o.OrderDate;
-- 查看执行计划:
-- 1. 在 SSMS 中执行,查看"实际执行计划"
-- 2. 查找"Table Valued Function"操作符
-- 3. 检查"估计行数" vs "实际行数" --- 应接近!
-- 4. 操作符属性中查看"IsInterleavedExecuted" = True
-- 查询 DMV 验证
SELECT
qs.query_hash,
qs.is_interleaved_executed -- 1=已使用交错执行
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
WHERE st.text LIKE '%GetCustomerOrders%';
GO
💡 优势:
- 消除 MSTVF 的"1行估计"问题。
- 生成更优的 JOIN 和索引策略。
- 显著提升复杂查询性能。
2.4 表变量延迟编译(Table Variable Deferred Compilation)
改进表变量的基数估计,避免因估计为 1 行导致的性能问题。
✅ 自动启用,适用于数据库兼容级别 150(SQL Server 2019)。
案例:表变量延迟编译
sql
-- 设置数据库兼容级别为 150(SQL Server 2019)
ALTER DATABASE YourDatabase SET COMPATIBILITY_LEVEL = 150;
GO
-- 创建测试存储过程
CREATE OR ALTER PROCEDURE dbo.TestTableVariable
AS
BEGIN
-- 声明表变量
DECLARE @TempOrders TABLE (
OrderID INT,
CustomerID INT,
TotalAmount DECIMAL(10,2)
);
-- 插入大量数据
INSERT INTO @TempOrders (OrderID, CustomerID, TotalAmount)
SELECT TOP 10000 OrderID, CustomerID, TotalAmount
FROM dbo.CustomerOrders
ORDER BY OrderID;
-- 使用表变量进行 JOIN(旧版估计1行,新版估计实际行数)
SELECT
c.CustomerName,
t.TotalAmount
FROM @TempOrders t
INNER JOIN dbo.Customers c ON t.CustomerID = c.CustomerID -- 假设有 Customers 表
WHERE t.TotalAmount > 100
ORDER BY t.TotalAmount DESC;
END;
GO
-- 执行存储过程
EXEC dbo.TestTableVariable;
GO
-- 查看执行计划:
-- 1. 在 SSMS 中执行,查看"实际执行计划"
-- 2. 查找"Table Variable"扫描操作符
-- 3. 检查"估计行数" --- 应接近 10000(而非1)
-- 4. 操作符属性中查看"CardinalityEstimationModelVersion" = 150
-- 对比:设置兼容级别为 140(SQL Server 2017)
ALTER DATABASE YourDatabase SET COMPATIBILITY_LEVEL = 140;
GO
EXEC dbo.TestTableVariable; -- 此时估计行数为1,性能差
GO
📌 关键点:
- 仅在兼容级别 150 下生效。
- 编译时根据表变量实际数据量估算行数。
- 解决表变量导致的性能瓶颈。
三、新增近似查询功能(Approximate Query Processing)
用于大数据场景,牺牲少量精度换取查询速度提升。
3.1 APPROX_COUNT_DISTINCT()
近似计算唯一值数量,比 COUNT(DISTINCT) 快 10-100 倍。
语法:
sql
SELECT APPROX_COUNT_DISTINCT(column_name) FROM table_name;
案例:
sql
-- 计算销售数据中不同客户的近似数量
SELECT
APPROX_COUNT_DISTINCT(CustomerID) AS ApproxUniqueCustomers,
COUNT(DISTINCT CustomerID) AS ExactUniqueCustomers -- 对比精确值
FROM dbo.CustomerOrders;
-- 在大型表上测试性能差异
SET STATISTICS TIME ON;
GO
-- 精确计算(可能很慢)
SELECT COUNT(DISTINCT CustomerID) FROM dbo.CustomerOrders; -- 假设1亿行
-- 近似计算(极快)
SELECT APPROX_COUNT_DISTINCT(CustomerID) FROM dbo.CustomerOrders;
GO
SET STATISTICS TIME OFF;
💡 误差范围:通常 < 2%,适用于仪表盘、趋势分析等场景。
四、开发人员新体验
4.1 新增边约束功能(Graph Edge Constraints)
在图数据库中,约束边只能连接指定的节点对。
语法:
sql
-- 创建图节点表
CREATE TABLE dbo.Person (
ID INT PRIMARY KEY,
Name NVARCHAR(50)
) AS NODE;
CREATE TABLE dbo.Company (
ID INT PRIMARY KEY,
Name NVARCHAR(50)
) AS NODE;
-- 创建边表(无约束)
CREATE TABLE dbo.WorksFor AS EDGE;
-- 添加边约束:仅允许 Person -> Company
ALTER TABLE dbo.WorksFor
ADD CONSTRAINT EC_WorksFor CONNECTION (dbo.Person TO dbo.Company);
案例:
sql
-- 插入节点
INSERT INTO dbo.Person (ID, Name) VALUES (1, 'Alice'), (2, 'Bob');
INSERT INTO dbo.Company (ID, Name) VALUES (100, 'Microsoft'), (200, 'Google');
-- 插入合法边(Person -> Company)
INSERT INTO dbo.WorksFor ($from_id, $to_id)
SELECT
p.$node_id,
c.$node_id
FROM dbo.Person p, dbo.Company c
WHERE p.Name = 'Alice' AND c.Name = 'Microsoft';
-- 尝试插入非法边(Company -> Person)--- 将失败!
INSERT INTO dbo.WorksFor ($from_id, $to_id)
SELECT
c.$node_id,
p.$node_id
FROM dbo.Company c, dbo.Person p
WHERE c.Name = 'Google' AND p.Name = 'Bob';
-- ❌ 错误:The edge constraint 'EC_WorksFor' does not allow this connection.
-- 查询约束信息
SELECT
ec.name AS ConstraintName,
object_name(ec.from_obj_id) AS FromTable,
object_name(ec.to_obj_id) AS ToTable
FROM sys.edge_constraints ec
WHERE ec.object_id = OBJECT_ID('dbo.WorksFor');
GO
✅ 优势:
- 强制数据模型完整性。
- 避免错误连接(如 Company -> Person)。
- 提升图查询的可靠性。
4.2 新增图匹配查询(SHORTEST_PATH, Arbitrary Length Patterns)
支持更复杂的图遍历查询。
语法:
sql
-- 最短路径
SELECT ...
FROM node1, edge, node2
WHERE MATCH(SHORTEST_PATH(node1(-(edge)->node2)+))
-- 任意长度模式
MATCH(node1-(edge)->{1,5}node2) -- 1到5跳
案例:
sql
-- 创建社交网络图
CREATE TABLE dbo.Friend (FriendID INT IDENTITY PRIMARY KEY, Since DATE) AS EDGE;
CREATE TABLE dbo.User (UserID INT PRIMARY KEY, Name NVARCHAR(50)) AS NODE;
-- 插入用户
INSERT INTO dbo.User (UserID, Name) VALUES
(1, 'Alice'), (2, 'Bob'), (3, 'Charlie'), (4, 'David'), (5, 'Eve');
-- 插入朋友关系
INSERT INTO dbo.Friend ($from_id, $to_id, Since)
SELECT u1.$node_id, u2.$node_id, '2025-01-01'
FROM dbo.User u1, dbo.User u2
WHERE (u1.Name = 'Alice' AND u2.Name = 'Bob')
OR (u1.Name = 'Bob' AND u2.Name = 'Charlie')
OR (u1.Name = 'Charlie' AND u2.Name = 'David')
OR (u1.Name = 'David' AND u2.Name = 'Eve');
-- 查询 Alice 到 Eve 的最短路径(朋友链)
SELECT
u1.Name AS StartUser,
u2.Name AS EndUser,
STRING_AGG(u.Name, ' -> ') WITHIN GROUP (GRAPH PATH) AS FriendPath,
COUNT(u.UserID) WITHIN GROUP (GRAPH PATH) AS PathLength
FROM dbo.User u1, dbo.User u2, dbo.User u, dbo.Friend f
WHERE MATCH(SHORTEST_PATH(u1(-(f)->u)+))
AND u1.Name = 'Alice'
AND u2.Name = 'Eve'
GROUP BY u1.Name, u2.Name;
-- 查询最多3跳的朋友的朋友
SELECT
u1.Name AS StartUser,
u2.Name AS ConnectedUser,
COUNT(f.FriendID) WITHIN GROUP (GRAPH PATH) AS Hops
FROM dbo.User u1, dbo.User u2, dbo.Friend f
WHERE MATCH(u1(-(f)->{1,3}u2)) -- 1到3跳
AND u1.Name = 'Alice'
AND u2.Name <> 'Alice';
🌟 强大功能:
SHORTEST_PATH:自动找到最短路径。{min, max}:指定跳数范围。STRING_AGG ... WITHIN GROUP (GRAPH PATH):聚合路径节点。
五、其他常用新增功能
5.1 UTF-8 排序规则支持
支持 UTF-8 编码,节省存储空间(尤其对英文/ASCII 数据)。
语法:
sql
-- 创建使用 UTF-8 的数据库
CREATE DATABASE MyUTF8DB
COLLATE Latin1_General_100_CI_AS_SC_UTF8; -- 关键:_UTF8 后缀
-- 或修改现有数据库
ALTER DATABASE MyDB COLLATE Latin1_General_100_CI_AS_SC_UTF8;
案例:
sql
-- 创建 UTF-8 表
CREATE TABLE dbo.Utf8Data (
ID INT IDENTITY,
EnglishText NVARCHAR(100) COLLATE Latin1_General_100_CI_AS_SC_UTF8, -- UTF-8 列
ChineseText NVARCHAR(100) -- 默认排序规则(通常是 UCS-2/UTF-16)
);
-- 插入数据
INSERT INTO dbo.Utf8Data (EnglishText, ChineseText)
VALUES
(N'Hello World! 😊', N'你好世界!😊'),
(N'This is ASCII-heavy text.', N'这是中文文本。');
-- 查看存储大小(UTF-8 对英文更省空间)
SELECT
EnglishText,
ChineseText,
DATALENGTH(EnglishText) AS EnglishBytes, -- UTF-8: ASCII字符占1字节
DATALENGTH(ChineseText) AS ChineseBytes -- UTF-16: 中文字符占2字节
FROM dbo.Utf8Data;
💡 节省空间:
- 英文/ASCII:UTF-8 比 UTF-16 节省 50% 空间。
- 中文/日文:UTF-8 占 3 字节,UTF-16 占 2 字节 → UTF-16 更省。
- 混合文本:根据比例决定。
5.2 RESUMABLE INDEX 操作
创建或重建索引时可暂停和恢复,避免长时间阻塞。
语法:
sql
-- 创建可恢复索引
CREATE INDEX IX_Resume ON table(column)
WITH (ONLINE = ON, RESUMABLE = ON, MAX_DURATION = 60); -- 60分钟超时暂停
-- 暂停索引操作
ALTER INDEX IX_Resume ON table PAUSE;
-- 恢复索引操作
ALTER INDEX IX_Resume ON table RESUME;
-- 中止索引操作
ALTER INDEX IX_Resume ON table ABORT;
案例:
sql
-- 在大型表上创建可恢复索引
CREATE INDEX IX_CustomerOrders_Resumable
ON dbo.CustomerOrders (CustomerID, OrderDate)
WITH (
ONLINE = ON, -- 在线操作,不阻塞查询
RESUMABLE = ON, -- 启用可恢复
MAX_DURATION = 10 -- 10分钟超时自动暂停(单位:分钟)
);
GO
-- 如果被暂停(或超时),可恢复
ALTER INDEX IX_CustomerOrders_Resumable ON dbo.CustomerOrders RESUME;
GO
-- 查看可恢复索引状态
SELECT
object_name(i.object_id) AS TableName,
i.name AS IndexName,
i.is_resumable,
i.percent_complete,
i.state_desc
FROM sys.indexes i
WHERE i.is_resumable = 1;
GO
✅ 优势:
- 避免维护窗口不足导致失败。
- 减少对业务的影响。
- 支持
CREATE INDEX和ALTER INDEX ... REBUILD。
六、关键任务的安全性
6.1 Always Encrypted with Secure Enclaves
支持在服务器端安全飞地(Intel SGX)内进行加密数据的计算,突破传统 AE 的限制。
⚠️ 要求:
- SQL Server 2019 企业版。
- 支持 Intel SGX 的硬件。
- 配置安全飞地。
语法(与传统 AE 类似,但支持更多操作):
sql
-- 创建支持安全飞地的列加密密钥
CREATE COLUMN MASTER KEY CMK_Enclave
WITH (
KEY_STORE_PROVIDER_NAME = N'MSSQL_CERTIFICATE_STORE',
KEY_PATH = N'CurrentUser/My/...'
);
CREATE COLUMN ENCRYPTION KEY CEK_Enclave
WITH VALUES (
COLUMN_MASTER_KEY = CMK_Enclave,
ALGORITHM = 'RSA_OAEP',
ENCRYPTED_VALUE = 0x...
);
-- 创建表(使用 ENCLAVE_COMPUTATIONS)
CREATE TABLE dbo.SecureSalary (
EmployeeID INT PRIMARY KEY,
Name NVARCHAR(50),
Salary DECIMAL(10,2)
ENCRYPTED WITH (
COLUMN_ENCRYPTION_KEY = CEK_Enclave,
ENCRYPTION_TYPE = Randomized,
ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'
)
ENCLAVE_COMPUTATIONS (SIGNATURE = 0x...) -- 启用飞地计算
);
🌟 突破限制:
- 支持
BETWEEN,>,<,LIKE等操作(传统 AE 仅支持=)。- 数据在飞地内解密和计算,SQL Server 仍无法访问明文。
七、高可用性的数据库环境
7.1 Accelerated Database Recovery (ADR)
大幅缩短数据库恢复时间(尤其对长事务)。
✅ 默认启用(数据库级别)。
语法:
sql
-- 启用 ADR(默认已启用)
ALTER DATABASE YourDB SET ACCELERATED_DATABASE_RECOVERY = ON;
-- 禁用 ADR
ALTER DATABASE YourDB SET ACCELERATED_DATABASE_RECOVERY = OFF;
💡 原理:
- 使用"持久版本存储"(PVS)记录事务版本。
- 崩溃恢复时,无需回滚未提交事务(只需丢弃 PVS 中的版本)。
- 恢复时间从小时级缩短到秒级。
八、更加灵活的平台选择
8.1 Linux 和容器支持增强
SQL Server 2019 完全支持 Linux 和 Docker 容器。
Docker 运行示例:
bash
# 拉取 SQL Server 2019 Linux 容器镜像
docker pull mcr.microsoft.com/mssql/server:2019-latest
# 运行容器
docker run -e "ACCEPT_EULA=Y" \
-e "SA_PASSWORD=YourStrong@Passw0rd" \
-p 1433:1433 \
--name sql2019 \
-d mcr.microsoft.com/mssql/server:2019-latest
✅ 优势:
- 跨平台一致性。
- 快速部署和测试。
- 支持 Kubernetes。
九、SQL Server 机器学习服务(Machine Learning Services)
集成 Python 和 R,支持在数据库内执行机器学习。
⚠️ 安装时需选择"机器学习服务"。
案例:使用 Python 执行聚类
sql
-- 启用外部脚本
EXEC sp_configure 'external scripts enabled', 1;
RECONFIGURE;
GO
-- 重启 SQL Server 服务
-- 使用 Python 进行 K-Means 聚类
EXEC sp_execute_external_script
@language = N'Python',
@script = N'
import pandas as pd
from sklearn.cluster import KMeans
# Input Data
InputDataSet.columns = ["CustomerID", "TotalSpent", "OrderCount"]
X = InputDataSet[["TotalSpent", "OrderCount"]]
# K-Means
kmeans = KMeans(n_clusters=3, random_state=0)
InputDataSet["Cluster"] = kmeans.fit_predict(X)
# Output
OutputDataSet = InputDataSet[["CustomerID", "Cluster"]]
',
@input_data_1 = N'
SELECT
CustomerID,
SUM(TotalAmount) AS TotalSpent,
COUNT(*) AS OrderCount
FROM dbo.CustomerOrders
GROUP BY CustomerID
',
@input_data_1_name = N'InputDataSet',
@output_data_1_name = N'OutputDataSet'
WITH RESULT SETS ((CustomerID INT, Cluster INT));
GO
🌟 优势:
- 数据无需出库,安全高效。
- 支持 Scikit-learn, TensorFlow, PyTorch 等库。
- 结果可直接插入表或返回给应用。
十、SQL Server 报表服务(SSRS)
10.1 移动报表和 KPI 支持
增强的 Web 门户支持移动设备和实时 KPI。
📌 无新 T-SQL 语法,主要是前端功能增强。
十一、综合性案例
综合案例1:构建智能数据湖查询平台
sql
-- 目标:使用 SQL Server 2019 查询 HDFS + Oracle + 本地数据,结合智能优化
USE DataLakeDB;
GO
-- 1. 启用 PolyBase
EXEC sp_configure 'polybase enabled', 1;
RECONFIGURE;
GO
-- 2. 创建外部数据源(HDFS + Oracle)
CREATE DATABASE SCOPED CREDENTIAL HdfsCred WITH IDENTITY = 'user', SECRET = 'pwd';
CREATE DATABASE SCOPED CREDENTIAL OracleCred WITH IDENTITY = 'ora_user', SECRET = 'ora_pwd';
CREATE EXTERNAL DATA SOURCE HdfsSource WITH (TYPE = HADOOP, LOCATION = 'hdfs://namenode:8020', CREDENTIAL = HdfsCred);
CREATE EXTERNAL DATA SOURCE OracleSource WITH (LOCATION = 'oracle://dbserver:1521', CREDENTIAL = OracleCred);
-- 3. 创建外部文件格式
CREATE EXTERNAL FILE FORMAT ParquetFormat WITH (FORMAT_TYPE = PARQUET);
CREATE EXTERNAL FILE FORMAT CsvFormat WITH (FORMAT_TYPE = DELIMITEDTEXT, FORMAT_OPTIONS (FIELD_TERMINATOR = ','));
-- 4. 创建外部表
CREATE EXTERNAL TABLE dbo.HdfsSales (
SaleID INT,
ProductID INT,
Amount DECIMAL(10,2),
SaleDate DATE
) WITH (LOCATION = '/data/sales/', DATA_SOURCE = HdfsSource, FILE_FORMAT = ParquetFormat);
CREATE EXTERNAL TABLE dbo.OracleProducts (
ProductID INT,
ProductName NVARCHAR(100),
Category NVARCHAR(50)
) WITH (LOCATION = '[ORCL].[PROD].[PRODUCTS]', DATA_SOURCE = OracleSource);
-- 5. 创建本地维度表
CREATE TABLE dbo.DateDimension (
DateKey DATE PRIMARY KEY,
Year INT,
Quarter INT,
Month INT
);
-- 6. 执行复杂查询(智能优化自动生效)
SELECT
p.Category,
d.Year,
d.Quarter,
APPROX_COUNT_DISTINCT(hs.SaleID) AS ApproxSalesCount, -- 近似计数
SUM(hs.Amount) AS TotalSales
FROM dbo.HdfsSales hs
INNER JOIN dbo.OracleProducts p ON hs.ProductID = p.ProductID
INNER JOIN dbo.DateDimension d ON hs.SaleDate = d.DateKey
WHERE d.Year = 2025
GROUP BY p.Category, d.Year, d.Quarter
ORDER BY TotalSales DESC
OPTION (RECOMPILE); -- 确保使用最新统计信息和智能反馈
GO
-- 7. 创建物化视图(加速查询)
CREATE MATERIALIZED VIEW dbo.SalesSummary
WITH (DISTRIBUTION = ROUND_ROBIN) -- 如果是大数据群集
AS
SELECT
p.Category,
YEAR(hs.SaleDate) AS SaleYear,
DATEPART(QUARTER, hs.SaleDate) AS SaleQuarter,
COUNT_BIG(*) AS SalesCount,
SUM(hs.Amount) AS TotalSales
FROM dbo.HdfsSales hs
INNER JOIN dbo.OracleProducts p ON hs.ProductID = p.ProductID
GROUP BY p.Category, YEAR(hs.SaleDate), DATEPART(QUARTER, hs.SaleDate);
GO
-- 8. 查询物化视图(极快)
SELECT * FROM dbo.SalesSummary WHERE SaleYear = 2025 ORDER BY TotalSales DESC;
GO
✅ 技术整合:
- PolyBase:虚拟化 HDFS 和 Oracle。
- 智能优化:内存反馈、交错执行。
- 近似查询:
APPROX_COUNT_DISTINCT。- 物化视图:预计算加速。
综合案例2:安全合规的图数据库应用
sql
-- 目标:构建社交网络图,包含安全加密和边约束
USE SocialGraphDB;
GO
-- 1. 创建节点表(用户信息加密)
CREATE COLUMN MASTER KEY CMK_Social WITH (
KEY_STORE_PROVIDER_NAME = N'MSSQL_CERTIFICATE_STORE',
KEY_PATH = N'CurrentUser/My/...'
);
CREATE COLUMN ENCRYPTION KEY CEK_Social WITH VALUES (
COLUMN_MASTER_KEY = CMK_Social,
ALGORITHM = 'RSA_OAEP',
ENCRYPTED_VALUE = 0x...
);
CREATE TABLE dbo.UserNode (
UserID INT IDENTITY PRIMARY KEY,
UserName NVARCHAR(50), -- 公开
Email NVARCHAR(100)
ENCRYPTED WITH (
COLUMN_ENCRYPTION_KEY = CEK_Social,
ENCRYPTION_TYPE = Deterministic,
ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'
),
Phone NVARCHAR(20)
ENCRYPTED WITH (
COLUMN_ENCRYPTION_KEY = CEK_Social,
ENCRYPTION_TYPE = Randomized,
ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256'
)
) AS NODE;
-- 2. 创建边表并添加约束
CREATE TABLE dbo.FriendEdge (Since DATE) AS EDGE;
-- 约束:仅允许 UserNode 到 UserNode
ALTER TABLE dbo.FriendEdge
ADD CONSTRAINT EC_Friend CONNECTION (dbo.UserNode TO dbo.UserNode);
-- 3. 插入数据(需在支持 AE 的客户端执行)
-- INSERT INTO dbo.UserNode (UserName, Email, Phone) VALUES (...);
-- 4. 查询最短路径(查找共同好友)
SELECT
u1.UserName AS StartUser,
u2.UserName AS TargetUser,
STRING_AGG(u.UserName, ' -> ') WITHIN GROUP (GRAPH PATH) AS FriendPath
FROM dbo.UserNode u1, dbo.UserNode u2, dbo.UserNode u, dbo.FriendEdge f
WHERE MATCH(SHORTEST_PATH(u1(-(f)->u)+))
AND u1.UserName = 'Alice'
AND u2.UserName = 'Eve'
AND COUNT(u.UserID) WITHIN GROUP (GRAPH PATH) <= 3; -- 限制3跳内
-- 5. 动态数据屏蔽(保护电话号码)
ALTER TABLE dbo.UserNode
ALTER COLUMN Phone ADD MASKED WITH (FUNCTION = 'partial(3, "XXXX", 2)');
-- 6. 创建普通用户(只能看到屏蔽数据)
CREATE USER analyst WITHOUT LOGIN;
GRANT SELECT ON dbo.UserNode TO analyst;
GRANT SELECT ON dbo.FriendEdge TO analyst;
-- 7. 以分析师身份查询
EXECUTE AS USER = 'analyst';
SELECT TOP 5 UserName, Email, Phone FROM dbo.UserNode; -- Phone 显示为 138XXXXXX00
REVERT;
GO
✅ 安全合规:
- Always Encrypted:保护敏感数据。
- 边约束:确保数据模型正确。
- 动态数据屏蔽:控制数据可见性。
- 图查询:支持复杂关系分析。
总结
SQL Server 2019 是一次重大升级,核心亮点:
| 类别 | 关键功能 |
|---|---|
| 智能性能 | 内存授予反馈、MSTVF 交错执行、表变量延迟编译 |
| 数据虚拟化 | PolyBase 增强,统一查询异构数据 |
| 开发体验 | 图数据库增强、UTF-8、近似查询 |
| 安全性 | Always Encrypted with Secure Enclaves |
| 高可用 | Accelerated Database Recovery |
| AI/ML | 内置 Python/R 机器学习 |
🚀 建议:
- 生产环境升级前充分测试。
- 利用智能优化减少手动调优。
- 结合 PolyBase 构建现代数据平台。
- 使用图数据库处理复杂关系。
✅ 掌握这些功能,你将能构建更智能、更安全、更高性能的 SQL Server 应用!