我一直认为CONCAT函数实际上是+(字符串连接)的包装,并带有一些额外的检查,以使我们的生活更轻松。
我还没有找到任何关于这些功能是如何实现的内部细节。至于性能,当数据在循环中连接时,调用似乎会产生开销CONCAT(这似乎很正常,因为有额外的 NULL 句柄)。
几天前,一位开发人员修改了一些字符串连接代码(从+到 ,CONCAT)因为不喜欢语法并告诉我它变得更快。
为了检查情况,我使用了以下代码:
DECLARE @V1 NVARCHAR(MAX)
,@V2 NVARCHAR(MAX)
,@V3 NVARCHAR(MAX);
DECLARE @R NVARCHAR(MAX);
SELECT @V1 = REPLICATE(CAST('V1' AS NVARCHAR(MAX)), 50000000)
,@V2 = REPLICATE(CAST('V2' AS NVARCHAR(MAX)), 50000000)
,@V3 = REPLICATE(CAST('V3' AS NVARCHAR(MAX)), 50000000);
Run Code Online (Sandbox Code Playgroud)
这是变体一:
SELECT @R = CAST('' AS NVARCHAR(MAX)) + '{some small text}' + ISNULL(@V1, '{}') + ISNULL(@V2, '{}') + ISNULL(@V3, '{}');
SELECT LEN(@R); -- 1200000017
Run Code Online (Sandbox Code Playgroud)
这是变体二:
SELECT @R = CONCAT('{some small text}',ISNULL(@V1, '{}'), ISNULL(@V2, …Run Code Online (Sandbox Code Playgroud) 我在 AWS i3.16xlarge 上运行 SQL Server 2022 RC1 设置,具有 2 个插槽、2 个 NUMA 节点、每个节点 32 个逻辑处理器、总共 64 个逻辑处理器。
安装程序推荐 MAXDOP 8:
但是,如果您单击该链接来配置 MAXDOP,建议会显示:
根据那篇知识库文章,MAXDOP 应该是 16,而不是 8。当然,从技术上讲,8 小于 16 - 但 2、4 或 15 也是如此。8 从哪里来?
SQL Server 安装完成且服务启动后,日志显示 SQL Server 自动实施具有 4 个节点的 Soft-NUMA,每个节点有 16 个逻辑处理器:
同样,这表明 MAXDOP 应为 16。
这是一个错误,还是我错过了一些明显的事情?是否还有另一个不成文的规则,设置将在 MAXDOP 8 处停止?
根据文档,返回的列timestamp_utc应为datetime2(7)类型
但是当我这样查询时
SELECT
*
FROM sys.fn_xe_file_target_read_file('system_health*.xel', null, null, null)
WHERE timestamp_utc > dateadd(hour, -1, GETUTCDATE())
Run Code Online (Sandbox Code Playgroud)
它不返回任何行。仅当我向datetime2添加显式转换时,它才返回行
SELECT
*
FROM sys.fn_xe_file_target_read_file('system_health*.xel', null, null, null)
WHERE cast(timestamp_utc as datetime2(7)) > dateadd(hour, -1, GETUTCDATE())
Run Code Online (Sandbox Code Playgroud)
这与文档中的最后一个示例匹配(即使没有引起注意)
这是为什么?
SQL Server 2022 引入了针对事务日志文件增长事件的即时文件初始化。在2022 年新增功能页面中,微软指出:
一般来说,事务日志文件无法从即时文件初始化 (IFI) 中受益。从 SQL Server 2022 (16.x)(所有版本)和 Azure SQL 数据库开始,即时文件初始化可以使事务日志增长事件受益最多 64 MB。新数据库的默认自动增长大小增量为 64 MB。大于 64 MB 的事务日志文件自动增长事件无法从即时文件初始化中受益。
为了测试这一点,我尝试反复以不同大小(例如 50 和 70MB)增长日志文件,但是......它们都不是瞬时的。
DROP DATABASE LogGrowthTest;
GO
CREATE DATABASE [LogGrowthTest]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N'LogGrowthTest', FILENAME = N'Z:\MSSQL\Data\LogGrowthTest.mdf',
SIZE = 8192KB , FILEGROWTH = 60000KB )
LOG ON
( NAME = N'LogGrowthTest_log', FILENAME = N'Z:\MSSQL\Data\LogGrowthTest_log.ldf' ,
SIZE = 8192KB , FILEGROWTH = 60000KB )
GO
DECLARE @TestStartTime DATETIME2 = GETDATE(), @i …Run Code Online (Sandbox Code Playgroud) 我的家庭实验室设置由跨两台物理主机在 HyperV 中运行的四台服务器组成。SQL Server 实例为 SQLAG101、SQLAG102、SQLAG201 和 SQLAG202。
SQLAG101 和 SQLAG102 是 SQLAG100 可用性组的成员,并且位于 192.168.0.0/24 网络上。
SQLAG201 和 SQLAG202 是 SQLAG200 可用性组的成员,并且位于 192.168.2.0/24 网络上。
流量在两个子网之间路由,这两个子网都是我的实验室的本地子网(即涉及的延迟非常小)。
SQLDAG 是跨越 SQLAG100 和 SQLAG200 的分布式可用性组。已经运行良好约 6 个月,AG 成员服务器之间的自动故障转移以及两个 AG 之间的手动故障转移工作正常,并且没有数据丢失。
在我的测试服务器上,我在使用以下命令的数据库的分布式 AG 转发器上看到以下错误FILESTREAM:
操作系统在“F:\SQLServer\HV2019\FILESTREAM\dag_test_db\dag_test_db_fg_fs_f01\3e6a0757-7405-4ee2-b8a8-df878b8cd7ce\a10e3ae8”上尝试“CreateFileW”时返回错误“2(系统找不到指定的文件。)” -922c-4821-904e-7555c031630d\0000008f-000292b0-0006'位于'fsdohdlr.cpp'(2474)。
由于以下原因,数据库“dag_test_db”的 Always On 可用性组数据移动已暂停:“系统”(源 ID 3;源字符串:“SUSPEND_FROM_CAPTURE”)。要恢复数据库上的数据移动,您需要手动恢复数据库。有关如何恢复可用性数据库的信息,请参阅 SQL Server 联机丛书。
(顺便说一句,喜欢在线书籍参考)
为了排除故障,我已经完全放弃了dag_test_db转发器和辅助转发器。然后,我从主数据库中进行了完整备份,并将其恢复到转发器,并根据需要通过恢复日志备份进行前滚,然后再dag_test_db通过以下方式将备份添加到转发器可用性组中:ALTER DATABASE [dag_test_db] SET HADR AVAILABILITY GROUP = SQLAG200;
最初,转发器 AG (SQLAG200) 的可用性组仪表板显示数据库正在同步,但大约一小时后,同步状态显示NOT SYNCHRONIZING,同步运行状况原因描述显示SUSPEND_FROM_CAPTURE。
chkdsk /f在 F: …
sql-server availability-groups distributed-availability-groups sql-server-2022
将 SQL Server 从 2019 年升级到 2022 后,以下使用链接服务器的查询开始失败(为了简单起见,我省略了一些列名称和详细信息):
UPDATE [<remote server>].[<remote db>].dbo.Projects
SET RemoteColumnName = p.LocalColumnName
FROM prod.Projects p
WHERE p.ProjectID = Projects.ProjectID;
Run Code Online (Sandbox Code Playgroud)
然而,不涉及本地表工作的基本更新就很好了。SQL Server 报告以下错误,我什至在文档中找不到该错误:
UPDATE [<remote server>].[<remote db>].dbo.Projects
SET RemoteColumnName = p.LocalColumnName
FROM prod.Projects p
WHERE p.ProjectID = Projects.ProjectID;
Run Code Online (Sandbox Code Playgroud)
两台服务器都是 SQL Server 2022,在升级之前一切正常。
为本地和远程表添加 DDL,以防万一。但是,问题似乎与模式无关,并且在具有不同数据类型的不同表上重现。
-- Table on the remote linked server
CREATE TABLE dbo.Projects
(
ProjectID BIGINT NOT NULL,
RemoteColumnName VARCHAR(255) NOT NULL,
CONSTRAINT PK_Projects PRIMARY KEY CLUSTERED (ProjectID)
)
-- Table on the local server
CREATE …Run Code Online (Sandbox Code Playgroud) 对于非sys.columns.sys.indexessys.tablesdb_owner
要重现,请在 Linux 上使用 SQL Server 2022(我使用的是 16.0.4035,这是撰写本文时的最新版本)并执行以下命令。它创建一个虚拟数据库,其中包含 500 个表,每个表有 10 列,这样sys.columns该数据库就会获取大约 5000 条记录。如果您手头的数据库总数超过 1000 列,则可以跳过创建虚拟数据库。
CREATE DATABASE SLOWSYSTABLES
GO
USE SLOWSYSTABLES
DECLARE @i int
DECLARE @createTable nvarchar(max)
SET @i = 0
WHILE (@i < 500)
BEGIN
SET @createTable = 'CREATE TABLE dummy_' + CAST(@i as nvarchar) + '(Col1 int not null identity(1,1) primary key, Col2 int, Col3 int, Col4 int, Col5 int, Col6 int, Col7 int, Col8 int, Col9 int, Col10 int)' …Run Code Online (Sandbox Code Playgroud) 我有一个查询,其中以下where子句需要花费大量时间来执行,因为基础表中有大量数据:
环境:SQL Server 2022
WHERE条款:
DATEFROMPARTS(dyear, dmonth, dday)
BETWEEN DATEADD(m, -2, DATEADD(mm, DATEDIFF(m, 0, GETDATE()), 0))
AND CAST(CAST(DATEADD(d, -2, GETDATE()) AS DATE) AS DATETIME)
Run Code Online (Sandbox Code Playgroud)
dyear, dmonth, dday由于使用了函数,它当前不使用索引(所有三个 int 列)。
如何重写它以便可以使用底层索引来使查询运行得更快?
抱歉,由于安全限制,我无法共享执行计划。
数据存储格式由第三方定义,不受我们控制。例如,不能选择将计算列添加到随后可以建立索引的表中。
目前,我遇到了 SaaS 应用程序的一些数据库性能问题。白天,RESOURCE_SEMAPHORE 等待统计数据会猛增 30 到 60 秒,持续 1 到 2 分钟。在此期间,我还从我们的服务器收到一封或多封严重性为 17 的警报邮件,其中包含警告“资源池‘内部’中没有足够的系统内存来运行此查询。”
我们已经解决了具有大量内存授予的效率最低的查询(1.5 到 2.5 GB 授予,但使用率仅为 5% 或更少)。为了精确定位这些查询,我们使用了 Brent Ozar 的 sp_BlitzCache。不幸的是,这些更改后仍然出现性能问题。
请注意,此时我们有一个代理作业每 5 分钟运行一次 DBCC FREEPROCCACHE。这样做会使问题更加分散。将此作业更改为每半小时运行一次似乎会使问题变得更糟。当然,运行此作业还有其他影响,例如更高的编译/秒和更高的 CPU 利用率,但目前这是一个“两全其美”的解决方案。
恐怕内存压力问题是由于服务器配置的 RAM 内存不足造成的?这个假设是正确的还是这些问题是由其他原因造成的?
服务器统计
SQL Server Native Client(通常缩写为 SNAC)已从 SQL Server 2022 (16.x) 和 SQL Server Management Studio 19 (SSMS) 中删除。不建议在新开发中使用 SQL Server Native Client(SQLNCLI 或 SQLNCLI11)和旧版 Microsoft OLE DB Provider for SQL Server (SQLOLEDB)。今后切换到适用于 SQL Server 的新 Microsoft OLE DB 驱动程序 (MSOLEDBSQL) 或最新的适用于 SQL Server 的 Microsoft ODBC 驱动程序。
我曾经使用 SQL Server 配置管理器创建别名,但从 SQL Server 2022 开始,创建别名的表单已禁用所有字段:
如何在 SQL Server 2022 中创建别名,这可能吗?
当启用自动调整时,使用SET AUTOMATIC_TUNING(FORCE_LAST_GOOD_PLAN),然后基于查询回归假设SQL Server自动决定强制执行一个计划,那么它什么时候重新访问它的决定并重新评估是否有更好的计划可以执行该查询更快/更少的资源?
我创建了一个包含的可用性组,但我不知道为什么作业在节点之间不同步。可能是什么问题呢?它不应该自动完成吗?
为了响应这个答案,我执行了以下操作:
我已连接到我们现在用作主服务器 (xxxxx) 的服务器,并且我在那里创建了一个测试作业。
数据库的同步工作正常,但不适用于登录和作业。
sql-server availability-groups contained-database sql-server-2022
我从 SQL Server 2014 迁移到 SQL Server 2022。
我首先从 SQL Server 2014 实例创建完整备份,然后运行RESTORE DATABASE下面所示的脚本来进行测试迁移。一切都按计划进行。
一周后,我删除了新服务器上的所有数据库,再次将 SQL Server 2014 备份到相同的文件名,然后再次运行以下脚本。然而,SQL Server 2022 并没有恢复该文件的最新版本,而是仅恢复了一周前的数据。只需右键单击用户界面并从那里执行“恢复”即可恢复数据的当前版本。
有人可以帮我理解为什么这是为了防止将来发生这种情况吗?
BACKUP DATABASE db1 TO DISK = db1.BAK;
Run Code Online (Sandbox Code Playgroud)
RESTORE DATABASE [db1]
FROM DISK = N'\\sql2014\migration\db1.BAK' WITH FILE = 1,
MOVE N'db1_data' TO N'D:\Data\db1_data.mdf',
MOVE N'db1_log' TO N'D:\Log\db1_log.ldf',
NOUNLOAD,
REPLACE,
STATS = 5;
GO
Run Code Online (Sandbox Code Playgroud) sql-server-2022 ×13
sql-server ×12
alias ×1
concat ×1
distributed-availability-groups ×1
linux ×1
maxdop ×1
memory ×1
numa ×1
restore ×1
t-sql ×1
update ×1