3

我最近一直在学习一些对我来说非常新的东西——全文索引。

似乎我可以针对两个单独的表对相同的参数运行两个单独的查询(使用 CONTAINSTABLE)获得几乎瞬时的答案(低于 10 毫秒)但是当我将两者结合在一起时,查询需要 1.3 秒 - 或 130 多次慢点!!

以下是查询(为本问题的目的而简化)。

查询一:

SELECT
    *
FROM
    dbo.FooBar FB
    INNER JOIN dbo.FooBalls FBS on FB.ID = FBS.ID
    LEFT JOIN CONTAINSTABLE(dbo.FooBar, (Col1, Col2, Col3), @query) FBCONT ON FB.ID = FBCONT.[KEY]
WHERE
    FBCONT.[KEY] IS NOT NULL

查询 2:

SELECT
    *
FROM
    dbo.FooBar FB
    INNER JOIN dbo.FooBalls FBS on FB.ID = FBS.ID
    LEFT JOIN CONTAINSTABLE(dbo.FooBalls, (Col1), @query) FBSCONT ON FBS.ID = FBSCONT.[KEY]
WHERE
    FBSCONT.[KEY] IS NOT NULL

查询组合:

SELECT
    *
FROM
    dbo.FooBar FB
    INNER JOIN dbo.FooBalls FBS on FB.ID = FBS.ID
    LEFT JOIN CONTAINSTABLE(dbo.FooBar, (Col1, Col2, Col3), @query) FBCONT ON FB.ID = FBCONT.[KEY]
    LEFT JOIN CONTAINSTABLE(dbo.FooBalls, (Col1), @query) FBSCONT ON FBS.ID = FBSCONT.[KEY]
WHERE
    (FBCONT.[KEY] IS NOT NULL OR FBSCONT.[KEY] IS NOT NULL)

也许我的研究遗漏了一些东西,但有人可以给我一个指标,说明为什么将两个子句放在一起会使性能降低 130 倍以上?

笔记:

  • 我已经检查了存在的相关索引 - 已通过单个查询的速度进行验证。
  • 该过程实际上涉及更多连接 - 但是它们与正在查询的表完全无关,并且在搜索超过 100,000 条记录的结果时,响应再次低于 10 毫秒。
  • 我尝试用单独的 CONTAINS 语句替换 CONTAINSTABLE - 正如我的研究所预期的那样,性能大幅下降。
  • 已经建立了一个目录,它只引用被查询的两个表中的四列
  • @query 参数目前设置为 NVARCHAR (50)。我读过使用 NVACHAR 更快,因为不需要隐式转换。
  • 我知道我可以分别对两个查询执行肮脏的 UNION ALL,但如果可能的话,我更愿意编写更好的查询,而不是一起破解它。此外,如果@query 值位于链接到一条记录的单独表的两列中,则 UNION ALL 会给我留下潜在的重复。

任何进一步的建议都将受到极大的欢迎。

4

1 回答 1

0

您的问题评论表明您通过重写查询的不相关部分(未在问题中显示)将性能提高到令人满意的水平。

如果它有效,这足够公平,但不能解释为什么当查询的其他不相关部分保持不变时,两个单独的查询和组合查询有如此显着差异。

没有看到查询计划和统计结果就很难自信地说;但是,仅基于对 SQL 查询的编写方式的推理,我可以想到两种可能性:

  1. 在这两个表被内部连接后,其中一列或两ID列(fromFooBarFooBalls)在行集中可能是非唯一的。因此,对结果集进行两次而不是一次连接CONTAINSTABLE可能会比单个连接“繁殖”更多的记录;较大的结果集需要更长的时间才能传递回客户端并显示。要对此进行测试:比较两个单独查询返回的行数,如果WHERE省略子句,则将这些与每个单独查询的行数进行比较。较大的行数通常表明查询经过的时间较长(所有其他条件都相同)。

  2. 每个单独的查询都使用左外连接编写,但结果集随后被限制为仅包含连接成功的行。这实际上是一个内连接:SQL Server 的查询计划器很可能会识别这个事实并选择一个执行计划,就好像已经指定了内连接一样。相反,组合查询需要其中一个连接(但不一定两者)都成功的行这是一个真正的左连接。执行计划可能对这些连接使用不同的、较慢的方法。 要对此进行测试:查看执行计划,并与请求内连接而不是左连接的单独查询的执行计划进行比较。

于 2015-09-17T22:32:53.683 回答