【问题标题】:Performance Issue with SQL Server query in a stored procedure存储过程中 SQL Server 查询的性能问题
【发布时间】:2018-05-31 18:46:16
【问题描述】:

我们正面临使用 Microsoft 企业库 3.0 从 .net 应用程序(Windows 服务)调用的存储过程的性能问题。 SQL Server 过程只是检查记录是否存在,如果不存在,则将记录插入到表中,否则只返回它们。

表格中有以下列:

create table AlarmLog 
(
    Id                   bigint
    MessageId            int
    MessageTime          datetime
    ControllerId         int
    InterfaceHardwareId  int
    IDType               int
    MapId                int
    RelatedEmployeeId    int
    RelatedCardId        int
);

Id 列是主键,上面有聚集索引。

作为业务规则,在插入记录时,我们需要确保组合 (MessageId, MessageTime, ControllerId, InterfaceHardwareId, IDType, MapId) 是唯一的。因此,我们放置了一个if exists 条件来检查组合是否已经存在。这种条件检查需要很长时间。

我们已尝试在 MessageId, MessageTime, ControllerId, InterfaceHardwareId, IDType, MapId 上添加非聚集索引。

在我们实验室的测试服务器上,大约有 30,00,000 条记录,即使条件到位,它也使用相同的 .net 服务以每分钟大约 400 多行的速度更快地插入。我们还尝试添加上述非聚集索引,并发现了一些明显的改进。

  • SQL Server 版本:SQL Server 2008 Standard
  • .NET Framework 4.0
  • 操作系统:Windows Server 2012 R2 标准版

在生产服务器上,大约有 300,000 多条记录,当我们从具备条件的 .net 应用程序(Windows 服务)逐行插入时,它每分钟仅插入 10 到 20 行。如果我们删除条件检查,那么插入的行数将达到每分钟 300 到 400+ 行。我们还尝试添加/删除上述非聚集索引,但没有发现任何明显的改进。

因此,我们暂时将其禁用。有趣的是,如果我们从 SQL Server Management Studio 运行存储过程以插入 1 条记录,则没有问题,我们还检查了实际执行计划,没有发生表扫描,存储过程也没有花费任何时间。

  • SQL Server 版本:SQL Server 2012 Standard SP3
  • .NET Framework 4.0
  • 操作系统:Windows Server 2012 R2 标准版

还尝试了其他性能调整活动重建、重组、更新统计信息、存储过程重新编译和参数嗅探。但是,似乎没有任何效果。

我们现在正在修复中。我们找不到任何替代方案。如果您能给我们一些建议/指导,将会很有帮助。

提前致谢。 乌贾尔

【问题讨论】:

  • 您忘记发布 SQL 语句了!没有查询,我们无法帮助您更快地进行查询!!! :) 表和索引的 DDL 也会帮助人们(不要列出列,提供CREATE 语句)。您还可以使用Paste the plan 提供实际执行计划
  • 如果您注意到生产代码和在 SSMS 中运行代码之间的性能差异,请查看sommarskog.se/query-plan-mysteries.html
  • 只是猜测,但可能会将唯一索引扩展到包括 Id,比如将其放在 (Id, MessageId, MessageTime, ControllerId, InterfaceHardwareId, IDType, MapId) 上可能值得一试。

标签: c# sql sql-server windows service


【解决方案1】:

添加一个唯一的约束而不是索引,如:

alter table AlarmLog add constraint uq_alarmlog_row unique (
  MessageId, MessageTime, ControllerId, 
  InterfaceHardwareId, IDType, MapId);

这将自动拒绝插入其值与此列组合完全匹配的新行。

这在性能方面也应该很快。无需调用过程来运行以前的select 并检查值是否存在。

只需运行一个简单的 SQL insert 即可解决问题。

【讨论】:

    【解决方案2】:

    您的生产环境可能接近带宽上限。由于当前正在其中运行的其他操作。正在处理的查询量使您的网络处于饱和状态。

    【讨论】:

      猜你喜欢
      • 2015-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-19
      • 2010-10-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多