我对为什么我的查询没有使用我认为是选择性索引的东西感到非常困惑。
我的模型由索赔、联系人和电话号码组成。每个索赔有 1 个联系人,每个联系人都有许多电话号码。索赔可以有状态,电话号码有类型。

我在状态的 Claim 上添加了一个索引,它包括 ContactID。
create index Status on tClaim(Status) include (Name,ContactID)
Run Code Online (Sandbox Code Playgroud)
我在电话上为 ContactID 和类型添加了一个索引,其中包括号码。
create index ContactID_Type on tContactPhone(ContactID,Type) include (Number)
Run Code Online (Sandbox Code Playgroud)
我正在尝试编写一个查询,该查询返回状态为“赢得”的所有索赔以及索赔联系人的相应“家庭电话”。我已经尝试了 2 种方法。一种包括加入通讯录,另一种没有。两者都不会产生我期望的计划。
select
c.ID,
c.Name,
p.Number
from
tClaim c
left join tContactPhone p on
c.ContactID=p.ContactID and p.Type='Home'
where
c.Status = 'Won'
select
c.ID,
c.Name,
p.Number
from
tClaim c
inner join tContact co on
co.id=c.ContactID
left join tContactPhone p on
co.ID=p.ContactID and p.Type='Home'
where
c.Status = 'Won'
Run Code Online (Sandbox Code Playgroud)
我回来的计划拒绝使用 tContactPhone.ContactID_Type。它建议按类型索引,这没有意义,因为它似乎没有 ContactId 选择性。
这是我用来创建要测试的示例数据集的脚本。请注意我的实际数据集要大得多,命名得更好,并且有更多的字段;但这被提炼出来以复制我的情况 [AKA 我什至不喜欢命名约定和数据生成,但它完成了工作:)] …
index sql-server execution-plan cardinality-estimates sql-server-2019
我们正在为一位客户运行 SQL Server 2019 CU12。不久前,我们开始遇到有线死锁,即单个进程在访问表变量时自身陷入死锁。
死锁报告示例
<deadlock>
<victim-list>
<victimProcess id="process2ae9f9f7468" />
</victim-list>
<process-list>
<process id="process2ae9f9f7468" taskpriority="0" logused="0" waitresource="OBJECT: 2:-1194094756:0 " waittime="110" ownerId="6978622122" transactionname="GetInitializedIMA" lasttranstarted="2021-09-15T21:46:44.243" XDES="0x2b4d9477be8" lockMode="Sch-S" schedulerid="3" kpid="10868" status="suspended" spid="102" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2021-09-15T21:46:44.113" lastbatchcompleted="2021-09-15T21:46:44.113" lastattention="2021-09-15T21:46:15.777" clientapp=".Net SqlClient Data Provider" hostname="removed" hostpid="15900" loginname="removed" isolationlevel="read committed (2)" xactid="6978622078" currentdb="15" currentdbname="MigrationSubjects" lockTimeout="4294967295" clientoption1="673187936" clientoption2="128056">
<executionStack>
<frame procname="unknown" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000">unknown</frame>
</executionStack>
<inputbuf>
(@Ids [SubjectRegistry.Consolidation.IdTable] READONLY)
DELETE [reg].[HistoricalCompanyInfo] FROM [reg].[HistoricalCompanyInfo] t
INNER JOIN @Ids ids ON ids.Id = t.HistoricalCompanyInfoId
</inputbuf>
</process>
</process-list>
<resource-list>
<objectlock …Run Code Online (Sandbox Code Playgroud) 在我的 SSMS(我使用的是 18.10)项目中,我对 Intellisense 在我的文件中不起作用这一事实感到沮丧。我猜测这是由于代码库的大小造成的,但事实上,我发现有点奇怪。
在下面的代码中:
CREATE FUNCTION X() RETURNS INT
WITH INLINE = OFF
AS
BEGIN
RETURN 1;
END;
Run Code Online (Sandbox Code Playgroud)
如果我删除WITH INLINE = OFF,Intellisense 会重新打开。到底是怎么回事?
最近,我们将一台生产服务器从 SQL Server 2016 升级到 SQL Server 2019 (CU 15)。这对我来说是一个在我们的主应用程序数据库上启用查询存储的绝佳机会。它已经运行了几天,这是总体资源消耗报告显示的内容:
在屏幕截图中,我精心挑选了一些看起来很疯狂的数字(查询存储启用的第一天),并将它们标准化为更容易讨论的度量单位。诸如逻辑读取消耗约 183 TB的数据,或内存消耗约 5 TB的数据之类的事情,在这台服务器上似乎几乎是不可能的。
该数据库是数据库中的 John Smith,数据文件大小仅为100 GB ,日志文件大小为200 GB 。全天最多可能有 100 个不同的用户连接到它,并且一天内不会创建大量交易。服务器本身仅为其配置了32 GB内存。要消耗5 TB内存,一天中分配的内存需要被填满150 多次。
我可以考虑添加的唯一其他可能相关的信息是升级后,我们立即将此数据库的“兼容性级别”设置为 150 (SQL Server 2019) 并保留“旧基数估计”设置。我知道这并不理想,最好在收集基线指标时让尘埃落定,但升级的部分原因是为了解决一些紧急的性能问题,从我们的测试来看,这些设置组合实际上最有效(并且仍然看起来)工作得很好)。
我们之前遇到的一些性能问题是由于疯狂的基数估计造成的,如果查询存储使用估计数据点,那么我实际上可以看到此报告的数字是相关的,但我不得不想象该报告是使用实际数据点?不过,如果这是我的生产服务器/数据库在我不断征服基数估计问题时的配置方式存在根本错误的另一个迹象,那将会很有趣。
我是否读错了这些数字,查询存储是否出问题了,或者我的服务器是否正常?
当执行查询时,SQL Server将产生一个查询计划列表,并启发式地选择成本较低的计划。
所选择的计划将存储在计划缓存中,以供后续看到相同查询时使用。
当表的某些属性发生变化或者重建索引时,它会再次产生一个查询计划列表,并启发式地选择一个成本较低的查询计划,并将其存储在计划缓存中。
但是,MSDN 似乎表明估计计划存储在计划缓存中,请参见下面的屏幕截图。那是对的吗?
我有两台服务器 A 和 B。两者都位于 Always On 组中。B 服务器配置为只读请求。到目前为止,这工作得很好,但最近查询服务时出现了问题。
该服务首先对表(可能在 A 服务器上)进行更新,然后在 B 服务器上进行只读选择。开发商表示,这是两笔独立的交易。
不幸的是,选择不会返回之前进行更新的值。仅在大约 1 到 1.5 秒后才会出现正确的值。我们以前从未能够观察到这种行为。
服务器设置为同步提交。所有数据库都是同步的,没有数据丢失。只读路由已经过测试并且有效。可读辅助设置为“是”。
我作为MSSQL数据库的DBA工作了大约1.5年,我不太明白AG中的两个节点A和B如何通信,但我假设两个节点会同时接收数据使用“同步提交”,对吗?
造成 1 到 1.5 秒时间差的原因是什么?
服务器是带有 CU12 的 SQL 2019 Enterprise - 在带有 Windows Server 2016 Standard 的一些功能强大的物理机上运行。
我正在使用 XEblocked_process_report 来检测和分析阻塞。
但由于这是一个时间点情况,我只能看到当前正在运行的阻塞领导者的语句以及被阻塞会话试图获取的不兼容锁。
因此,如果阻塞领导者在一个事务中有多个批次/语句,我无法找出之前的哪个语句导致阻塞。
重现脚本
/* Set up tables */
CREATE TABLE dbo.FirstQuery (Id int PRIMARY KEY)
CREATE TABLE dbo.SecondQuery (Id int PRIMARY KEY)
INSERT INTO dbo.FirstQuery (Id)
OUTPUT Inserted.Id INTO dbo.SecondQuery ( Id )
VALUES (1), (2), (3)
/* set up the blocked process event */
EXEC sys.sp_configure
@configname = 'blocked process threshold (s)' -- varchar(35)
, @configvalue = 10 -- int
RECONFIGURE
CREATE EVENT SESSION [blocked_process_report] ON SERVER
ADD EVENT sqlserver.blocked_process_report
(
ACTION(sqlserver.session_id,sqlserver.sql_text,sqlserver.tsql_stack)
)
GO
ALTER EVENT …Run Code Online (Sandbox Code Playgroud) 我有一个关于表中主键列的统计信息。当我使用默认选项更新统计信息时:
UPDATE STATISTICS dbo.MyTable PK__MyTable__CB394B3946083350
Run Code Online (Sandbox Code Playgroud)
我得到一个直方图如下(删节)
RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
3400002201 0 1 0 1
3400009992 18103.04 1 7790 2.323882
3400040033 26083.68 1 26080 1.000144
3400050456 13029.09 1 10422 1.250153
3400087676 26083.68 1 26080 1.000144
3400103858 19556.38 1 16181 1.208602
3400126866 13029.09 1 13029 1
3400162832 39138.27 1 35965 1.088232
3400213115 45665.56 1 45641 1.000547
3400238444 26083.68 1 25328 1.029836
3400242626 13029.09 1 4181 3.116262
3400262174 19556.38 1 19547 1.00048
3400283983 26083.68 1 21808 1.19606
3400304837 19556.38 1 …Run Code Online (Sandbox Code Playgroud) sql-server primary-key statistics index-statistics sql-server-2019
我目前正在浏览《Pro SQL Server 2019 管理:现代 DBA 指南》,发现一件事让我有些困惑。
在第 5 章:配置实例中,有关最小和最大服务器内存的部分(第 139-140 页)说:
在许多环境中,您可能希望为最小和最大服务器内存提供相同的值。这将避免 SQL Server 动态管理其保留的内存量的开销。
但是,如果您有多个实例,则动态内存管理可能会有所帮助,以便在任何给定时间具有最重工作负载的实例可以消耗最多的资源。
...假设您有一个实例并且没有其他应用程序(例如 SSIS 包)在服务器上运行,您通常会将最小和最大内存设置设置为
- 内存 - 2 GB
- (内存/8)* 7
然而,“为最小和最大服务器内存提供相同的值”的建议与文档相矛盾,文档说:
不建议将最大服务器内存 (MB) 和最小服务器内存 (MB) 设置为相同或接近相同的值。
在什么情况下最好将最大服务器内存和最小服务器内存设置为相同的值?
或者我对建议有什么误解?
我正在调整 SQL Server 2019 中的一些 SQL 性能,并且遇到了涉及行目标问题的一个查询问题。简化的查询是:
select TOP 1 ISNULL(RUNID,-1)
from T_PROCESS_MONITOR mon WITH (INDEX = IDX_T_PROCESS_MONITOR_RUNID)
WHERE
mon.SOURCE = 'Dynamic Export'
AND
mon.STATUS = 'PROCESSING'
Run Code Online (Sandbox Code Playgroud)
(索引提示只是为了强制优化器使用索引来匹配基准)
如果我通过另一个查询提示禁用行目标OPTION (MAXDOP 1, USE HINT('DISABLE_OPTIMIZER_ROWGOAL')),则查询的性能会显着不同(在这种情况下 MAXDOP 并不重要)。我知道行目标会影响估计的行数,并且基于此我认为它实际上会调整执行计划。但这里的情况并非如此。两个查询的执行计划完全相同,但没有行目标的执行计划要快得多(1 秒 vs 12 秒):

有人可以向我解释一下有什么区别吗?因为尽管估计的行数不同,但两个索引扫描实际上从同一索引读取相同数量的行,然后我期望性能是相同的。
编辑:共享执行计划:
sql-server ×10
sql-server-2019 ×10
blocking ×1
deadlock ×1
index ×1
memory ×1
monitoring ×1
optimization ×1
performance ×1
plan-cache ×1
primary-key ×1
query-store ×1
ssms ×1
statistics ×1
upgrade ×1