【问题标题】:Optimize Performance of SQL Server (a lot of waiting tasks)优化 SQL Server 的性能(大量等待任务)
【发布时间】:2020-11-10 17:40:21
【问题描述】:

我的数据库(Microsoft SQL Server)有问题,我们有很多用户在使用我们的 API,并且这个 API 对我们的数据库进行了很多查询(这是正常的,因为我们正在保存跟踪数据),我们是为我们的 API 使用负载均衡器,这样我们就可以处理很多请求,但这给我们带来了问题,那就是早上一切正常,但是当一天过去的时候,一切都变得非常缓慢,我查看了活动监视器(我不是一个 DBA 但团队没有)我注意到当它变慢时是等待任务增加时,它总是大于 500(等待任务总是在 500-800 左右),因此我谈到了我的经理也不是技术人员,我们租了一台只能运行数据库的服务器,规格如下:

服务器规格:

  • 128 内存,16 虚拟处理器

但问题是一样的:

我查看了任务管理器,发现它甚至没有使用 100% 的 ram 或 cpu:

所以我希望专家可以推荐我该怎么做,因为我有硬件并且它没有改进:(,提前致谢。

一些相关信息:

  • 我们的API是用实体框架的,听说用ADO.NET可以改善这个,是真的吗?

  • 购买 Azure SQL 数据库层关键业务可以解决我们的问题吗?

  • 我们有 de SQL 标准版

  • SQL INSTANCE 的属性:

【问题讨论】:

    标签: sql-server entity-framework ado.net load-balancing database-administration


    【解决方案1】:

    我最近在 sql server 上看到了这个问题。请在 google 中搜索 lock contention。您的数据库正在完成其工作,需要锁定才能进行更新和插入。这是保持数据一致性所必需的。这是一致性和速度(=并发)之间的权衡。您需要查看应用程序层并尝试使您的事务更短。您还应该查看您的事务隔离级别。 Serialisable 并不总是需要,当有很多锁定时,它是一个糟糕的选择。请搜索隔离级别以及如何选择一个。 也许您应该与您的开发人员讨论 READ_COMMITTED_SNAPSHOT。如果您考虑 read_commited_snapshot,请查看 tempdb 使用情况,它会变得更高。 这说起来容易做起来难。我知道。如果您可以关闭锁定,您的服务器将自动更快。这就是为什么您看不到 CPU 和 RAM 的大量使用。它大部分时间都在等待。优化您的交易。

    尝试在进行更改之前制定性能基准,以便您可以衡量更改是否具有积极影响。

    简而言之:

    • 检查隔离级别
    • 检查您的交易
    • 制作基线
    • 想想 READ_COMMITTED_SNAPSHOT
    • 检查您的索引。
    • 反馈会很好:-)

    【讨论】:

    • 这里有一个有趣的链接,您可以查看:sqlskills.com/help/waits/lck_m_u
    • 非常有教育意义的答案和优雅,我会看看,谢谢。
    • 非常感谢,我们已经使用了 READ_COMMITED_SNAPSHOT 范围,我们的等待任务减少到了 10-20 个。我们知道权衡,但对我们来说,要求是速度比一致性更重要。非常感谢。
    【解决方案2】:

    如果实施不佳,实体框架肯定会给数据库带来过多的负载,因此这是一种探索途径。然而,它确实需要调查可能的罪魁祸首以及消除它们的具体优化。

    我遇到的最常见的 EF 性能问题如下:

    1. 延迟加载命中。这是开发人员编写查询以加载实体的地方,然后遍历它们以访问相关实体,从而触发更多 SQL 调用以加载这些单独的实体。当在实体集上运行时,这会导致大量不必要的查询。急切加载需要这些实体的相关实体 (Include) 可以用 JOIN 替换这些额外的数据库命中。更好的是,利用Select 的投影可以产生更高效的查询。

    2. 加载太多数据,太频繁了。像错误的ToList 调用这样简单的事情可能意味着锁定的行数远远超过所需的行数。这通常是当开发人员面临他们想要过滤计算值数据的情况(即无法转换为 SQL 的方法结果等)并且“修复”是添加 ToList 然后它神奇地工作时引起的。在幕后,EF 正在将大量未经过滤的数据从服务器具体化到内存中。此处的解决方法是重新散列过滤,以便更多过滤下到查询,以减少被拉回的数据量。

    对于这些类型的问题,如 Generic Repository 类之类的东西是一个致命的问题,因为存储库会返回整个实体或实体集合,但有更有效的选项可用。

    经典例子包括:

    • 返回一个实体只是为了检查它是否为空。 (改用.Any() 查询)
    • 获取实体列表只是为了获得计数。 (改用.Count() 查询)
    • 获取仅需要少量列的实体。 (改用 .Select() 的投影)

    EF 可以构建非常高效的查询,但如果实施不当,可能会导致数据库交互噩梦。不幸的是,如果不深入研究代码并与分析器一起运行,就不可能列出有帮助的具体改进。

    【讨论】:

      【解决方案3】:

      我看到一个被阻止的交易。会有一个拦截器。如果您发现 head blocker 是一个可以优化的查询,那将是一个开始的地方。这些是简单的单一查询事务还是一个事务中的多个查询?您是否正在做一些强制插入单线程的事情,例如获取最后一个 id 并为插入的新 id 添加 1?它是否必须阻止其他交易?

      例如,在一个繁忙的数据库中,我们处理了新记录。我们快速读取以获取要处理的最后一条记录。然后我们使用 where 子句仅处理直到该记录的记录。否则,插入将被事务阻止,直到处理完所有记录。

      【讨论】:

        猜你喜欢
        • 2013-07-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多