【问题标题】:What is the best optimization technique for a wildcard search through 100,000 records in sql table通过 sql 表中的 100,000 条记录进行通配符搜索的最佳优化技术是什么
【发布时间】:2013-08-01 04:27:22
【问题描述】:

我正在开发一个 ASP.NET MVC 应用程序。此应用程序由 200 个用户使用。这些 用户不断(每 5 分钟)从 100,000 个项目的列表中搜索一个项目(这个列表将每月增加 1-2%)。这个包含 100,000 个项目的列表存储在 SQL Server 表中。

搜索是通配符搜索

例如:

Select itemCode, itemName, ItemDesc 
from tblItems
Where itemName like '%SearchWord%'

搜索需要非常快,因为主要业务依赖于搜索和选择项目。

我想知道如何获得最佳性能。搜索结果必须立即出现。

我尝试过的-

  1. 我尝试将全部 100,000 条记录预加载到内存缓存中,然后从内存缓存中读取。我试图避免每次搜索都调用 SQL Server。

    这需要很多时间。每次用户搜索项目时,我们都会从内存缓存中检索 100,000 条记录,然后进行搜索。这比直接 SQL 搜索花费的时间几乎多出 2-3 倍。

  2. 我尝试对 SQL Server 表进行直接搜索,但将结果限制为一次仅 50 条记录(使用前 50 条记录)

    这似乎没问题,但仍远未达到我们所寻求的性能

我想听听可能的解决方案和任何文章/代码的链接。

提前致谢

【问题讨论】:

  • 您能详细说明一下您的应用程序的架构吗?执行关键字搜索时,它是精确关键字词还是通配符/屈折词?作为一般规则,您应该将搜索的繁重工作留给数据库..
  • 这是全文目录搜索还是LIKE
  • 嗨,菲尔,这将是一个通配符搜索。
  • Alex,它不会是全文目录搜索。这类似于使用 Like '%SearchKey%'
  • 有几个解决方案:缓存(您尝试过的),对列进行索引(使插入速度变慢,但读取速度会更快)。缓存可能会导致数据库中的数据不是最新的,但如果处理得当,您可以将其保持关闭,这将防止对数据库的命中。索引是数据库读取性能的最佳选择,它会增加一些写入开销,因此您应该考虑到这一点。

标签: c# sql-server-2008 asp.net-mvc-4 optimization memcached


【解决方案1】:

运行 SQL Profiler 并执行调优配置文件。这将对要针对您的数据库执行的索引提出建议。

此外,类似以下的查询也值得一试。

SELECT  *
FROM    
( 
    SELECT    ROW_NUMBER() OVER ( ORDER BY ColumnA) AS RowNumber, itemCode, itemName, ItemDesc
    FROM      tblItems
    WHERE     itemName LIKE '%FooBar%'
) AS RowResults
WHERE   RowNumber >= 1 AND RowNumber < 50
ORDER BY RowNumber

编辑:更新查询以反映您的真实情况。

【讨论】:

    【解决方案2】:

    如何将不带前导通配符的搜索作为主要搜索......

    Where itemName like 'SearchWord%'
    

    然后有一个加载“更多结果”按钮

    Where itemName like '%SearchWord%'
    

    (或者从第一个结果集中排除结果)

    Where itemName not like 'SearchWord%' and itemName like '%SearchWord%'
    

    【讨论】:

      【解决方案3】:

      一个奇怪的替代方案可能有效,因为它取决于几个假设等。抱歉没有完全解释,但我使用 ipad 很难打字。 (是的,该解决方案已用于高交易量的商业系统)

      假设

      1. 您的查询受 cpu 约束而不是 IO
      2. itemName 不太长,可以容纳所有字母和数字
      3. 该搜索词总共包含足够多的选择性字符,而不仅仅是非常常见的字符
      4. 您的选择谓词受 %like% 约束

      基本思想是扩展您的查询以帮助优化器了解哪些行需要类似扫描。

      第 1 步。设置您的餐桌

      为每个字母/数字创建额外的 26 或 36 列。当我真正做到这一点时,它一直是一个单独的表,但是对于像 100k 这样的小卷,将它放在源表上应该没问题。让我们调用 colmns trig_a、trig_b 等。

      为每个插入/编辑/删除创建一个触发器,如果​​ trig_a 字段包含“a”,则将 1 或 0 放入,对所有 26/36 列执行此操作。执行此操作的触发器很复杂,但可能(至少使用 Oracle)。如果您遇到困难,我相信 SO'ers 可以创建它,或者我可以将其挖掘出来。

      此时,我们有一系列列来指示字段是否包含字母/数字等。

      第二步,帮你查询

      有了这些额外的信息,我们可以帮助优化者。将以下内容添加到您的查询中

      Select ... Where .... And
       ((trig_a > 0) or (searchword not like '%a%')) and
       ((trig_b > 0) or (searchword not like '%b%')) and
         ... Repeat for all columns monitored...
      

      如果优化器正常运行,它可以使用(希望)较低成本字段>0 谓词来减少评估的相似谓词。

      注释。

      1. 您可能需要强制优化器扫描 trig_?字段优先
      2. 索引对 trig_ 有帮助吗?字段,尤其是在源表中
      3. 我没有展示如何处理大小写,不要忘记处理这个
      4. 您可能会发现只需写几个字母即可。
      5. 此技术不会为每次使用 like 提供性能提升,因此它不是一种适用于任何使用 like 的通用技术。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-10
        • 1970-01-01
        • 2011-03-10
        • 2010-12-23
        • 1970-01-01
        • 2011-01-12
        • 2011-09-24
        • 2015-04-15
        相关资源
        最近更新 更多