你先执行没有Top的,再执行有Top的,测试一下时间
解决方案 »
- TravyLee,你昨天帮我写的SQL有点小问题,帮忙再看看,谢谢!
- 请教一个Selec语句中的[列名] in (值列表)的问题
- Sqlserver 与 oracle 相比,各方面性能真的差距那么大吗?3000人的国企用的数据库,专业人员最后定性 sqlserver 太差,太初级.......
- sql卸载后重装不成功,请高手帮我.
- 实际应用中的棘手问题
- SQL2005 express edition 出现部分英文
- 表的更新
- 大家帮忙好急................
- 表的转换问题
- 涉及天数的小计问题
- 排序问题
- 谁能说明白,数据库应用中的“商业规则(business rule)”到底指的是什么?
查询问:加了top限制,就少扫描了165949-1000条数据,当然比第二条语句快(第二条没加TOP限制,是全表扫描)
第二个语句执行时就不需要任何I/O操作了,当然快了,你可以查询1 执行多次就知道了。
查询2:第一个语句加了top限制,就只扫描表前1000条数据,当然比第二条语句快(第二条没加TOP限制,是全表扫描)
DECLARE @d datetime
SET @d = getdate()SELECT * FROM product WHERE CONTAINS(name,'男上装') OR CONTAINS(text,'男上装')
SELECT datediff(ms,@d,getdate())
SET @d = getdate()
SELECT top 1000 * FROM product WHERE CONTAINS(name,'男上装') OR CONTAINS(text,'男上装')
SELECT datediff(ms,@d,getdate())先取得所有的。。再取得TOP1000的。
结果:(总数:14条)
14条数据用时313(这是没用top 1000后)
14条数据用时3780(这是用了top 1000后)
同时。“查询1”和“查询2”是“一样”的查询语句。只是条件不同。
查询1查出的总数是14条,查询2查出的总数是165949条。当总数14条时。用了TOP 1000 比没用TOP 1000的查询花费时间多。
当总数165949条时,用了TOP 1000 比没用TOP 1000的查询花费时间少。
可是当数据少时,如14条。取TOP 1000 比没TOP 1000的要慢很多。
而数据多时,如160K。取TOP 1000 比没TOP 1000的要快很多。。
1. 执行两句:
SELECT top 1000 * FROM product WHERE CONTAINS(name,'男上装')
SELECT top 1000 * FROM product WHERE CONTAINS(text,'男上装')
2. 对结果做一个join这样就涉及取两表join联接的算法了
有top 的情况下, 一般使用的是嵌套循环, 没有top的情况下, 多半使用的是哈希联接嵌套循环使用的搜索方法是:
将一个联接输入用作外部输入表(显示为图形执行计划中的顶端输入),将另一个联接输入用作内部(底端)输入表。外部循环逐行处理外部输入表。内部循环会针对每个外部行执行,在内部输入表中搜索匹配行。很显然, 如果匹配的数据很少的话(准确地说匹配的数据在扫描顺序的尾部, 匹配的数据越少, 发生这种情况的可能性越高), 那么扫描势必会遍历完整个表, 这样的效率显然不高.
而哈希联接不存在这种问题所以你会发觉, 匹配的数据量少的情况下, TOP 的执行效率反而低.
OPTION(HASH JOIN)应该会发现, 是否加TOP的效率都差不多了(注意, 如果匹配的数据量多的话, 要考虑不加TOP时, 取回大量数据对查询时间的影响)
根据你的意见:
我改成:
DECLARE @d datetime
SET @d = getdate()
SELECT top 1000 * FROM product WHERE CONTAINS(name,'男上装') OR CONTAINS(text,'男上装')
OPTION(HASH JOIN)
SELECT datediff(ms,@d,getdate())SQL查询分析器显示为:
服务器: 消息 8622,级别 16,状态 1,行 3
由于此查询中定义的提示,查询处理器未能生成查询计划。请重新提交查询,并且不要在查询中指定任何提示,也不要使用 SET FORCEPLAN。
SELECT top 1000 * FROM product WHERE CONTAINS(name,'男上装') OR CONTAINS(text,'男上装')
OPTION(HASH JOIN)显示错误为:
服务器: 消息 8622,级别 16,状态 1,行 1
由于此查询中定义的提示,查询处理器未能生成查询计划。请重新提交查询,并且不要在查询中指定任何提示,也不要使用 SET FORCEPLAN。
指定应在整个查询中使用所指定的查询提示。每个查询提示只能指定一次,但允许指定多个查询提示。用该语句只可能指定一个 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
}
上网搜索了下资料。给的HASH JOIN的例子是:SELECT A.PONO,B.VCODE,B.VNAME FROM TBLPO A INNER JOIN TBLVENDOR B ON A.VENDORID=B.ID OPTION (HASH JOIN)我刚刚试了OPTION(HASH UNION),可以运行。但是结果和没加OPTION(HASH UNION)时所用的时间。一样。
(2005应该在这方面改进了, 所以我在2005下倒是成功的)
你直接看查询计划好了, 看看它使用的联接是否如我猜测的那样.
如果数据多时。当到达1000时。他就不再读了执行计划里:
TOP 1000 少数据时:是Nested Loops/Left Semi Jion而*少数据,*多数据,TOP1000多数据时:是Merge Join/Left Semi Join
但是不知道怎么优化。。
DECLARE @d datetime
SET @d = getdate()
set rowcount 1000
SELECT * FROM product WHERE CONTAINS(name,'男上装') OR CONTAINS(text,'男上装')
SELECT datediff(ms,@d,getdate())
SET @d = getdate()
set rowcount 0
SELECT * FROM product WHERE CONTAINS(name,'男上装') OR CONTAINS(text,'男上装')
SELECT datediff(ms,@d,getdate())
DECLARE @d datetime
SET @d = getdate()
set rowcount 1000
SELECT * FROM product WHERE CONTAINS(name,'男上装') OR CONTAINS(text,'男上装')
SELECT datediff(ms,@d,getdate())
SET @d = getdate()
set rowcount 0
SELECT * FROM product WHERE CONTAINS(name,'男上装') OR CONTAINS(text,'男上装')
SELECT datediff(ms,@d,getdate())效率是:
6356
283感觉使用set rowcount 1000和用top 1000一样的。