我一直在尝试诊断应用程序中的减速。为此,我记录了 SQL Server扩展事件。
存储过程的执行时间变化很大。这个存储过程的很多执行在 < 1s 内返回:
而对于那个“快速”的bucket,它的时间远小于1s。它实际上是大约 90 毫秒:
但是有一个长尾用户必须等待 2s、3s、4s 秒。有些必须等待 12 秒、13 秒、14 秒。然后是真正可怜的灵魂,他们必须等待 22 秒、23 秒、24 秒。
30 秒后,客户端应用程序放弃,中止查询,用户不得不等待30 秒。
所以我试图关联:
而且似乎没有任何相关性;似乎没有一个原因
持续时间 vs 逻辑读取:无论是少量还是大量的逻辑读取,持续时间仍然波动很大:
持续时间 vs 物理读取:即使查询不是从缓存中提供的,并且需要大量物理读取,它也不会影响持续时间:
持续时间 vs cpu 时间:无论查询占用 0 秒的 CPU 时间,还是完整的 2.5 秒的 CPU 时间,持续时间都具有相同的可变性:
奖励:我注意到Duration v Physical Reads和Duration v CPU …
我在一台服务器上进行了查询,优化器估计其成本为 0.01。实际上,它最终运行得非常糟糕。
注意:您可以在 Stackoverflow 上找到详细的 ddl、sql、表等。但是这些信息虽然有趣,但在这里并不重要——这是一个不相关的问题。而这个问题甚至不需要DDL。
如果我强制使用覆盖索引查找,它估计使用该索引的子树成本为 0.04。
因此,服务器会选择使用以下计划也就不足为奇了:
服务器A:
| Plan | Cost | I/O Cost | CPU Cost |
|--------------------------------------------|-----------|-------------|-----------|
| clustered index scan (optimizer preferred) | 0.0106035 | 116.574 | 5.01949 | Actually run extraordinarily terrible (147k logical reads, 27 seconds)
| covering index seek (force hint) | 0.048894 | 0.0305324 | 0.0183616 | actually runs …
Run Code Online (Sandbox Code Playgroud) 我管理的几台服务器在 system_health XE 会话中记录了很多事件。
error_code 5023 应该是(系统错误代码):
ERROR_INVALID_STATE 5023 (0x139F)
The group or resource is not in the correct state to perform the requested operation.
Run Code Online (Sandbox Code Playgroud)
我在事件安全日志和 SQL Server 日志中都没有登录失败事件。
给定一些带有主键的表,例如:
CREATE TABLE Customers (
CustomerID int NOT NULL PRIMARY KEY,
FirstName nvarchar(50),
LastName nvarchar(50),
Address nvarchar(200),
Email nvarchar(260)
--...
)
Run Code Online (Sandbox Code Playgroud)
我们有一个唯一的主键CustomerID
。
传统上,我可能需要一些额外的覆盖索引;例如通过CustomerID
或快速找到用户Email
:
CREATE INDEX IX_Customers_CustomerIDEmail ON Customers
(
CustomerID,
Email
)
Run Code Online (Sandbox Code Playgroud)
这些是我几十年来创建的索引类型。
索引本身的存在是为了避免表扫描;它是一个覆盖索引,以帮助提高性能(该索引不是强制执行唯一性的约束)。
今天我想起了一点信息——SQL Server 可以使用以下事实:
以帮助它优化其查询执行。事实上,来自SQL Server 索引设计指南:
如果数据是唯一的并且您希望强制执行唯一性,则在相同的列组合上创建唯一索引而不是非唯一索引可为查询优化器提供附加信息,从而可以生成更高效的执行计划。在这种情况下,建议创建唯一索引(最好通过创建 UNIQUE 约束)。
鉴于我的多列索引包含主键,这个复合索引实际上是唯一的。这不是我特别需要 SQL Server 在每次插入或更新期间强制执行的约束;但事实是这个非聚集索引是唯一的。
将此事实上的唯一索引标记为实际唯一索引是否有任何优势?
在客户上创建唯一索引 IX_Customers_CustomerIDEmail ( 顾客ID, 电子邮件 ) …
在高并发期间,我们遇到了返回无意义结果的查询的问题 - 结果违反了所发出查询的逻辑。需要一段时间才能重现该问题。我已经设法将可重现的问题归结为几个 T-SQL。
注意:有问题的实时系统部分由 5 个表、4 个触发器、2 个存储过程和 2 个视图组成。对于已发布的问题,我已将实际系统简化为更易于管理的系统。事情已经被削减,列被删除,存储过程被内联,视图变成了公共表表达式,列的值发生了变化。这是一个很长的说法,虽然下面的内容会重现错误,但可能更难以理解。您必须避免想知道为什么某些事物的结构是这样的。我在这里试图弄清楚为什么错误情况会在这个玩具模型中重复发生。
/*
The idea in this system is that people are able to take days off.
We create a table to hold these *"allocations"*,
and declare sample data that only **1** production operator
is allowed to take time off:
*/
IF OBJECT_ID('Allocations') IS NOT NULL DROP TABLE Allocations
CREATE TABLE [dbo].[Allocations](
JobName varchar(50) PRIMARY KEY NOT NULL,
Available int NOT NULL
)
--Sample allocation; there is 1 avaialable slot …
Run Code Online (Sandbox Code Playgroud) 我在生产服务器上遇到了奇怪的事情。客户端(都在本地 LAN 上)在查询时出现超时错误,本应完全没有问题。
我花了一个下午在 SQL Server Profiler 中实时观察跟踪,而毫无意义的绝对缩影是批处理:
SELECT GETDATE() As ServerDate
Run Code Online (Sandbox Code Playgroud)
探查器显示数字的地方:
在这个数据库引擎中可能会发生什么,完全良性查询需要太长时间?
因为即使服务器是忙,一个查询,需要:
不应该需要 17 秒才能完成。
唯一的出路是想办法弄清楚这duration
意味着什么。
持续时间是什么意思?是吗:
或者是:
或者是: …
我正在尝试解决 SQL Server 2008 R2 的问题,但我正在抓紧稻草。
鉴于数据位于 B 树的叶节点中,并且也存在于索引中,有人可以在单个UPDATE
语句中读取多个值吗?
想象一个进程更新一行:
--Change status from Pending -> Waiting
BEGIN TRANSACTION
UPDATE Transactions SET Status = 'Waiting'
WHERE TransactionID = 12345
COMMIT TRANSACTION
Run Code Online (Sandbox Code Playgroud)
是否有可能在此期间BEGIN TRANS; UPDATE; COMMIT
另一个进程可以同时读取新旧值?
我想知道这一点,因为更新不会只在一个地方改变一个值。该值将存在于多个地方:
如果更新开始,它必须更新所有这些位置的值。如果另一个进程使用索引执行计划来查找值会发生什么:
在那一刻,如果发出一个查询来查看聚集索引中的值,它将找到Waiting。
但是如果一个查询使用IX_Transactions_4
它会发现一个值 …
SQL Server 使用 34 GB RAM。但当查询内存消耗报告、缓冲池大小和即席查询大小时,加起来只有 2 GB 左右。另外 32 GB RAM 有何用途?
\n先发制人:“您应该限制 SQL Server 可以使用的 RAM 量。” 可以说它的上限是x
。这只是将我的问题改为“其他x
GB 的 RAM 在做什么?”
我有一个消耗 32 GB RAM 的 SQL Server 实例:
\n\n这不是 32 GB虚拟内存;它实际上消耗了 32 GB物理内存(在 RAM 芯片上)——称为“工作集”。
\n而且它不像是与其他进程共享的。本质上所有这些都是 SQL Sever 私有的:
\n\n它用那么多内存做什么?
\n因此,我们按数据库查询内存使用情况 - …