3

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

http://76.12.87.164/cpd/testperformance.cfm

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

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

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

谢谢

4

5 回答 5

2

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

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

因此,让我们看一下您正在搜索“关键字'会计'”的情况。根据您的结果页面,生成的 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.providerid是一个外键,cpd_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 就会越慢。因此,有时您需要整合索引,或者如果它们不能提供足够的性能优势,则完全忽略它们。需要一些判断。

于 2010-06-15T00:58:25.790 回答
1

这是真实的实时数据库数据吗?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 运算符进行模式匹配......

于 2010-06-15T00:58:41.780 回答
0

我会尝试将您的 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>
于 2010-06-15T18:50:02.110 回答
0

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

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

于 2010-06-15T01:12:27.660 回答
0

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

于 2010-06-15T00:59:52.900 回答