【发布时间】:2011-06-12 13:58:07
【问题描述】:
我们开发了一个带有搜索屏幕的系统,看起来有点像这样:
(来源:nsourceservices.com)
如您所见,有一些相当重要的搜索功能。您可以使用状态、渠道、语言、活动类型的任意组合,然后按名称等缩小范围。
然后,一旦您搜索并在底部弹出潜在客户,您就可以对标题进行排序。
查询使用 ROWNUM 执行分页方案,因此我们一次只返回大约 70 行。
问题
尽管我们只返回 70 行,但仍有大量 IO 和排序正在进行。这当然是有道理的。
这总是会导致磁盘队列出现一些小峰值。当我们达到 300 万个潜在客户时,它开始变得更加缓慢,而现在我们已经接近 5 个,磁盘队列有时会持续一两秒。
这实际上仍然可行,但是该系统还有另一个区域具有时间敏感的过程,为了简单起见,它是一个 Web 服务,需要非常快速地提供响应,否则会导致另一个超时结尾。磁盘队列峰值导致该部分陷入困境,从而导致下游超时。最终结果实际上是在我们基于 VoiceXML 的自动 IVR 中掉线,这对我们来说非常糟糕。
我们的尝试
我们已经尝试过:
- 将系统中的引线数量减少到最低限度的维护任务。
- 添加了明显的索引以提供帮助。
- 在分析器中运行索引调整向导并应用了它的大部分建议。其中一个会或多或少地在索引中复制整个表,因此我手动对其进行了调整,使其做得更少。
- 为服务器添加了更多 RAM。它有点低,但现在它总是有 8 gigs 空闲,并且 SQL 服务器配置为使用不超过 8 gigs,但它从不使用超过 2 或 3。我发现这很奇怪。为什么不只是将整个表放在 RAM 中?它只有 500 万个潜在客户,而且还有足够的空间。
- 覆盖查询执行计划。我可以看到,此时索引似乎大部分都在完成它们的工作——大约 90% 的工作发生在排序阶段。
- 考虑将 Leads 表分区到不同的物理驱动器,但我们没有资源,似乎没有必要这样做。
即将结束...
我的一部分感觉服务器应该能够处理这个问题。考虑到该服务器的强大功能,500 万条记录并不算多,这是一个不错的四核和 16 GB 内存。但是,我可以看到排序部分是如何导致数百万行被触摸而只返回少数。
那么在这种情况下你做了什么?我的直觉是我们也许应该削减一些功能,但如果有办法保持这一点完好无损,那将避免我与业务部门的战争。
提前致谢!
【问题讨论】:
-
您在搜索 GUID 吗?你的聚集索引是什么?您是否考虑过在服务器中使用 SSD?你在做通配符搜索吗?如果是这样,您可能需要向后和向前索引 varchars
-
@Matthew PK:没有 GUID。聚集索引只是主键——LeadID (int)。至于固态驱动器......好吧,把钱扔在它上面是我最后的选择。但它在我的脑海里。 :)
-
返回整个结果集并在客户端分页呢?作为用户,我宁愿提前多等 2 秒,也不愿每次页面都等待。
-
查询是内置在动态 SQl 中还是固定查询?可能是查询本身需要调整而不是索引。
-
@Matthew PK:嗯,我实际上并没有考虑到这一点。问题是整个结果集可能多达数百万条线索,而在 ASP.NET 中,我相信这必须直接进入视图状态,除非我完全改变方向并在客户端 实际上 这样做使用某种 jQuery,或者可能使用 Silverlight 之类的东西。它似乎行不通,但老实说,我还没有涉足这种发展。你认为这是一个合法的选择吗?
标签: asp.net database optimization orm query-optimization