我最近一直在学习一些新东西--FULLTEXT索引。
似乎我可以在两个单独的表上运行两个单独的查询(使用CONTAINSTABLE)对两个单独的表获得几乎即时的答案(子10ms)但是当我将两者组合在一起时,查询需要1.3秒 - 或者慢了130倍!!
以下是查询(为此问题而简化)。
查询1:
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多倍?
备注:
任何进一步的建议都将受到极大的欢迎。
答案 0 :(得分:0)
您的问题评论建议您通过重写查询的无关部分(未在问题中显示)将性能提升到令人满意的水平。
如果它有效,这是公平的,但是当查询的其他不相关部分保持不变时,这并不能解释为什么两个单独的查询和组合查询的差异如此显着。
如果没有查看查询计划和统计结果,很难自信地说出来;但是我可以根据有关如何编写SQL查询的推理来考虑两种可能性:
在这两个表内部连接后,ID
列中的一个或两个(来自FooBar
和FooBalls
)在行集中可能是非唯一的。因此,对CONTAINSTABLE
结果集进行两次而不是一次加入可能会导致"育种"比单个连接更多的记录;较大的结果集需要更长的时间才能传递回客户端并显示。 要对此进行测试:比较两个单独查询返回的行计数,并在省略WHERE
子句时将这些行计数与每个单独查询的行计数进行比较。较大的行数通常表示查询经过的时间较长(所有其他条件相同)。
每个单独的查询都使用左外连接编写,但结果集仅限于包含连接成功的行。这实际上是内部联接:SQL Server的查询计划程序可能正在识别此事实并选择执行计划,就像指定了内部联接一样。相反,组合查询需要行 加入(但不一定两者)都成功,这是一个真正的左连接。执行计划可能会对这些连接使用不同的,较慢的方法。 测试一下:查看执行计划,并与请求内部联接而不是左联接的单独查询的执行计划进行比较。