百分!优化SQL语句时遇见的怪异问题
一条SQL语句,不添加order by ,则查询出结果需要1S左右的时间,而添加order by后,则查询出结果需要20S左右的时间。
通过set statistics io on查看,
结果如下:
--不添加order by
表 'BAS_CONTRACT_CONTENT '。扫描计数 40,逻辑读 136 次,物理读 0 次,预读 0 次。
表 'BAS_USR '。扫描计数 20,逻辑读 53 次,物理读 0 次,预读 0 次。
表 'BAS_ACCOUNT_ITEM '。扫描计数 9088,逻辑读 51963 次,物理读 16 次,预读 0 次。
表 'BAS_CONTRACT_ZX '。扫描计数 9030,逻辑读 36250 次,物理读 5 次,预读 0 次。
表 'BAS_CONTRACT_REP '。扫描计数 9030,逻辑读 18125 次,物理读 0 次,预读 0 次。
表 'BAS_CONTRACT '。扫描计数 1,逻辑读 1507 次,物理读 0 次,预读 0 次。
--添加order by
表 'BAS_CONTRACT_CONTENT '。扫描计数 40,逻辑读 216 次,物理读 0 次,预读 0 次。
表 'BAS_USR '。扫描计数 20,逻辑读 53 次,物理读 0 次,预读 0 次。
表 'BAS_CONTRACT '。扫描计数 2,逻辑读 20781 次,物理读 0 次,预读 8 次。
表 'BAS_CONTRACT_ZX '。扫描计数 1,逻辑读 466 次,物理读 6 次,预读 104 次。
表 'BAS_ACCOUNT_ITEM '。扫描计数 1,逻辑读 986 次,物理读 0 次,预读 0 次。
表 'Worktable '。扫描计数 677,逻辑读 1130 次,物理读 0 次,预读 0 次。
表 'BAS_CONTRACT_REP '。扫描计数 1,逻辑读 11 次,物理读 0 次,预读 0 次。
可以看到不添加order by比添加order by 后的逻辑读的次数高出许多,但是查询速度却快很多,这与我平时看到的资料的描述不符,请各位高手帮忙看看,有什么情况会出现这个情况!
另:order by三个字段A/B/C,A/B组成一个索引,C也设置了索引!
------解决方案-------------------- 'BAS_CONTRACT_CONTENT '
这个表的逻辑读次数在加了ORDER BY之后,高了很多!
=======================
这个表的数据量应该很大,而且你从这个表取的字段量也应该很多吧?
逻辑读次数多不一定速度就慢
一个只有10条数据的表、逻辑读100次、取1个类型为int的字段(平均字节数为4);(A)
一个10000条数据的表、逻辑读10次、取10个类型为int等组合的字段(平均字节数为30);(B)
A的速度也应该会比B快。
------解决方案--------------------对数据库页的请求,该请求中 SQL Server 必须将所请求页从磁盘传输到 SQL Server 缓冲区池。所有读取页的尝试都称作逻辑读取。如果该页已在缓冲区中,则不存在由逻辑读取生成的相关物理读取。物理读取的数目从不会超过逻辑读取的数目。在调整良好的 SQL Server 实例中,逻辑读取的数目通常远高于物理读取的数目。
由此可见,逻辑读是从从数据高速缓存读取的页数,物理读是从磁盘读取的页数,而预读则是为查询放入高速缓存的页数,所以物理读才是决定效率的主要因素(这里单指IO)
另外,做个测试,表1,字段a为聚集索引
select * from table1,和select * from table1 order by a
2条语句的效率或者执行计划应该是一样的,都只扫描聚集索引
如果字段b无索引,select * from table1 order by b,则会执行sort排序工作,这会产生大量的IO操作,对效率影响很大
如果字段b为非聚集索引, select * from table1 order by b,则会对非聚集索引进行排序,这步的IO操作介于聚集索引和无索引之间