SQL索引谣言粉碎

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

很多文章都提到使用IN,OR会破坏索引,造成全表扫描,但实际测试却不是这样。

SELECTcFROMtWHEREc=1SELECTcFROMtWHEREcin(1)

或者

SELECTcFROMtWHEREc=1ORc=2SELECTcFROMtWHEREcin(1,2)

以上SQL文,第一组(=,IN),第二组(=,OR,IN),每一组的两个SQL文都使用相同的执行计划,执行计划中也可以看到使用了相同的索引,磁盘活动信息中的逻辑读次数也相同。

测试中需要的设定:

SET STATISTICS IO ON 使SQLSERVER显示Transact-SQL语句生成的磁盘活动量信息。

SET STATISTICS TIME ON 显示分析,编译,执行语句所需要的毫秒数

每次执行查询前的处理:

CHECKPOINT 强制将当前数据库的全部脏页写入磁盘,然后清除缓冲区

DBCC DROPCLEANBUFFERS 从缓冲池中删除所有CleanBuffers

测试:

SQLServer 2008 R2

SQLServer 2014

1.新建数据库表:

CREATETABLE[dbo].[TestTable]([ID][bigint]IDENTITY(1,1)NOTNULL,[Birthday][varchar](10)NOTNULL,CONSTRAINT[PK_TestTable]PRIMARYKEYCLUSTERED([ID]ASC)WITH(PAD_INDEX=OFF, STATISTICS_NORECOMPUTE=OFF, IGNORE_DUP_KEY=OFF, ALLOW_ROW_LOCKS=ON, ALLOW_PAGE_LOCKS=ON)ON[PRIMARY])ON[PRIMARY]

2.向Birthday中插入大量数据

3.建立Birthday列的非聚集索引

4.查询测试

CHECKPOINTDBCCDROPCLEANBUFFERSSELECTbirthdayFROM[dbo].[TestTable]WHEREBirthdayIN('19901111')

表 'TestTable'。扫描计数 1,逻辑读取 8 次,物理读取 2 次,预读 5 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

CHECKPOINT

DBCC DROPCLEANBUFFERS

SELECT Birthday FROM [dbo].[TestTable] WHERE Birthday IN ('19901111')

表 'TestTable'。扫描计数 1,逻辑读取 8 次,物理读取 2 次,预读 5 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

下面的语句执行后,查询计划以及读取次数也都是一样的。

CHECKPOINTDBCCDROPCLEANBUFFERSSELECTBirthdayFROM[dbo].[TestTable]WHEREBirthday='19901111'ORBirthday='19901212'

表 'TestTable'。扫描计数 2,逻辑读取 16 次,物理读取 2 次,预读 10 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

CHECKPOINTDBCCDROPCLEANBUFFERSSELECTbirthdayFROM[dbo].[TestTable]WHEREBirthdayIN('19901111','19901212')

表 'TestTable'。扫描计数 2,逻辑读取 16 次,物理读取 2 次,预读 10 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。

执行计划截图这里就不上传了,有兴趣的话,大家可以自行验证。

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航