Rebus SqlServerTransport,来自 SQL 服务器的 "MissingIndex" 似乎不正确,或者某些东西没有按预期工作
Rebus SqlServerTransport, "MissingIndex" from SQL Server seems incorrect, or something isn't working as intended
SQL 服务器报告 Rebus
和 SQLServerTransport
使用的消息 table 需要为其创建不同的索引。我觉得当前的索引设置是正确的,但是 CTE 的使用、删除和输出导致 SQL 服务器执行某些操作。
是 SQL 服务器在索引上出错还是 CTE 在这里做了一些意外的事情?
SQL 服务器正在请求和索引
CREATE INDEX IX_<NewNameHere>
ON [MessageQueues].[dbo].[Messages] ([id])
INCLUDE ([recipient], [priority])
目前聚集索引在哪里
PRIMARY KEY CLUSTERED
(
[recipient] ASC,
[priority] ASC,
[id] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
这是针对此数据库的唯一查询 运行。
exec sp_executesql N'SET NOCOUNT ON
;WITH TopCTE AS
(
SELECT TOP 1
[id], [headers], [body]
FROM
[Messages] M WITH (ROWLOCK, READPAST)
WHERE
M.[recipient] = @recipient
AND M.[visible] < getdate()
AND M.[expiration] > getdate()
ORDER BY
[priority] ASC, [id] ASC
)
DELETE FROM TopCTE
OUTPUT deleted.[id] as [id],
deleted.[headers] as [headers],
deleted.[body] as [body]
', N'@recipient nvarchar(200)', @recipient=N'Location'
更新:
我在导致所需索引的查询上错了。 Rebus 定期发送消息 PerformExpiredMessagesCleanupCycle
运行此查询
```
从 [{_tableName}] 中删除
其中 [id] 在 (
SELECT TOP 1 [id] 来自 [{_tableName}] WITH (ROWLOCK, REDPAST)
WHERE [收件人] = @recipient
AND [过期时间] < getdate()
)
```
是所需索引的来源。
"SQL Server is reporting that (...) needing a different index" 是什么意思?你在哪里看到的?
我不是 SQL 服务器方面的专家....但是当我通过使用 Rebus 自动创建的索引在 table 上执行查询获得实际查询计划时,我得到这个计划:
现在,由于我不是专家,所以当我看这些东西时,我可能会遗漏很多东西。但我知道要注意的是 "index scan",而 "index seek" 很好,因为这意味着 SQL 服务器实际上正在使用索引。
为了检查 SQL 服务器建议的索引是否会产生影响,我进行了一项测试,测量端点接收 10000 条消息所花费的时间。
在第一轮中,测试以通常的配置运行 - 即 没有 SQL 服务器建议的索引:
10000 messages received in 12,5 s - that's 801,5 msg/s
第二轮,我添加SQL服务器建议的索引:
10000 messages received in 13,6 s - that's 736,2 msg/s
在第三轮中,我添加了 SQL 服务器建议的索引,并删除了 Rebus 自己创建的索引:
10000 messages received in 13,8 s - that's 722,6 msg/s
这里是用一个简洁的小 ASCII 码总结的结果 table:
+---------------+-----------+----------------------+
| Current index | New index | Approx. receive rate |
+---------------+-----------+----------------------+
| Yes | No | 800 msg/s |
| Yes | Yes | 735 msg/s |
| No | Yes | 720 msg/s |
+---------------+-----------+----------------------+
据此-当然,不是很彻底,但可能足够指示-测试,如果使用SQL服务器建议的索引,似乎不会提高接收率。
Rebus 为每个队列定期清理以删除所有过期消息。它做到了这一点
command.CommandText =$@"
DELETE FROM [{_tableName}]
WHERE [id] IN (
AND [expiration] < getdate()
)
";
如果查询是这样的
command.CommandText =$@"
;with TopCTE as (
SELECT TOP 1 [id] FROM [{_tableName}] WITH (ROWLOCK, READPAST)
WHERE [recipient] = @recipient
AND [expiration] < getdate()
)
DELETE FROM TopCTE
";
那么就不需要进行导致 ID
列被扫描的二次查找。
SQL 服务器报告 Rebus
和 SQLServerTransport
使用的消息 table 需要为其创建不同的索引。我觉得当前的索引设置是正确的,但是 CTE 的使用、删除和输出导致 SQL 服务器执行某些操作。
是 SQL 服务器在索引上出错还是 CTE 在这里做了一些意外的事情?
SQL 服务器正在请求和索引
CREATE INDEX IX_<NewNameHere>
ON [MessageQueues].[dbo].[Messages] ([id])
INCLUDE ([recipient], [priority])
目前聚集索引在哪里
PRIMARY KEY CLUSTERED
(
[recipient] ASC,
[priority] ASC,
[id] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
这是针对此数据库的唯一查询 运行。
exec sp_executesql N'SET NOCOUNT ON
;WITH TopCTE AS
(
SELECT TOP 1
[id], [headers], [body]
FROM
[Messages] M WITH (ROWLOCK, READPAST)
WHERE
M.[recipient] = @recipient
AND M.[visible] < getdate()
AND M.[expiration] > getdate()
ORDER BY
[priority] ASC, [id] ASC
)
DELETE FROM TopCTE
OUTPUT deleted.[id] as [id],
deleted.[headers] as [headers],
deleted.[body] as [body]
', N'@recipient nvarchar(200)', @recipient=N'Location'
更新:
我在导致所需索引的查询上错了。 Rebus 定期发送消息 PerformExpiredMessagesCleanupCycle
运行此查询
``` 从 [{_tableName}] 中删除 其中 [id] 在 ( SELECT TOP 1 [id] 来自 [{_tableName}] WITH (ROWLOCK, REDPAST) WHERE [收件人] = @recipient AND [过期时间] < getdate() )
```
是所需索引的来源。
"SQL Server is reporting that (...) needing a different index" 是什么意思?你在哪里看到的?
我不是 SQL 服务器方面的专家....但是当我通过使用 Rebus 自动创建的索引在 table 上执行查询获得实际查询计划时,我得到这个计划:
现在,由于我不是专家,所以当我看这些东西时,我可能会遗漏很多东西。但我知道要注意的是 "index scan",而 "index seek" 很好,因为这意味着 SQL 服务器实际上正在使用索引。
为了检查 SQL 服务器建议的索引是否会产生影响,我进行了一项测试,测量端点接收 10000 条消息所花费的时间。
在第一轮中,测试以通常的配置运行 - 即 没有 SQL 服务器建议的索引:
10000 messages received in 12,5 s - that's 801,5 msg/s
第二轮,我添加SQL服务器建议的索引:
10000 messages received in 13,6 s - that's 736,2 msg/s
在第三轮中,我添加了 SQL 服务器建议的索引,并删除了 Rebus 自己创建的索引:
10000 messages received in 13,8 s - that's 722,6 msg/s
这里是用一个简洁的小 ASCII 码总结的结果 table:
+---------------+-----------+----------------------+
| Current index | New index | Approx. receive rate |
+---------------+-----------+----------------------+
| Yes | No | 800 msg/s |
| Yes | Yes | 735 msg/s |
| No | Yes | 720 msg/s |
+---------------+-----------+----------------------+
据此-当然,不是很彻底,但可能足够指示-测试,如果使用SQL服务器建议的索引,似乎不会提高接收率。
Rebus 为每个队列定期清理以删除所有过期消息。它做到了这一点
command.CommandText =$@"
DELETE FROM [{_tableName}]
WHERE [id] IN (
AND [expiration] < getdate()
)
";
如果查询是这样的
command.CommandText =$@"
;with TopCTE as (
SELECT TOP 1 [id] FROM [{_tableName}] WITH (ROWLOCK, READPAST)
WHERE [recipient] = @recipient
AND [expiration] < getdate()
)
DELETE FROM TopCTE
";
那么就不需要进行导致 ID
列被扫描的二次查找。