我们正忙于对我们在 .NET 4.0 中开发并在后台运行 SQL Server 2008 R2 的 OLTP 系统进行负载测试。系统使用 SQL Server Service Broker 队列,它们的性能非常好,但我们在处理时遇到了一个特殊的趋势。
SQL Server 以极快的速度处理请求 1 分钟,然后增加约 20 秒的磁盘写入活动。下图说明了这个问题。

Yellow = Transactions per second
Blue = Total CPU usage
Red = Sqlsrv Disk Write Bytes/s
Green = Sqlsrv Disk Read Bytes/s
Run Code Online (Sandbox Code Playgroud)
在故障排除期间,我们尝试了以下方法,但模式没有任何重大变化:
似乎 SQL Server 可能正在建立其缓存并以特定的时间间隔将其写入磁盘,但我无法在网上找到任何支持该理论的内容。
接下来,我计划将解决方案转移到我们的专用测试环境中,看看我是否可以复制该问题。在此期间的任何帮助将不胜感激。
更新 1 根据要求,附上一张图表,其中包括Checkpoint Pages/Sec、Page Life Expectancy和一些磁盘延迟计数器。

看起来好像检查点(浅蓝线)是我们观察到的性能下降(黄线)的原因。^
磁盘延迟在处理过程中保持相对一致,页面预期寿命似乎没有任何明显影响。我们还调整了 SQL Server 可用的 ram 量,这也没有太大影响。将恢复模型从 …
我想跨连接表的列进行搜索。以下查询的最佳索引配置是什么?
Table A
------------
Id
ValueA
-- Table A has many more columns
Table B
------------
Id
AId
ValueB
-- Table B has many more columns
Run Code Online (Sandbox Code Playgroud)
此刻,我对主键和非聚集索引(不包括任何列)列的聚簇索引AId,ValueA和ValueB。
SELECT *
FROM TableA a
INNER JOIN TableB b ON a.Id = b.AId
WHERE
a.ValueA LIKE 'SearchTerm%' OR
b.ValueB LIKE 'SearchTerm%'
Run Code Online (Sandbox Code Playgroud)
更新 表 A 可能会遇到数百万个,而表 B 将只有数万个条目。
在现实世界中,表 A 将是一个交易列表,其中的值是某种交易引用。表 B 将是一个用户列表,其中的值可以是任何名称或任何其他描述性信息。
目前我们使用的是一个 ORM,它本质上会做一个SELECT *. 当然,这可以改变,但会对应用程序产生相当大的影响。
我们实现了一个 Google 风格的搜索,其中在前端触发去抖动后运行 SQL 查询。(我们知道 SQL 可能是错误的技术,但我在这里陷入了启动混乱。)查询:
SELECT
TOP(50) [Name], [Surname]
FROM
[dbo].[Clients]
WHERE
[Name] LIKE @SearchTerm + '%' OR
[Surname] LIKE @SearchTerm + '%'
Run Code Online (Sandbox Code Playgroud)
这是一个相当大的表,所以我在两列上添加了两个非聚集索引以帮助加快速度:
CREATE NONCLUSTERED INDEX [IX_Patients_Name] ON [dbo].[Clients]
(
[Name] ASC
)
INCLUDE([Surname]);
CREATE NONCLUSTERED INDEX [IX_Patients_Surname] ON [dbo].[Clients]
(
[Surname] ASC
)
INCLUDE([Name]);
Run Code Online (Sandbox Code Playgroud)
我的想法是 SQL 会在两列上进行索引查找,但查询优化器似乎决定使用索引扫描。
对于这个简单的用例,这可能不是一个真正的问题,但我们有更复杂的版本,具有多个连接等。
有什么方法可以优化此查询以使用搜索吗?