我注意到在运行 SQL Server 2016 SP1 CU6 的服务器上,扩展事件会话有时会显示导致写入的 SELECT 查询。例如:
执行计划没有显示写入的明显原因,例如可能溢出到 TempDB 的哈希表、假脱机或排序:
对 MAX 类型的变量分配或自动统计更新也可能导致这种情况,但在这种情况下都不是写入的原因。
写的东西还来自什么?
假设我有一个Foo包含列ID1, ID2和一个复合主键的表ID2, ID1。(我目前正在使用 System Center 产品,该产品具有以这种方式定义的多个表,主键列以它们在表定义中出现的相反顺序列出。)
CREATE TABLE dbo.Foo(
ID1 int NOT NULL,
ID2 int NOT NULL,
CONSTRAINT [PK_Foo] PRIMARY KEY CLUSTERED (ID2, ID1)
);
GO
-- Add a row and update stats so that histogram isn't empty
INSERT INTO Foo (ID1, ID2) VALUES (1,2);
UPDATE STATISTICS dbo.Foo;
Run Code Online (Sandbox Code Playgroud)
的key_ordinal列sys.index_columns示出了它们在复合材料中的主键被宣布相同顺序的索引列:
SELECT t.name, i.name, c.column_id, c.name, ic.index_column_id, ic.key_ordinal
FROM sys.tables AS t
JOIN sys.indexes AS i
ON t.[object_id] = i.[object_id]
JOIN sys.index_columns …Run Code Online (Sandbox Code Playgroud) 我正在测试从聚集列存储索引中删除数据。
我注意到执行计划中有一个很大的eager spool操作符:
这完成了以下特征:
如果我欺骗估算器低估,我会得到一个更快的计划,避免使用 TempDB:
预计扫描成本:56.901
(这是一个估计的计划,但评论中的数字是正确的。)
有趣的是,如果我通过运行以下命令刷新增量存储,线轴会再次消失:
ALTER INDEX IX_Clustered ON Fact.RecordedMetricsDetail REORGANIZE WITH (COMPRESS_ALL_ROW_GROUPS = ON);
Run Code Online (Sandbox Code Playgroud)
只有当增量存储中的页面超过某个阈值时才会引入假脱机。
为了检查增量存储的大小,我正在运行以下查询来检查表的行内页:
SELECT
SUM([in_row_used_page_count]) AS in_row_used_pages,
SUM(in_row_data_page_count) AS in_row_data_pages
FROM sys.[dm_db_partition_stats] as pstats
JOIN sys.partitions AS p
ON pstats.partition_id = p.partition_id
WHERE p.[object_id] = OBJECT_ID('Fact.RecordedMetricsDetail');
Run Code Online (Sandbox Code Playgroud)
第一个计划中的假脱机迭代器是否有任何合理的好处?我不得不假设它是为了提高性能而不是为了万圣节保护,因为它的存在不一致。
我正在 2016 CTP 3.1 上对此进行测试,但我在 2014 SP1 CU3 上看到了相同的行为。
我已经发布了一个生成模式和数据的脚本,并指导您在此处演示问题。
这个问题主要是出于对优化器此时行为的好奇,因为我有一个解决方法来解决引发这个问题的问题(一个大的 spool 填充了 TempDB)。我现在通过使用分区切换来删除。
尝试使用特定 SQL Server 群集的网络名称将 SSMS 连接到 Integration Services 时收到以下错误:
连接到计算机 'FooDB' 上的 Integration Services 服务失败,出现以下错误:“访问被拒绝”。
如果计算机尚未配置为允许通过 DCOM 进行远程连接,或者用户确实有权通过 DCOM 访问 SQL Server Integration Services 服务,则会发生此错误。
这是一个有据可查的解决方案的常规问题。例如,请参阅此处和此处的解决方案。
但是,我已经尝试了我所知道的所有解决方案,但问题仍然存在。
更详细地说,我做了以下工作:
验证连接的用户是否具有以上 MsDtsServer100 上链接的文章中列出的 DCOM 权限:
启动和激活权限:允许本地启动、允许远程启动、本地激活、远程激活
访问权限:允许本地访问,允许远程访问
配置权限:允许读取
使用数据包嗅探器确认与连接相关的所有流量都成功通过了防火墙。在 TCP 连接断开之前显示的最后一个数据包是来自服务器的回复,其中包含 MSRPC 标头中“拒绝访问”的 Windows 状态代码。
测试将用户添加到“分布式 COM 用户”组和/或本地管理员组,然后重新启动服务器。这允许用户使用本地节点名称(FooDBN1、FooDBN2)从 SSMS 连接到 SSIS,但是在连接到集群网络名称(FooDB)时,他们仍然会收到“访问被拒绝”错误,这是他们的习惯使用,以及什么对我们的其他集群有效。
此外,我还没有发现在其他集群上更改这些组的成员身份是必要的。
在我检查过的其他集群上,我可以使用集群名称将 SSMS 连接到 SSIS,无需任何非默认配置。
我意识到这可能更适合 ServerFault,如果需要,可以迁移问题,但这也是一个 SQL Server 问题,我认为这里的用户之前可能更可能处理过它。
平台详情:
给定以下常量:
给定这些常量,SQL Server 是否总是为给定的查询生成相同的计划?
如果没有,是否还有其他考虑?是否还需要考虑不确定性因素?
是否有关于 SQL Server 2016 中关于如何估计包含 SUBSTRING() 或其他字符串函数的谓词的基数的更改的任何文档或研究?
我问的原因是我正在查看一个在兼容模式 130 下性能下降的查询,原因与与包含对 SUBSTRING() 调用的 WHERE 子句匹配的行数估计值的变化有关。我通过查询重写更正了这个问题,但我想知道是否有人知道有关 SQL Server 2016 中该领域更改的任何文档。
演示代码如下。在这个测试案例中,估计值非常接近,但准确度因数据而异。
在测试用例中,在兼容级别 120 中,SQL Server 似乎使用直方图进行估计,而在兼容级别 130 中,SQL Server 似乎假定表的固定 10% 匹配。
CREATE DATABASE MyStringTestDB;
GO
USE MyStringTestDB;
GO
DROP TABLE IF EXISTS dbo.StringTest;
CREATE TABLE dbo.StringTest ( [TheString] varchar(15) );
GO
INSERT INTO dbo.StringTest
VALUES
( 'Y5_CLV' );
INSERT INTO dbo.StringTest
VALUES
( 'Y5_EG3' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_NE' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_PQT' );
INSERT INTO …Run Code Online (Sandbox Code Playgroud) sql-server optimization substring sql-server-2016 cardinality-estimates
我见过几个人SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED在阅读系统 DMV 之前打电话。是否有任何理由这样做,假设您没有在同一事务中混合调用 DMV 和表?
我的雇主正在考虑部署 NTFS 碎片整理软件,该软件使用 Windows MoveFile API 对打开的文件进行碎片整理。这将被部署到数千个运行 SQL 版本 2005-2012 和 Windows 版本 2003 和 2008 R2 的 SQL Server 服务器。如果重要的话,我正在谈论的产品是 PerfectDisk,但我相信有类似的程序以相同的方式工作。
到目前为止,除了偶尔出现的 I/O 性能问题之外,测试还没有发现很多问题,这并不奇怪,可以通过重新安排和调整碎片整理来解决。但是,我更关心数据损坏的风险。
这里有没有人有在数据库服务器上在生产中运行这种类型的软件的经验?您是否遇到过任何数据损坏?
尽管无法找到任何确凿的证据表明它存在问题,但我对此感到相当不安。
感谢您的任何答复。
编辑补充:幸好这个可怕的想法被遗忘了,部分原因可能是我给出了一些警告。
通过修改查询或影响优化器的策略,是否可以通过单个搜索或扫描来检索与以下相同的数据?
与此类似的代码和架构目前位于 SQL Server 2014 上。
复制脚本。设置:
USE tempdb;
GO
IF OBJECT_ID('dbo.TestUpload', 'U') IS NOT NULL
DROP TABLE dbo.TestUpload;
CREATE TABLE dbo.TestUpload(
JobRunId bigint NOT NULL,
ThingAName nvarchar(255) NOT NULL,
ThingAType nvarchar(255) NOT NULL,
ThingAGranularity nvarchar(255) NOT NULL,
ThingBName nvarchar(255) NOT NULL,
ThingBType nvarchar(255) NOT NULL,
ThingBGranularity nvarchar(255) NOT NULL
);
CREATE CLUSTERED INDEX IX_JobRunId ON dbo.TestUpload (JobRunId);
GO
INSERT INTO dbo.TestUpload (JobRunId, ThingAName, ThingAType, ThingAGranularity, ThingBName, ThingBType, ThingBGranularity)
VALUES (1, 'A', 'B', 'C', 'D', 'E', 'F');
GO 10
INSERT …Run Code Online (Sandbox Code Playgroud) 我正在与一位正在努力阻止以下错误的开发人员合作:
服务器将断开连接,因为客户端驱动程序在会话处于单用户模式时发送了多个请求。当客户端在会话中仍有批处理运行时发送重置连接的请求,或者当会话正在重置连接时客户端发送请求时,会发生此错误。请联系客户端驱动程序供应商。
发生此错误时,典型的结果是会话持有锁,但没有运行 SQL(sys.dm_exec_requestssession_id没有行),并导致阻塞,直到它被终止。阻塞的原因很简单,但如何阻止错误发生却不是。
关于这个问题的一些事实:
sys.dm_exec_connections为 .Net SqlClient Data Providernet_transport在sys.dm_exec_connections表演Session。如果在连接字符串上设置 Async=true ,它应该可以防止出现此问题。如果您正在使用 MARS 并在多个并发线程上使用相同的连接,则可能发生的情况是重置连接的调用可能会稍微延迟并触发此错误。如果您设置 Async=true,我们会在客户端驱动程序中执行额外的锁定以防止这种情况发生。
关于此错误的更多信息很少。这似乎表明客户端的程序sp_reset_connection在批处理仍在运行时正在调用。我可以设置一个跟踪来确认这一点,但我必须记录很多不相关的活动,而且问题每隔几天才会发生一次。此外,我不确定开发人员是否能够利用这些证据来解决问题。
作为 DBA 或系统管理员,我是否可以使用任何其他技术来进一步解决此问题,或者我可以向开发人员提出任何可能为他提供有用信息或使问题不太可能发生的建议?
sql-server ×10
clustering ×1
columnstore ×1
determinism ×1
dmv ×1
optimization ×1
permissions ×1
ssis ×1
statistics ×1
substring ×1
t-sql ×1
windows ×1