我继承了一个多年前由软件供应商安装的应用程序(以及相关的 MS SQL 数据库)。目前我们没有任何类型的供应商支持。除了使用应用程序之外,我们还独立于应用程序访问数据库,通常直接更新数据库并查询数据以进行报告。
为了提高性能,我删除了一些不必要的索引并创建了其他索引。当应用程序执行某些任务时,这会导致应用程序出现错误。应用程序不会显示任何类型的错误消息,并且似乎执行正常,但应用程序未按预期更新数据库。我无法访问源代码。
我的理论是,应用程序在其查询之一的 with(index) 语句中显式指定已删除的索引。这将导致服务器返回错误而不是完成查询,并且如果应用程序抑制错误,用户将不会意识到某些表已更新而其他表未更新。还有哪些其他想法可能导致这种行为?
假设我的理论是正确的,我仍然相信索引实际上是不必要的,并且应用程序不应该指定索引。也许解决方法是创建一个具有相同名称的新索引,但列数尽可能少。有没有办法创建没有列的索引?创建与聚集索引具有相同列的非聚集索引是否是最有效的?在这种情况下,优化器会做什么 - 它是否仍然制定计划包含这些仅引用聚集索引的“坏”索引,或者它会知道忽略 with(index) 请求吗?
我确实运行了跟踪来查看应用程序正在运行哪些查询。我收到了一堆 RPC 调用,例如“exec sp_cursorfetch”和“exec sp_cursorexecute”(我不明白),而不是实际的 SQL。也许我会在一个单独的问题中询问这些问题,但如果你知道我如何将这些语句解释或解码为常规 SQL,那么这至少可以让我证实我的理论。
要验证有关应用程序代码隐藏错误的理论,请运行 XE 跟踪来捕获error_reported事件。
RPCsp_cursor*调用是系统游标 procs,通常由服务器端游标的客户端驱动程序调用。在同一连接上应该有一个先前sp_prepare或类似的 RPC 调用来传递 SQL 语句并返回句柄以供后续使用。
索引更改不会改变编写良好的应用程序的行为,但对于那些做出不良假设的应用程序来说可能会产生意想不到的副作用。例如,考虑ORDER BY下面的查询中的缺失可能会返回任意行。返回的行将根据查询计划中使用的索引而有所不同。
SELECT TOP (1) Column1 FROM SomeTable WHERE Column2 = @SomeValue;
Run Code Online (Sandbox Code Playgroud)
如果可能的话,我建议您在测试环境中执行以下操作:
| 归档时间: |
|
| 查看次数: |
340 次 |
| 最近记录: |