深入浅出理解索引结构(3)

6exists in 的执行效率是一样的  

很多资料上都显示说,exists要比in的执行效率要高,同时应尽可能的用not exists来代替not in但事实上,我试验了一下,发现二者无论是前面带不带not,二者之间的执行效率都是一样的。因为涉及子查询,我们试验这次用SQL SERVER自带的pubs数据库。运行前我们可以把SQL SERVERstatistics I/O状态打开。  

(1)         select title,price from titles where title_id in (select title_id from sales where qty>30) 

(2)         该句的执行结果为:  

'sales'。扫描计数 18,逻辑读 56 次,物理读 0 次,预读 0 次。  

'titles'。扫描计数 1,逻辑读 2 次,物理读 0 次,预读 0 次。  

2select title,price from titles where exists (select * from sales where sales.title_id=titles.title_id and qty>30) 

第二句的执行结果为:  

'sales'。扫描计数 18,逻辑读 56 次,物理读 0 次,预读 0 次。  

'titles'。扫描计数 1,逻辑读 2 次,物理读 0 次,预读 0 次。  

我们从此可以看到用exists和用in的执行效率是一样的。  

7、用函数charindex()和前面加通配符%LIKE执行效率一样  

        前面,我们谈到,如果在LIKE前面加上通配符%,那么将会引起全表扫描,所以其执行效率是低下的。但有的资料介绍说,用函数charindex()来代替LIKE速度会有大的提升,经我试验,发现这种说明也是错误的:  

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 次。  

8union并不绝对比or的执行效率高  

        我们前面已经谈到了在where子句中使用or会引起全表扫描,一般的,我所见过的资料都是推荐这里用union来代替or。事实证明,这种说法对于大部分都是适用的。  

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 次。  

        看来,用union在通常情况下比用or的效率要高的多。  

       但经过试验,笔者发现如果or两边的查询列是一样的话,那么用union则反倒和用or的执行速度差很多,虽然这里union扫描的是索引,而or扫描的是全表。 

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 次。  

9、字段提取要按照“需多少、提多少”的原则,避免“select *”  

我们来做一个试验:  

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毫秒  

       由此看来,我们每少提取一个字段,数据的提取速度就会有相应的提升。提升的速度还要看您舍弃的字段的大小来判断。  

10count(*)不比count(字段)  

某些资料上说:用*会统计所有列,显然要比一个世界的列名效率低。这种说法其实是没有根据的。我们来看: 

select count(*) from Tgongwen 用时:1500毫秒  

select count(gid) from Tgongwen 用时:1483毫秒  

select count(fariqi) from Tgongwen 用时:3140毫秒  

select count(title) from Tgongwen   用时:52050毫秒  

       从以上可以看出,如果用count(*)和用count(主键)的速度是相当的,而count(*)却比其他任何除主键以外的字段汇总速度要快,而且字段越长,汇总的速度就越慢。我想,如果用count(*) SQL SERVER可能会自动查找最小字段来汇总的。当然,如果您直接写count(主键)将会来的更直接些。 

你可能感兴趣的:(数据结构,sql,SQL Server)