第2步(即图片第四行)使用WHERE rr.CreateTime BETWEEN '2015-2-16' AND '2015-2-18' 查询 rr表时查找步骤返回的Rows=【62】行,但是实际上这个条件下的记录有【940300】行,那么问题来了,为何第四行查找步骤返回的Rows 不是等于【940300】行你弄错了吧? 你七楼的截图,查询结果ID是71911940的执行计划是截图中的,940300的无名列是count(*)出来的结果吧
感谢回复针对这种情况,一个大表(匹配率低),一个小表,如何连接?想听听你的建议?select top 1 rr.id from rr,ai where rr.userid=ai.userid and rr.createtime between '2015-2-15' and '2015-2-16' order by rr.createtime desc这样写吗?该写法无论TOP 1是否有值,ai和rr的逻辑读次数和exists写法是一样的
select top 1 rr.id from rr,ai where rr.createtime between '2015-2-15' and '2015-2-16' and rr.userid=ai.userid and ai.a='nice' order by rr.createtime desc
对于执行快(第一个图片)的Rows=【62】,但和Count()统计出来的行数【940300】不一致,但是另外一个库(第三个图片)的却是一致的【835879】
对于执行快(第一个图片)的Rows=【62】,但和Count()统计出来的行数【940300】不一致,但是另外一个库(第三个图片)的却是一致的【835879】
实际上楼主误解了,rows列确实是返回的列,
你的查询,一个是top 1 id,一个是count(1),最后返回的当然都是1行数据
之前返回的数据行数是聚合操作之前的行数,因为是并行执行的
最开始的索引seek因为是并行执行的,所以executes是12,返回的行数是835879,然后对12个并行的并行的结果集分别作做聚合运算,依旧是executes12次,返回12行(rows)数据(并行),然后对这个12行做聚合运算,返回的是1行(rows)数据
查看资料显示SET STATISTICS PROFILE ON返回的ROWS 是执行计划的每一步返回的实际行数
对于执行快(第一个图片)的Rows=【62】,但和Count()统计出来的行数【940300】不一致,但是另外一个库(第三个图片)的却是一致的【835879】 我解释一下,拿第一张图片来说,我的理解是这样的:从下面往上看执行计划:
1.先从外部表 ai(600行) 拿出一行数据
2.然后和内部表 rr(940300行 查询条件WHERE rr.CreateTime BETWEEN '2015-2-16' AND '2015-2-18' ) 的记录去匹配,然后取外部表下一条记录再次匹配
3.将所有为真的记录排序
4. 取TOP1
5.返回结果集第2步(即图片第四行)使用WHERE rr.CreateTime BETWEEN '2015-2-16' AND '2015-2-18' 查询 rr表时查找步骤返回的Rows=【62】行,但是实际上这个条件下的记录有【940300】行,那么问题来了,为何第四行查找步骤返回的Rows 不是等于【940300】行5楼朋友说是因为EXISTS短路功能导致的,我不理解的地方是,不是首先要将内部表的数据取出来(第二步),再匹配(第三步)吗?就算是短路了,但是看索引的情况,16-18号数据可是有【940300】行,为何就搜索【62】行就匹配完了
第2步(即图片第四行)使用WHERE rr.CreateTime BETWEEN '2015-2-16' AND '2015-2-18' 查询 rr表时查找步骤返回的Rows=【62】行,但是实际上这个条件下的记录有【940300】行,那么问题来了,为何第四行查找步骤返回的Rows 不是等于【940300】行你弄错了吧?
你七楼的截图,查询结果ID是71911940的执行计划是截图中的,940300的无名列是count(*)出来的结果吧
我怀疑你说的快的是不是在测试环境或者是开发环境测出来的结果,而慢的是在生产环境测试出来的?
你说的快的,第一个截图,统计信息明显没有实时更新,而后一个截图,统计信息就是相对比较新的
要确认快慢是每次都有明显的差异,还是第一次执行差异比较明显,后面再执行快慢差异就不明显了
你需要什么数据,我可以提供给你
刚才我在查询慢的数据库里,把查询条件调整了一下,即同一数据库,一个有值,一个没有值,具体如下:
首先是TOP1没有值的情况接下来是TOP1有值得情况一个奇怪的现象是,当TOP1没值得时候,ai表逻辑读的次数170多万次,一行数据600字节,这个逻辑读次数为何这么高?
有值的情况比没值的情况少读了100多W次?
如果没有匹配的情况,EXISTS一直扫描子表,直到全表扫描完,才发现没有,这时的扫描行数就是全表记录数
假设,有一个查询,符合值在靠后,这时实际的扫描行数也会很大,就如你#11楼的情况。而你普通的聚合查询,这个查询一定是扫描全表,或整个索引的相同条件的查询,作为相关子查询放至EXISTS中和单独聚合查询,两个的扫描行数和数据有很大的关系。因此,EXISTS不适合用于在匹配率低的大表作子查询,万一匹配很低,那你每个相关子查询都是全表扫描,那时间小伙伴会惊呆的。
感谢回复针对这种情况,一个大表(匹配率低),一个小表,如何连接?想听听你的建议?select top 1 rr.id
from rr,ai
where rr.userid=ai.userid and rr.createtime between '2015-2-15' and '2015-2-16'
order by rr.createtime desc这样写吗?该写法无论TOP 1是否有值,ai和rr的逻辑读次数和exists写法是一样的
select top 1 rr.id
from rr,ai
where rr.createtime between '2015-2-15' and '2015-2-16' and rr.userid=ai.userid and ai.a='nice'
order by rr.createtime desc
比如:rr总行数835879,每行600字节,索引400字节
ai总行数600,每行1586字节,索引282字节
ai的逻辑读1724009,rr逻辑读11644有公式能计算出来吗?
如果没有匹配的情况,EXISTS一直扫描子表,直到全表扫描完,才发现没有,这时的扫描行数就是全表记录数但是楼主的问题,一个大表(匹配率低),一个小表,如何连接?
好似乎inner join连接代价要比exists大,楼主可以写一下比较一下
http://www.cnblogs.com/CareySon/archive/2011/12/23/2299127.html
其实也只能是算出个大概
你可以大概对比下你11楼两次的行数与逻辑读的比例是一样的。另外,SQL优化分析语句,我想看下#15楼语句的执行计划。
但是不存在的话,相当于要扫描了整个表后才知道,
这个时候,我想应该只有提高Nested Loops连接效率了
是的,一个大表,一个小表,SQLSERVER 查询分析器生成执行计划时会使用Nested Loops,那就是没办法优化了的意思?