翻译自:node
https://www.mssqltips.com/sqlservertip/5710/whats-new-in-the-first-public-ctp-of-sql-server-2019/web
问题算法
SQL Server 2019的第一个公共CTP版已经发布,充满了加强和新特性(其中不少也能够在预览形式Azure SQL Database里找到)。我以前有深刻了解过,容许我分享一下个人经验。你也能够查看SQL Server团队最新的博文和更新的官方技术文档。sql
解决方案数据库
我将讨论一些新的引擎特性,分为下五个方面:性能、问题定位、安全、可用性和开发。此次,对于有些特性我有更详细的内容,事实上已经写了完整的博文详述几个。当更多的文档和文章可用时,我将回头更新这些部分。放心,这不是一个详尽的列表,只是直到CTP 2.0版我已了解的内容。还会有更多内容到来。浏览器
性能安全
表变量延迟编译(Table variable deferred compilation)服务器
表变量名声有点很差,大多由于预估。默认,SQL Server预计只有一行会出如今表变量中,当实际有多行时会致使某些有趣的计划选择。避免这种状况的典型变通方案是使用OPTION (RECOMPILE),但这须要修改代码,当行数一般相同时单次重编译很浪费时间。引入了跟踪标志2453来模拟重编译行为,可是须要运行在一个跟踪标志下,只有当发现又很明显行数变化时才会发生。架构
在兼容级别150,当表变量调用时你能够延迟编译,意思是,直到表变量被填充一次才会构建一个计划。预估将基于表变量的第一次使用,再次以后将没有重编译发生。这是一个在一直重编译以得到实际每次预估,和从不重编译一直预估为1之间的折中。 若是你的行数保持相对稳定就很好,而且这个数远远大于1就更好,但若是这个数大幅波动就没什么用。并发
在最近发表的博文中,我深刻研究了该功能,SQL Server中的表变量延迟编译,Brent Ozar在更快的表变量和新的参数嗅探问题也谈到了它。
行模式内存授予反馈(Row mode memory grant feedback)
SQL Server 2017引入了批模式内存授予反馈,在这里有详细描述。本质上,对于任何与执行计划有关的内存授予牵涉到批模式操做者,SQL Server会预估查询的内存使用,并将它与请求内存相比较。若是请求的内存过低或过高,致使溢出或浪费内存,它会在下次运行的时候调整与执行计划相关的内存授予。这要么会减小授予以容许更高并发量,要么增长授予以提升性能。
如今在兼容级别150下,对于行模式查询咱们也得到了该行为。若是一个查询被发现须要访问磁盘,对于后续的执行将会增长内存授予。若是查询的实际内存使用少于内存授予的一半,后续授予请求将会更低。Brent Ozar在这篇文章适当的内存授予中讲得更细。
基于行存储的批模式(Batch mode over rowstore)
自从SQL Server 2012,对带有列存储索引的表查询在批模式的性能加强中收益。性能提高是因为相对一行行执行,查询处理器执行批处理。数据行能够在存储引擎上面以批的形式存储,能够避免并行交换算子。Paul White(Twitter帐号@SQL_Kiwi)提醒我若是你使用一个空的列存储表能够执行批模式操做,存储的行由不可见的操做符汇集成批。然而,这个黑 客行为会取消从批模式处理得到的任何提高。在Stack Exchange的回答中有些信息。
在兼容级别150下,SQL Server 2019会在特定的热点案例中自动选择批模式,即便没有出现列存储索引。你会想,为何不仅建立一个列存储索引并使用它?或者使用上面提到的黑 客行为?这种状况扩展到传统的行存储对象,由于列存储索引不老是可能的,因为大量缘由,包括缺少特性支持(例如触发器),大量的更新删除负载下,或者缺少第三方支持。上面提到的黑 客行为只是一个坏消息。
我建立了一个1千万行的简单表,在整型列上建立了一个单一汇集索引,而后运行以下查询:
SELECT sa5, sa2, SUM(i1), SUM(i2), COUNT(*) FROM dbo.FactTable WHERE i1 > 100000 GROUP BY sa5, sa2 ORDER BY sa5, sa2;
这个查询清晰的显示了一个汇集索引查找和并行,可是没有任何列存储索引的迹象(显示在SentryOne执行计划浏览器,一个免费查询调优工具):
若是你深刻研究,会发现几乎全部的操做符都以批模式运行,甚至排序和标量计算:
你能够经过保持在一个更低的兼容级别上、经过修改数据库范围配置(在未来的CTP版本会到来),或经过使用DISALLOW_BATCH_MODE查询提示来禁止该功能:
SELECT … OPTION (USE HINT ('DISALLOW_BATCH_MODE'));
在这个案例中以上查询计划有一个额外的交换运算符,全部的运算符以行模式执行,该查询花费了三倍时间去运行:
你能够在这个图上看到,可是在执行计划树的详细信息里,你也能够看到谓词直到排序后才会消除行:
批模式的选择不老是必杀器。而是与行计数的决定,操做符相关的类型和批模式期待收益有关。
APPROX_COUNT_DISTINCT
新的聚合函数为数据仓库场景设计,等价于COUNT(DISTINCT())。替代执行昂贵的排序去重操做以肯定实际行数,它依赖于统计信息来获取相对真实的数据。你会发现差距是实际计数的2%,97%的时间,一般用于高级别分析,值用于填充一个报表,或快速预估。
我建立了一个表,有一个值范围在100到1000000之间的惟一值的整型列,和一个值范围在100到100000之间的惟一值的字符串列。除了主要整型列上的汇集索引主键,没有其余索引。针对这些列的COUNT(DISTINCT())和APPROX_COUNT_DISTINCT()的比较结果,你能够看到差别总在2%之内。
若是你是内存受限的,回报是巨大的,适用于大多数状况。若是你这个案例中查看执行计划,你会看到在哈希匹配操做符上内存占用量的巨大差别:
注意:
若是你已是内存受限的,你只会看到重要的性能提高。在个人系统上,因为更多CPU被新的函数使用,运行时间稍微更长一些:
若是我有更大的表,更少的可用内存给到SQL Server,更高的并发量,或任何组合,结果颇有可能不同。
查询做用域的兼容级别提示(Query-scoped compatibility level hints)
有一个查询在与当前数据库不一样的兼容级别下运行得更好?如今你可使用新的查询提示支持六个不一样的兼容级别和五个不一样的基数预估模式。如下显示了在每一个案例中使用的可用兼容级别,示例语法和CE模式。你能够看到它如何影响预估,甚至对于系统目录视图:
长话短说:再也不须要记录跟踪标志,或怀疑是否仍然须要担忧在TF 4199下你的优化修复被覆盖,或被某些服务包或累积更新包所消除。注意,这些额外的提示当前也被添加到SQL Server 2017累积更新10中(查看Pedro Lopes的博文查看更多详细信息)。你也能够看到全部可用提示:
SELECT name FROM sys.dm_exec_valid_use_hints;
但请一直记住提示是最后的依靠。它们让你摆脱困境,可是你不能长期让你的代码像那样,由于随着以后的更新行为会改变。
问题定位
默认开启轻量级跟踪(Lightweight profiling on by default)
这个加强须要一点背景知识。SQL Server 2014引入了DMV sys.dm_exec_query_profiles,容许用户运行查询,同时收集查询执行期间全部操做符的诊断信息。在查询完成后,这个信息能够被用来肯定哪一个操做符实际作了最多工做而且为何。没有运行那个特定查询的任何用户,仍然能够对任何会话启用STATISTICS XML或STATISTICS PROFILE,或者对于全部会话经过query_post_execution_showplan扩展事件(经过该事件会对总体性能带来潜在的巨大压力)来得到这个数据的解析。
SSMS 2016添加了功能基于从DMV收集的信息经过执行计划实时显示数据移动,它对于问题定位很是有用。执行计划浏览器也提供了对于查询执行期间可视化数据的实时和重放能力。
从SQL Server 2016 SP1开始,你也能够对于全部会话启用轻量版本的数据收集,经过使用跟踪标志7412或者query_thread_profile扩展事件,以便你能够当即得到任何会话的确切信息而不用在他们的会话中显示启用任何东西(特别是负面影响性能的东西)。与此有关的更多信息在Pedro Lopes的博文中。
在SQL Server 2019,这个进程跟踪默认被启用。因此你不须要运行一个特定扩展事件会话,或者任何跟踪标志,或者在任何独立查询开启STATISTICS选项;你只能对并发会话在任什么时候候从DMV查看数据。你可使用一个新的数据库范围配置叫LIGHTWEIGHT_QUERY_PROFILING来关闭它,但该语法不能工做在CTP 2.0(这将会被未来的CTP修复)。
汇集列存储索引统计信息在克隆数据库时可用(Clustered Columnstore Index Statistics Available in Clone Databases)
在当前版本的SQL Server,克隆数据库只会从汇集列存储索引带来原始统计对象,忽略任何在建立后对该表所作的任何更新。若是你对依赖于基数预估的查询调优和其余性能测试使用克隆,这些案例可能无效。Parikshit Savjani在这篇博文描述了限制,并提供了一个工做区:在开始克隆前,生成了一个针对每一个对象运行DBCC SHOW_STATISTICS…WITH STATS_STREAM的脚本。这个成本很高,彻底容易忘记。
在SQL Server 2019,这些更新的统计信息也只能在克隆时自动可用,所以你能够测试不一样的查询场景,并基于真实统计信息得到可靠的计划,不用对全部表运行STATS_STREAM。
对于列存储的压缩预估(Compression estimates for Columnstore)
在当前版本,存储过程sys.sp_estimate_data_compression_savings有以下检查:
if (@data_compression not in ('NONE', 'ROW', 'PAGE'))
意味着它容许你检查行或页压缩(或去看下移除当前压缩的影响)。在SQL Server 2019,该检查如今像这样:
if (@data_compression not in ('NONE', 'ROW', 'PAGE', 'COLUMNSTORE', 'COLUMNSTORE_ARCHIVE'))
这是个好消息,由于它容许你粗略预估添加一个列存储索引到一个表的影响,或者转换一个表或分区到一个更激进的列存储格式,不用存储表到另外一个系统并实际尝试它。在个人系统上有一个1千万行的表,提供五个参数运行该存储过程:
EXEC sys.sp_estimate_data_compression_savings @schema_name = N'dbo', @object_name = N'FactTable', @index_id = NULL, @partition_number = NULL, @data_compression = N'NONE'; -- repeat for ROW, PAGE, COLUMNSTORE, COLUMNSTORE_ARCHIVE
结果:
如同其余压缩类型,精确性依赖于行取样,和这些数据在其余数据中的表明性。固然,这是一个猜猜看的很好方式而不用精准数据。
得到页信息的新函数(New function to retrieve page info)
DBCC PAGE和DBCC IND长期用于收集包含分区、索引或表的信息。但它们是未公开的和不支持的命令。关于涉及多个索引或页的问题对于自动化解决方案是至关乏味的。
随着sys.dm_db_database_page_allocations的到来,DMF返回特定对象的全部页的一个集合。仍然是未公开的,该功能展现了在大表上的实际问题--谓词下推:即便得到单页的信息,也得读取整个结构,这多是颇为忌讳的。
SQL Server 2019引入了另外一个DMF sys.dm_db_page_info。它基本返回了一页上的全部信息,没有分配DMF的开销。在当前版本,你得已经知道使用这个函数的页号。这多是有意的,由于这样是惟一确保性能的方法。所以若是你尝试肯定一个索引或表里的全部页,你仍然须要使用分配DMF。以后我会写些关于这个函数的博文。
安全
始终使用安全包加密敏感数据(Always Encrypted using Secure Enclaves)
今天,在传输中始终使用安全包加密敏感数据,和在每一个进程端在内存中加密和解密。不幸的是,这一般会引入关键的处理约束,这样不能执行运算和过滤。意味着为了执行一个范围查找,整个数据集得被发送。
一个安全包是一个保护的内存区域,在哪里运算和过滤被委托(在Windows中,这使用基于虚拟化的安全)。数据在引擎中保持加密,可是在安全包中能够被安全加密或解密。你只须要添加ENCLAVE_COMPUTATIONS选项到主秘钥,你能够再SSMS中勾选“Allow enclave computations”复选框:
与老方法相比(经过向导,或者Set-SqlColumnEncyption命令,或应用程序,须要将数据库的全部数据彻底移出、加密、而后发送回数据库),如今你几乎能够当即加密数据:
ALTER TABLE dbo.Patients ALTER COLUMN SSN char(9) -- currently not encrypted! ENCRYPTED WITH ( COLUMN_ENCRYPTION_KEY = ColumnEncryptionKeyName, ENCRYPTION_TYPE = Randomized, ALGORITHM = 'AEAD_AES_256_CBC_HMAC_SHA_256' ) NOT NULL;
这容许通配符和范围查找、排序等,以及查询内的就地加密,无安全损失,由于安全包容许加密和解密在服务器上发生。你也能够执行安全包中的加密秘钥轮询。
我猜该特性将让不少组织修正目标,但在这个CTP版某些优化仍旧是很棒的,而它们默认没启用。但在这篇文章启用丰富的运算你能够了解到如何开启。
在配置管理中的证书管理(Certificate Management in Configuration Manager)
管理SSL和TLS证书一直是一个痛点,不少人不得不执行冗长乏味的工做和自制的脚本,在企业中部署和维护证书。随着SQL Server 2019配置管理器的功能更新,容许你快速查看和验证任何实例的证书,找出即将过时的证书,在AG中跨多个副本(从一个地方:主副本)、或者FCI中的全部节点(从一个地方:活跃节点)同步部署证书。
我尚未尝试全部这些操做,可是它们应该能对旧版的SQL Server起做用,只要从SQL Server 2019版的SQL Server配置管理器来执行。
内置数据分类和审计(Built-In Data Classification and Auditing)
在SSMS 17.5,SQL Server团队在SSMS中添加了分类数据的功能,你能够识别可能包含敏感信息的列,或者可能不遵照各类标准(HIPAA、SOX、PCI和GDPR)。该向导使用一个算法,对于它认为可能致使规范性问题的列给出建议,但你能够本身添加、调整它的建议,并从列表消除任何列。使用扩展属性存储这些分类;基于SSMS的报表使用相同的信息来显示这些被识别的列。报表外,这些属性不可见。
在SQL Server 2019对于该元数据有个新命令,在Azure SQL Database也有,叫作ADD SENSITIVITY CLASSIFICATION。这容许你像SSMS向导同样作一样的事情,可是信息再也不存储为扩展属性,任何对数据的访问自动以新的XML列data_sensitivity_information显示在审计中。这包含了在审计事件中访问的全部信息类型。
例如,有以下表:
CREATE TABLE dbo.Contractors ( FirstName sysname, LastName sysname, SSN char(9), HourlyRate decimal(6,2) );
能够看到,这四列要么容易数据泄露,要么不该该对每一个访问该表的人可用,至少,咱们须要提升可见性。所以能够用不一样方式分类这些列:
ADD SENSITIVITY CLASSIFICATION TO dbo.Contractors.FirstName, dbo.Contractors.LastName WITH (LABEL = 'Confidential – GDPR', INFORMATION_TYPE = 'Personal Info'); ADD SENSITIVITY CLASSIFICATION TO dbo.Contractors.SSN WITH (LABEL = 'Highly Confidential', INFORMATION_TYPE = 'National ID'); ADD SENSITIVITY CLASSIFICATION TO dbo.Contractors.HourlyRate WITH (LABEL = 'Highly Confidential', INFORMATION_TYPE = 'Financial');
如今,不用看sys.extended_properties,你能够查看sys.sensitivity_classifications的元数据:
若是你对该表审计SELECT或DML,你没必要修改审计;建立了分类后一个SELECT *将在审计日志中产生新的data_sensitivity_information列:
<sensitivity_attributes> <sensitivity_attribute label="Confidential - GDPR" information_type="Personal Info" /> <sensitivity_attribute label="Highly Confidential" information_type="National ID" /> <sensitivity_attribute label="Highly Confidential" information_type="Financial" /> </sensitivity_attributes>
这明显不能解决全部规范性问题,可是开了个好头。若是你试用向导自动识别列,那么会自动将sp_addextendedproperty调用翻译为ADD SENSITIVITY CLASSIFICATION命令,能够很好的听从规范性。以后我会写更多关于此的博文。
你也能够基于标签元数据自动或更新权限。对一个用户、组或彻底可管理的角色,建立一个禁止访问全部Confidential – GDPR列的动态SQL语句。以后我会展开来说。
可用性
可恢复在线索引建立(Resumable online index creation)
SQL Server 2017引入了暂停和恢复在线索引重建的功能,对于你想修改使用的CPU数颇有用,在一个故障转移事件后继续剩下的操做,或者只是填补维护窗口间的空白。以前的博文我已讲到该特性,关于SQL Server 2017中的可恢复在线索引重建。
在SQL Server 2019,你可使用相同的语法在线建立索引,你能够暂停和恢复,甚至设置运行时上线(在上线将会暂停运行):
CREATE INDEX foo ON dbo.bar(blat) WITH (ONLINE = ON, RESUMABLE = ON, MAX_DURATION = 10 MINUTES);
若是运行时间太长,你能够在另外一个会话使用ALTER INDEX来暂停(哪怕这个索引还不存在):
ALTER INDEX foo ON dbo.bar PAUSE;
在当前版本当恢复时不能像重建那样减小并行度。若是你尝试减小DOP:
ALTER INDEX foo ON dbo.bar RESUME WITH (MAXDOP = 2);
你会获得:
Msg 10666, Level 16, State 1, Line 3 Cannot resume index build as required DOP 4 (DOP operation was started with) is not available. Please ensure sufficient DOP is available or abort existing index operation and try again. The statement has been terminated.
事实上,当你这么作时,至少在当前版本,只会触发一个没有选项的恢复,会获得相同的错误消息。我猜恢复尝试记录在某处并被重用。你须要指定正确或更高的DOP以便继续:
ALTER INDEX foo ON dbo.bar RESUME WITH (MAXDOP = 4);
很明显,当恢复一个暂停的索引建立时你能够增长DOP,你只是不能减小。
另外一个额外的好处是,当使用新的数据库范围配置ELEVATE_ONLINE和ELEVATE_RESUMABLE时,默承认以对数据库执行在线和可恢复索引操做。
汇集列存储索引在线建立、重建(Online create / rebuild for Clustered Columnstore Indexes)
除了可恢复的在线索引建立,你也能够在线建立或重建汇集列存储索引(固然这也是可恢复的)。巨大改变是你再也不须要维护窗口来执行索引维护,一个更具说服力的案例:将行存储转换为列存储:
CREATE TABLE dbo.splunge ( id int NOT NULL ); GO CREATE UNIQUE CLUSTERED INDEX PK_Splunge ON dbo.splunge(id); GO CREATE CLUSTERED COLUMNSTORE INDEX PK_Splunge ON dbo.splunge WITH (DROP_EXISTING = ON, ONLINE = ON);
警告:从传统的汇集索引转换为汇集列存储索引,只有在你已存在的汇集索引是以特定的方式建立时才能够在线操做。若是它是显式汇集索引约束或者内联建立索引:
CREATE TABLE dbo.splunge ( id int NOT NULL CONSTRAINT PK_Splunge PRIMARY KEY CLUSTERED (id) ); GO -- or after the fact -- ALTER TABLE dbo.splunge ADD CONSTRAINT PK_Splunge PRIMARY KEY CLUSTERED(id);
将会报错:
Msg 1907, Level 16 Cannot recreate index 'PK_Splunge'. The new index definition does not match the constraint being enforced by the existing index.
为了转换为汇集列存储索引,你得先删除该约束,可是你仍然能执行在线操做:
ALTER TABLE dbo.splunge DROP CONSTRAINT PK_Splunge WITH (ONLINE = ON); GO CREATE CLUSTERED COLUMNSTORE INDEX PK_Splunge ON dbo.splunge WITH (ONLINE = ON);
在大表上,它可能要比主键建立为惟一汇集索引花的时间更长。我不肯定是否为预期行为,或者是当前CTP版本的限制。
辅助副本到主副本链接重定向(Secondary to Primary Replica Connection Redirection)
该特性容许你不用监听器配置重定向,所以即使辅助副本在链接串中显式命名,你能够切换链接到主副本。当你的群集拓扑不支持监听器,或者当你使用无群集AG,或者在多子网场景下有一个复杂的重定向架构,你也可使用该特性。例如,这将阻止尝试对一个只读副本写操做(失败)的链接。
开发
图加强(Graph enhancements)
图关系如今对node或edge表支持使用MATCH谓词的MERGE语句;如今一条语句能够更新一个存在的edge或插入一个新的edge。一个新edge约束容许控制一个edge能够链接那个node。
UTF-8
SQL Server 2012添加了对UTF-16的支持,经过将排序规则命名为_sc后缀来增补字符,像Latin1_General_100_CI_AI_SC,对于使用Unicode列(nchar/nvarchar)。在SQL Server 2017,能够以UTF-8格式导入和导出数据,经过BCP和BULK INSERT来处理这些列。
在SQL Server 2019,有新的排序规则在SQL Server内本地支持存储为UTF-8数据。所以,你能够适当的使用新的以_SC_UTF8后缀的排序规则建立char或varchar列存储UTF-8数据,像Latin1_General_100_CI_AI_SC_UTF8。这能够帮助提升扩展应用和其余数据库平台和系统的兼容性,不用花费性能去存储nvarchar。
发现的一个小彩蛋
在个人记忆中,SQL Server用户老是抱怨模糊的错误信息:
Msg 8152 String or binary data would be truncated.
在当前的CTP版本中,我发现了以前没有的有趣错误信息:
Msg 2628 String or binary data would be truncated in table '%.*ls', column '%.*ls'. Truncated value: '%.*ls'.
我不认为这里还有什么须要说明的;这是一个伟大的姗姗来迟的改进,将让不少人很是高兴。然而,该功能在CTP 2.0不可用;我只是给你窥探下未来的加强,你可能尚未发现。Brent Ozar在当前CTP版本中列出了全部新的消息,在他的博文中准备了一些有用的评注:sys.messages解密。
总结
SQL Server 2019提供了大量的加强来提高你钟爱的关系数据库平台,还有大量的改变我尚未说起的。持久内存支持,机器学习服务群集,Linux上的复制和分布式事务,Kubernetes,Oracle/Teradata/MongoDB的链接器,同步AG副本最多可到5个支持Java(相似于Python/R的实现),最后一点,新的尝试“Big Data Cluster”。这些新特性你须要填写EAP表单得到。
Bob Ward即将出版的新书,Pro SQL Server on Linux – Including Container-Based Deployment with Docker and Kubernetes,会给你一些新线索。Brent Ozar的博文谈到了对用户自定义标量函数的即将到来的修复。
但即使是在第一个公共CTP版,这些特性都只是针对每一个人的,我鼓励你本身作实验,让我知道你以为怎样。
接下来
阅读更多关于SQL Server 2019的资源: