查询1:
DECLARE @d datetime
SET @d = getdate()
SELECT top 1000 * FROM product WHERE CONTAINS(name,'男上装') OR CONTAINS(text,'男上装')
SELECT datediff(ms,@d,getdate())
SET @d = getdate()
SELECT * FROM product WHERE CONTAINS(name,'男上装') OR CONTAINS(text,'男上装')
SELECT datediff(ms,@d,getdate())
结果1:(总数:14条)
14条数据用时3610(这是使用了top 1000后)
14条数据用时266 (这是没有使用top 1000的)
查询2:
DECLARE @d datetime
SET @d = getdate()
SELECT top 1000 * FROM product WHERE CONTAINS(name,'公司') OR CONTAINS(text,'公司')
SELECT datediff(ms,@d,getdate())
SET @d = getdate()
SELECT * FROM product WHERE CONTAINS(name,'公司') OR CONTAINS(text,'公司')
SELECT datediff(ms,@d,getdate())
结果2:(总数:165949条)
1000条数据用时4233(这是用了top 1000后)
165949条数据用时8330(这是没用top 1000后)
楼主的查询使用了 OR 条件, 这个查询大致上会这样生成这样的执行计划:
1. 执行两句:
SELECT top 1000 * FROM product WHERE CONTAINS(name,'男上装')
SELECT top 1000 * FROM product WHERE CONTAINS(text,'男上装')
2. 对结果做一个join
这样就涉及取两表join联接的算法了
有top 的情况下, 一般使用的是嵌套循环, 没有top的情况下, 多半使用的是哈希联接
嵌套循环使用的搜索方法是:
将一个联接输入用作外部输入表(显示为图形执行计划中的顶端输入),将另一个联接输入用作内部(底端)输入表。外部循环逐行处理外部输入表。内部循环会针对每个外部行执行,在内部输入表中搜索匹配行。
很显然, 如果匹配的数据很少的话(准确地说匹配的数据在扫描顺序的尾部, 匹配的数据越少, 发生这种情况的可能性越高), 那么扫描势必会遍历完整个表, 这样的效率显然不高.
而哈希联接不存在这种问题
所以你会发觉, 匹配的数据量少的情况下, TOP 的执行效率反而低.
OPTION 子句
指定应在整个查询中使用所指定的查询提示。每个查询提示只能指定一次,但允许指定多个查询提示。用该语句只可能指定一个 OPTION 子句。查询提示影响语句中的所有运算符。如果主查询中涉及 UNION,则只有涉及 UNION 运算符的最后一个查询可以有 OPTION 子句。如果一个或多个查询提示导致查询优化器不生成有效计划,则产生 8622 错误。
注意 由于查询优化器通常为查询选择最优执行计划,所以建议只把 <join_hint>, <query_hint> 和 <table_hint> 作为经验丰富的数据库管理员的最终手段。
语法
[ OPTION ( < query_hint > [ ,...n ] ) ]
< query_hint > ::=
{ { HASH | ORDER } GROUP
| { CONCAT | HASH | MERGE } UNION
| { LOOP | MERGE | HASH } JOIN
| FAST number_rows
| FORCE ORDER
| MAXDOP number
| ROBUST PLAN
| KEEP PLAN
| KEEPFIXED PLAN
| EXPAND VIEWS
}