优化 SQL 服务器的性能(大量等待任务)
Optimize Performance of SQL Server (a lot of waiting tasks)
我的数据库(Microsoft SQL 服务器)有问题,我们有很多用户使用我们的 API,这个 API 对我们的数据库进行了很多查询(这很正常,因为我们正在保存跟踪数据),我们正在为 API 使用负载均衡器,因此我们可以处理很多请求,但这给我们带来了问题,即早上一切正常,但当一天过去了,一切都变得非常缓慢,我查看了 activity 监视器(我不是 DBA,但团队没有监视器),我注意到当它变慢时等待任务增加,它总是大于 500(等待任务总是在 500-800 左右),因此我和我的经理谈过,他也不是技术人员,我们租了一台服务器,它只会 运行 数据库,这些是规格:
服务器规格:
- 128 内存,16 vcpus
但问题是一样的:
我查看了任务管理器,我注意到它甚至没有使用 100% 的 ram 或 cpu:
所以我希望专家可以推荐我做什么,因为我有硬件但它没有改进:(,提前致谢。
一些相关信息:
我们API用的是entity framework,听说用ADO.NET可以改善这个,是真的吗?
买一个azure SQL database tier Business-critical能解决我们的问题吗?
我们有SQL标准版
SQL 实例的属性:
我最近在 sql 服务器上看到了这个问题。请在 google 中搜索锁争用。您的数据库正在执行其工作,需要锁定以进行更新和插入。这是保持数据一致性所必需的。这是一致性和速度(=并发)之间的权衡。您需要查看应用程序层并尝试使您的事务更短。您还应该查看您的事务隔离级别。 Serialisable 并不总是需要的,并且在有很多锁定时是一个糟糕的选择。请搜索隔离级别以及如何选择隔离级别。
或许您应该与您的开发人员讨论 READ_COMMITTED_SNAPSHOT。如果您考虑 read_commited_snapshot,请查看 tempdb 使用情况,它会变得更高。
这说起来容易做起来难。我知道。如果您可以锁定,您的服务器将自动变得更快。这就是为什么您看不到 CPU 和 RAM 的大量使用。大部分时间都在等待。优化您的交易。
尝试在进行更改之前制定性能基准,以便您可以衡量更改是否具有积极影响。
简而言之:
- 检查隔离级别
- 检查您的交易
- 制定基准
- 想想READ_COMMITTED_SNAPSHOT
- 检查你的索引。
- 反馈会很好 :-)
我看到一个被阻止的交易。会有一个拦截器。如果您发现 head 阻塞程序是一个可以优化的查询,那将是一个开始的地方。这些是简单的单一查询事务还是一个事务中的多个查询?您是否正在做一些强制插入为单线程的事情,例如获取最后一个 ID 并为插入的新 ID 添加 1?它是否必须阻止其他交易?
例如,在繁忙的数据库中我们处理了新记录。我们进行了快速读取以获取要处理的最后一条记录。然后我们使用 where 子句只处理该记录之前的记录。否则,插入将被事务阻塞,直到处理完所有记录。
如果实施不当,Entity Framework 肯定会给数据库带来过度的负载,因此这是探索的一种途径。然而,它确实需要调查可能的罪魁祸首和具体的优化来消除它们。
我遇到的最常见的 EF 性能问题如下:
延迟加载命中。这是开发人员编写查询来加载实体的地方,然后遍历它们以访问相关实体,这会触发更多 SQL 调用来加载这些单独的实体。当 运行 超过实体集时,这会导致大量不必要的查询。在需要这些实体的地方急切加载相关实体 (Include
) 可以用 JOIN 替换这些额外的数据库命中。更好的是,通过 Select
利用投影可以产生更高效的查询。
加载太多数据,太频繁了。像放错地方的 ToList
调用这样简单的事情可能意味着锁定了比需要的多得多的行。这通常是由于开发人员面临他们想要根据计算值过滤数据(即方法结果等无法转换为 SQL)并且“修复”是添加 ToList
然后它神奇地工作。在幕后,EF 正在将大量未过滤的数据从服务器具体化到内存。此处的解决方法是重新散列过滤,以便更多过滤深入查询以减少被拉回的数据量。
像 Generic Repository 类 这样的东西对于这些类型的问题来说是一个致命的放弃,其中存储库 return 支持整个实体或实体集合,其中更有效的选项可用。
经典例子包括:
- 取回一个实体只是为了检查它是否为空。 (改用
.Any()
查询)
- 取回实体列表只是为了获得计数。 (改用
.Count()
查询)
- 获取只需要少量列的实体。 (改为使用
.Select()
的投影)
EF 可以构建非常高效的查询,但如果实施不当,它可能会导致数据库交互噩梦。不幸的是,如果不深入研究代码并 运行 与分析器一起使用,就无法列出有帮助的具体改进。
我的数据库(Microsoft SQL 服务器)有问题,我们有很多用户使用我们的 API,这个 API 对我们的数据库进行了很多查询(这很正常,因为我们正在保存跟踪数据),我们正在为 API 使用负载均衡器,因此我们可以处理很多请求,但这给我们带来了问题,即早上一切正常,但当一天过去了,一切都变得非常缓慢,我查看了 activity 监视器(我不是 DBA,但团队没有监视器),我注意到当它变慢时等待任务增加,它总是大于 500(等待任务总是在 500-800 左右),因此我和我的经理谈过,他也不是技术人员,我们租了一台服务器,它只会 运行 数据库,这些是规格:
服务器规格:
- 128 内存,16 vcpus
但问题是一样的:
我查看了任务管理器,我注意到它甚至没有使用 100% 的 ram 或 cpu:
所以我希望专家可以推荐我做什么,因为我有硬件但它没有改进:(,提前致谢。
一些相关信息:
我们API用的是entity framework,听说用ADO.NET可以改善这个,是真的吗?
买一个azure SQL database tier Business-critical能解决我们的问题吗?
我们有SQL标准版
SQL 实例的属性:
我最近在 sql 服务器上看到了这个问题。请在 google 中搜索锁争用。您的数据库正在执行其工作,需要锁定以进行更新和插入。这是保持数据一致性所必需的。这是一致性和速度(=并发)之间的权衡。您需要查看应用程序层并尝试使您的事务更短。您还应该查看您的事务隔离级别。 Serialisable 并不总是需要的,并且在有很多锁定时是一个糟糕的选择。请搜索隔离级别以及如何选择隔离级别。 或许您应该与您的开发人员讨论 READ_COMMITTED_SNAPSHOT。如果您考虑 read_commited_snapshot,请查看 tempdb 使用情况,它会变得更高。 这说起来容易做起来难。我知道。如果您可以锁定,您的服务器将自动变得更快。这就是为什么您看不到 CPU 和 RAM 的大量使用。大部分时间都在等待。优化您的交易。
尝试在进行更改之前制定性能基准,以便您可以衡量更改是否具有积极影响。
简而言之:
- 检查隔离级别
- 检查您的交易
- 制定基准
- 想想READ_COMMITTED_SNAPSHOT
- 检查你的索引。
- 反馈会很好 :-)
我看到一个被阻止的交易。会有一个拦截器。如果您发现 head 阻塞程序是一个可以优化的查询,那将是一个开始的地方。这些是简单的单一查询事务还是一个事务中的多个查询?您是否正在做一些强制插入为单线程的事情,例如获取最后一个 ID 并为插入的新 ID 添加 1?它是否必须阻止其他交易?
例如,在繁忙的数据库中我们处理了新记录。我们进行了快速读取以获取要处理的最后一条记录。然后我们使用 where 子句只处理该记录之前的记录。否则,插入将被事务阻塞,直到处理完所有记录。
如果实施不当,Entity Framework 肯定会给数据库带来过度的负载,因此这是探索的一种途径。然而,它确实需要调查可能的罪魁祸首和具体的优化来消除它们。
我遇到的最常见的 EF 性能问题如下:
延迟加载命中。这是开发人员编写查询来加载实体的地方,然后遍历它们以访问相关实体,这会触发更多 SQL 调用来加载这些单独的实体。当 运行 超过实体集时,这会导致大量不必要的查询。在需要这些实体的地方急切加载相关实体 (
Include
) 可以用 JOIN 替换这些额外的数据库命中。更好的是,通过Select
利用投影可以产生更高效的查询。加载太多数据,太频繁了。像放错地方的
ToList
调用这样简单的事情可能意味着锁定了比需要的多得多的行。这通常是由于开发人员面临他们想要根据计算值过滤数据(即方法结果等无法转换为 SQL)并且“修复”是添加ToList
然后它神奇地工作。在幕后,EF 正在将大量未过滤的数据从服务器具体化到内存。此处的解决方法是重新散列过滤,以便更多过滤深入查询以减少被拉回的数据量。
像 Generic Repository 类 这样的东西对于这些类型的问题来说是一个致命的放弃,其中存储库 return 支持整个实体或实体集合,其中更有效的选项可用。
经典例子包括:
- 取回一个实体只是为了检查它是否为空。 (改用
.Any()
查询) - 取回实体列表只是为了获得计数。 (改用
.Count()
查询) - 获取只需要少量列的实体。 (改为使用
.Select()
的投影)
EF 可以构建非常高效的查询,但如果实施不当,它可能会导致数据库交互噩梦。不幸的是,如果不深入研究代码并 运行 与分析器一起使用,就无法列出有帮助的具体改进。