【问题标题】:How can I prevent two applications clashing, because they use one database?如何防止两个应用程序发生冲突,因为它们使用一个数据库?
【发布时间】:2015-08-08 08:46:06
【问题描述】:

情况

有两种应用:

  • Windows 服务
    • 处理队列消息
    • 执行大量数据库 I/O (SELECT/UPDATE/INSERT)
  • ASP.NET 应用程序
    • 主要使用数据库进行 SELECT 查询

这两个应用程序都使用一个(镜像)MSSQL 数据库 (SQL Server 2014)。我们使用 NHibernate ORM 查询数据。应用程序和数据库服务器都有自己的专用服务器。

问题

数据库中有数百万条记录,因此只有有足够的可用索引才能进行查询。 Windows 服务主要使用聚集索引进行查询,但有很多非聚集索引用于查询 Web 应用程序中的其他字段。 Windows 服务应该尽可能快。

  • 这些非聚集索引使更新和插入查询变慢。
  • Web 应用程序的使用对服务性能有很大影响。

到目前为止我们的解决方案

  • 向上扩展服务器
  • 存档数据
  • 改进索引

问题

除了我们目前的努力之外,还有其他解决方案吗?我们不想添加额外的服务器,我们想使用新的架构或软件来解决这个问题。在理想情况下,使用 Web 应用程序根本不会影响 Windows 服务的性能。

【问题讨论】:

  • 您的问题是 asp.net 查询阻塞了服务还是其他问题?查看计划缓存以获取最昂贵的查询和等待统计信息可能是个好主意。
  • 我的瓶颈是硬盘 io(数据库)。如果有办法不使用 Web 应用程序中的数据库,同时仍然拥有最新数据(不超过几分钟),我会喜欢的。
  • 如果实际的磁盘 I/O 是只读查询的问题,asp.net 查询是否从磁盘读取所有内容?更多内存是否有助于将所有内容保存在缓存(缓冲池)中?
  • 如果问题是内存不足,Page Life Expectancy 可能会显示它,例如使用:blog.sqlauthority.com/2010/12/13/…
  • 如果您没有这样做,那么从计划缓存中查看具有大多数逻辑读取的查询也可能会有所帮助。有时,如果在搜索条件中存在 varchar 与 nvarchar 问题或使用非最佳索引/计划时,实际可以读取多少内容会令人惊讶。

标签: .net sql-server performance nhibernate architecture


【解决方案1】:

不是一个理想的世界。桌子上的任何活动都会影响其他活动。

如您所知,索引会减慢插入、更新和删除的速度。

索引维护会有所帮助(碎片整理)

填充系数小于 100 会有所帮助(例如 50)

尝试按照PK的顺序执行插入
如果不是尽可能多的索引顺序的PK

尽可能设置基本更新、插入和删除
获得一个写锁和 1000 次插入比一次获得一个更有效

Web 应用程序的主要影响是需要锁定。
你有选择 .... with (nolock) 的选项吗?
with (nolock) 是脏读,所以请谨慎使用。

【讨论】:

  • 我会做一些关于脏读(nolock)的研究,看看它是否对我的情况有帮助,谢谢。
【解决方案2】:

除了 Blam 的建议之外,您可能还想研究一下 ASP.NET 应用程序的缓存读取,可能使用 ASP.NET 的缓存类:https://msdn.microsoft.com/en-us/library/system.web.caching.cache%28v=vs.110%29.aspx - 请参阅 https://msdn.microsoft.com/en-us/library/vstudio/ff477235%28v=vs.100%29.aspx 以及实现示例。

如果您可以容忍脏读(可能会也可能不会 - 应用程序用户可以看到部分更新的数据吗?),您可以将其与 SELECT ... WITH(NOLOCK) 结合使用。

基本想法是,您的数据库只会每 5 分钟左右(但对于更大的读取)而不是实时受到 WebApplication 的访问。这里的问题是每 5 分钟需要缓存多少数据。如果您可以将用户使用的大部分数据缓存在合理大小的缓存中,那就太好了。您可以在这里采取一些策略:

  • 仅缓存不经常更改的数据,并不太频繁地更新该缓存
  • 仅缓存与最近更新的对象/实体相关的数据
  • 只缓存网站经常请求的数据

所有这些都需要对您的 ASP 应用程序何时以及如何访问数据库进行一些分析。

您也可以将其与轮询模式结合以进行进一步改进,即当服务更新数据库中的实体时,它还会在您的 ASP.NET 应用程序正在轮询的另一个表中创建一条记录以保持缓存最多日期。轮询表将包含一个主密钥(或一组密钥)来访问实体,因此您的 ASP 缓存更新程序只能请求那些过期的实体。

【讨论】:

  • 作为一个警告,nolock 也可能(很少)导致您读取同一行两次或完全错过一行 - 如果问题不是阻塞,则 nolock 可能无济于事
  • 他几乎肯定遇到了阻塞问题,因为他有一个经常写入表格的服务和一个经常读取表格的网站。但是是的,应该谨慎使用 NOLOCK。
  • 这也是我的第一个猜测,还应该检查阻塞查询的索引使用/查询计划——这可能比尝试解决它更简单、更便宜。
  • 今天晚些时候我会更彻底地调查您的答案,但我认为缓存不会有太大帮助。许多查询并不经常执行(参数差异很大),但它们确实会对数据库产生很大的影响。如果大多数查询具有不同的参数,我认为缓存不会有太大帮助?
  • @annemartijn 在问题陈述中“Web 应用程序的使用对服务性能有很大影响”。除了阻塞问题,您如何解释这一点?
【解决方案3】:

您没有说您使用的是什么版本的 SQL Server,也没有描述您的硬盘方案(共享存储、本地存储等),但您确实说硬盘是瓶颈(不是内存,对吗?) ,但没有说是由于写入还是写入+读取。但是,由于您要求只落后几分钟,并且您不想引入报告服务器 - 如果您使用的是 SQL 2012,则可以将 AlwaysOn 与异步副本一起使用,只需确保辅助副本位于不同的磁盘集比主数据库。通过分离辅助数据库,读取不会与写入发生冲突,同时仍然比主数据库慢几秒。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-23
    • 1970-01-01
    • 2019-05-07
    • 1970-01-01
    • 1970-01-01
    • 2021-01-12
    相关资源
    最近更新 更多