SQL Server 索引结构及其使用(二)
|
SQL Server 索引结构及其使用(二) 改善SQL语句 select * from table1 where name=''zhangsan'' and tID > 10000 和执行: select * from table1 where tID > 10000 and name=''zhangsan'' 一些人不知道以上两条语句的执行效率是否一样,因为如果简单的从语句先后上看,这两个语句的确是不一样,如果tID是一个聚合索引,那么后一句仅仅从表的10000条以后的记录中查找就行了;而前一句则要先从全表中查找看有几个name=''zhangsan''的,而后再根据限制条件条件tID>10000来提出查询结果。 列名 操作符 <常数 或 变量> 或 <常数 或 变量> 操作符列名 列名可以出现在操作符的一边,而常数或变量出现在操作符的另一边。如: Name=’张三’ 价格>5000 5000<价格 Name=’张三’ and 价格>5000 如果一个表达式不能满足SARG的形式,那它就无法限制搜索的范围了,也就是SQL SERVER必须对每一行都判断它是否满足WHERE子句中的所有条件。所以一个索引对于不满足SARG形式的表达式来说是无用的。 如:name like ‘张%’ ,这就属于SARG 而:name like ‘%张’ ,就不属于SARG。 原因是通配符%在字符串的开通使得索引无法使用。 ABS(价格)<5000 Name like ‘%三’ 有些表达式,如: WHERE 价格*2>5000 SQL SERVER也会认为是SARG,SQL SERVER会将此式转化为: WHERE 价格>2500/2 但我们不推荐这样使用,因为有时SQL SERVER不能保证这种转化与原始表达式是完全等价的。 Select * from table1 where tid in (2,3) 和 Select * from table1 where tid=2 or tid=3 是一样的,都会引起全表扫描,如果tid上有索引,其索引也会失效。 (1)select title,price from titles where title_id in (select title_id from sales where qty>30) 该句的执行结果为: (2)select title,price from titles where exists (select * from sales where sales.title_id=titles.title_id and qty>30) 第二句的执行结果为: select gid,title,fariqi,reader from tgongwen
where charindex(''刑侦支队'',reader)>0 and fariqi>''2004-5-5''
用时:7秒,另外:扫描计数 4,逻辑读 7155 次,物理读 0 次,预读 0 次。 select gid,title,fariqi,reader from tgongwen where reader like ''%'' + ''刑侦支队'' + ''%'' and fariqi>''2004-5-5'' 用时:7秒,另外:扫描计数 4,逻辑读 7155 次,物理读 0 次,预读 0 次。 select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16'' or gid>9990000 用时:68秒。扫描计数 1,逻辑读 404008 次,物理读 283 次,预读 392163 次。 select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16'' union select gid,fariqi,neibuyonghu,reader,title from Tgongwen where gid>9990000 用时:9秒。扫描计数 8,逻辑读 67489 次,物理读 216 次,预读 7499 次。 select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16'' or fariqi=''2004-2-5'' 用时:6423毫秒。扫描计数 2,逻辑读 14726 次,物理读 1 次,预读 7176 次。 select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16'' union select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-2-5'' 用时:11640毫秒。扫描计数 8,逻辑读 14806 次,物理读 108 次,预读 1144 次。 select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc 用时:4673毫秒 select top 10000 gid,fariqi,title from tgongwen order by gid desc 用时:1376毫秒 select top 10000 gid,fariqi from tgongwen order by gid desc 用时:80毫秒 select count(*) from Tgongwen 用时:1500毫秒 select count(gid) from Tgongwen 用时:1483毫秒 select count(fariqi) from Tgongwen 用时:3140毫秒 select count(title) from Tgongwen 用时:52050毫秒 select top 10000 gid,fariqi,reader,title from tgongwen 用时:196 毫秒。 扫描计数 1,逻辑读 289 次,物理读 1 次,预读 1527 次。 select top 10000 gid,fariqi,reader,title from tgongwen order by gid asc 用时:4720毫秒。 扫描计数 1,逻辑读 41956 次,物理读 0 次,预读 1287 次。 select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc 用时:4736毫秒。 扫描计数 1,逻辑读 55350 次,物理读 10 次,预读 775 次。 select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi asc 用时:173毫秒。 扫描计数 1,逻辑读 290 次,物理读 0 次,预读 0 次。 select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi desc 用时:156毫秒。 扫描计数 1,逻辑读 289 次,物理读 0 次,预读 0 次。 select top 10 * from ( select top 10000 gid,fariqi,title from tgongwen where neibuyonghu=''办公室'' order by gid desc) as a order by gid asc 这条语句,从理论上讲,整条语句的执行时间应该比子句的执行时间长,但事实相反。因为,子句执行后返回的是10000条记录,而整条语句仅返回10条语句,所以影响数据库响应时间最大的因素是物理I/O操作。而限制物理I/O操作此处的最有效方法之一就是使用TOP关键词了。TOP关键词是SQL SERVER中经过系统优化过的一个用来提取前几条或前几个百分比数据的词。经笔者在实践中的应用,发现TOP确实很好用,效率也很高。但这个词在另外一个大型数据库ORACLE中却没有,这不能说不是一个遗憾,虽然在ORACLE中可以用其他方法(如:rownumber)来解决。在以后的关于“实现千万级数据的分页显示存储过程”的讨论中,我们就将用到TOP这个关键词。
|
浙公网安备 33010602011771号