【问题标题】:Improve SQL Server 2005 Query Performance提高 SQL Server 2005 查询性能
【发布时间】:2011-03-03 18:48:18
【问题描述】:

我有一个课程搜索引擎,当我尝试进行搜索时,显示搜索结果需要很长时间。你可以尝试在这里搜索

http://76.12.87.164/cpd/testperformance.cfm

在该页面上,您还可以看到数据库表和索引(如果有)。

我没有使用存储过程 - 查询是使用 Coldfusion 内联的。

我想我需要创建一些索引,但我不确定是哪种(集群、非集群)以及在哪些列上。

谢谢

【问题讨论】:

    标签: performance sql-server-2005 coldfusion indexing non-clustered-index


    【解决方案1】:

    您需要为出现在WHERE 子句中的列创建索引。该规则有几个例外:

    • 如果列只有一个或两个唯一值(这方面的典型示例是“性别” - 只有“男性”和“女性”是可能的值,这里没有指向索引的意义)。通常,您需要一个能够将需要处理的行限制为显着数量的索引(例如,仅将搜索空间减少 50% 的索引不值得,但将其减少 99 % )。
    • 如果您要搜索x LIKE '%something',那么索引就没有意义了。如果您认为索引为行指定特定的顺序,那么如果您正在搜索“%something”,则按x 排序是没有用的:您将不得不扫描所有行无论如何。

    让我们看一下您正在搜索“关键字'会计'”的情况。根据您的结果页面,生成的 SQL 是:

    SELECT
      *
    FROM (
      SELECT TOP 10
        ROW_NUMBER() OVER (ORDER BY sq.name) AS Row,
        sq.*
      FROM (
        SELECT
          c.*,
          p.providername,
          p.school,
          p.website,
          p.type
        FROM
          cpd_COURSES c, cpd_PROVIDERS p
        WHERE
          c.providerid = p.providerid AND
          c.activatedYN = 'Y' AND
          (
            c.name like '%accounting%' OR
            c.title like '%accounting%' OR
            c.keywords like '%accounting%'
          )
      ) sq
    ) AS temp
    WHERE
      Row >= 1 AND Row <= 10 
    

    在这种情况下,我假设cpd_COURSES.provideridcpd_PROVIDERS.providerid 的外键,在这种情况下您不需要索引,因为它已经有一个。

    此外,activatedYN 列是 T/F 列,并且(根据我上面关于将可能值限制为仅 50% 的规则)T/F 列也不应该被索引。

    最后,因为使用 x LIKE '%accounting%' 查询进行搜索,您也不需要名称、标题或关键字的索引 - 因为它永远不会被使用。

    所以在这种情况下您需要做的主要事情是确保cpd_COURSES.providerid 实际上 cpd_PROVIDERS.providerid 的外键。

    SQL Server 特定

    由于您使用的是 SQL Server,因此 Management Studio 提供了许多工具来帮助您决定需要在哪里放置索引。如果您使用“索引调整向导”,它实际上通常很擅长告诉您什么会给您带来良好的性能改进。您只需将您的查询剪切并粘贴到其中,它就会返回有关要添加的索引的建议。

    您仍然需要对添加的索引有点小心,因为您拥有的索引越多,INSERTs 和 UPDATEs 的速度就越慢。因此,有时您需要整合索引,或者如果它们不能提供足够的性能优势,则完全忽略它们。需要一些判断。

    【讨论】:

    • 好答案codeka。执行查询后的执行计划选项为索引提供建议。不是很聪明,但很好的起点。之后,您只需要耐心和时间来测试。
    【解决方案2】:

    这是真实的实时数据库数据吗? 52,000 条记录是一个很小的表,相对而言,SQL 2005 可以处理。

    我想知道为 SQL 服务器分配了多少 RAM,或者数据库位于哪种磁盘上。 IDE 甚至 SATA 硬盘无法提供与 15K RPM SAS 磁盘相同的性能,如果有足够的 RAM 来缓存大量经常访问的数据,那就太好了。

    说了这么多,我觉得“ (c.name like '%accounting%' OR c.title like '%accounting%' OR c.keywords like '%accounting%') ”子句有问题。

    您能否创建一个单独的 Course_Keywords 表,其中包含“courseid”和“keyword”两列(对于最长的关键字,varchar(24) 应该足够了吗?),在 courseid+keyword 上具有复合聚集索引

    然后,为了使 UI 更加友好,当人们在关键字输入字段中键入单词时,使用 AJAX 应用关键字验证和自动完成。这为您提供了幕后的好处,即拥有要搜索的准确关键字,无需使用 LIKE 运算符进行模式匹配......

    【讨论】:

    • 数据库位于廉价网络托管服务提供商的共享服务器/共享数据库上。我确信这是性能不佳的原因之一,但我希望至少在数据库中尽可能多地优化,因为这是免费的。
    【解决方案3】:

    使用 CF9?尝试使用 Solr 全文搜索而不是 %xxx%

    【讨论】:

    • 引用的页面表明他正在使用 CF8——我相信只有 Verity——这对我们来说从来都不是很好。
    • 如果有很大帮助,我可以将应用程序移至 CF9。 Solr 看起来很有趣。我会检查一下。希望整合起来不会太难。
    【解决方案4】:

    您需要在搜索的字段上创建索引。索引是按索引字段预先排序的记录的二级列表。

    想想老式的印刷黄页 - 如果您想按姓氏查找一个人,电话簿已经按这种方式排序 - 姓氏是聚集索引字段。如果您想查找名为 Jennifer 的人或电话号码为 867-5309 的人的电话号码,则必须搜索每个条目,并且需要很长时间。如果后面有一个索引,将所有电话号码或名字与电话簿中列出此人的页面一起按顺序列出,那会快很多。这些将是非聚集索引。

    【讨论】:

      【解决方案5】:

      我会尝试将您的 IN 语句更改为 EXISTS 查询,看看您是否在邮政编码查找中获得了更好的性能。我的经验是 IN 语句非常适合小型列表,但它们越大,EXISTS 的性能就越好,因为查询引擎将停止搜索它遇到的第一个实例的特定值。

      <CFIF zipcodes is not "">
          EXISTS (
              SELECT zipcode
              FROM cpd_CODES_ZIPCODES
              WHERE zipcode = p.zipcode
                  AND 3963 * (ACOS((SIN(#getzipcodeinfo.latitude#/57.2958) * SIN(latitude/57.2958)) +
                  (COS(#getzipcodeinfo.latitude#/57.2958) * COS(latitude/57.2958) *
                  COS(longitude/57.2958 - #getzipcodeinfo.longitude#/57.2958)))) <= #radius#
          )
      </CFIF>
      

      【讨论】:

      • 有趣。我会试试的。谢谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-08-01
      • 2019-03-20
      • 1970-01-01
      • 2015-02-18
      • 2023-03-18
      • 2022-01-09
      • 2014-03-23
      相关资源
      最近更新 更多