这篇文章主要为大家详细介绍了SQL Server 查询性能优化之不可小觑的书签查找介绍,具有一定的参考价值,可以用来参考一下。
感兴趣的小伙伴,下面一起跟随四海网的小编两巴掌来看看吧!
小小程序猿SQL Server认知的成长代码如下:
--懒得的肥兔 --创建表Users
Create table Users
(
UserID int identity,
UserName nvarchar(50),
Age int,
Gender bit,
CreateTime datetime
)
--在UserID列创建聚集索引PK_UserID
create unique clustered index PK_UserID on Users(UserID)
--在UserName创建非聚集索引IX_UserName
create index IX_UserName on Users(UserName)
--插入示例数据
insert into Users(UserName,Age,Gender,CreateTime)
select N'Bob',20,1,'2012-5-1'
union all
select N'Jack',23,0,'2012-5-2'
union all
select N'Robert',28,1,'2012-5-3'
union all
select N'Janet',40,0,'2012-5-9'
union all
select N'Michael',22,1,'2012-5-2'
union all
select N'Laura',16,1,'2012-5-1'
union all
select N'Anne',36,1,'2012-5-7'
代码如下:
select * from Users
select * from Users where UserID=4
代码如下:
--查询1:使用索引IX_UserName,选择列UserID,UserName,查询条件列为UserName
select UserID,UserName from Users with(index(IX_UserName)) where UserName='Robert'
--查询2:使用索引IX_UserName,选择列UserID,UserName,Age,查询条件列为UserName
select UserID,UserName,Age from Users with(index(IX_UserName)) where UserName='Robert'
--查询3:使用索引IX_UserName,选择列UserID,UserName,查询条件列为UserName,Age
select UserID,UserName from Users with(index(IX_UserName)) where UserName='Robert' and Age=28
--查询4:使用索引IX_UserName,选择列所有列,查询条件列为UserName
select * from Users with(index(IX_UserName)) where UserName='Robert'
【图片暂缺】【图片暂缺】
书签查找是怎么发生的和许多人一样看到大神们画的二叉树索引结构图就脑袋大,看得云里雾里,所以这里我们以表Users为例来说聚集索引(PK_UserID)和非聚集索引(IX_UserName)的结构可以简单的表示为下图
【图片暂缺】
首先我们来看聚集索引PK_UserID,对于聚集索引来说数据行就是其叶子节点,故当执行聚集索引查找时找到了具体的键值后就可以直接去叶子节点获取所有需要的数据不需要进行额外的逻辑读,比如select * from Users where UserID=2,根据值2在索引PK_UserID中找到UserID为2的值后去叶子节点就可以拿到所需数据,然后返回查询结果代码如下:
--set statistics io onselect * from Users where UserName like 'ja%'select * from Users with(index(IX_UserName)) where UserName like 'ja%'
【图片暂缺】
【图片暂缺】
我们示例的数据量比较小,所以感受不明显,不过我们却也看到了我们在UserName列上市建立了索引 IX_UserName,默认情况下查询优化器并没有使用我们的索引,而是选择了表扫描,仅仅需要2次逻辑读就拿到了我们需要的数据,在我们使用索引提示强制查询优化器使用索引IX_UserName后,同样也是返回2条数据,逻辑读缺达到了惊人的6次,看查询计划使用IX_UserName后发生了书签查找,而这个开销主要是有书签查找造成的,而且随着我们返回数据量的增加,由书签查找导致的逻辑读将会成直线上升,造成的结果就是查询开销比进行全表扫描还要大的多,最终导致索引失效代码如下:
drop index IX_UserName on Userscreate index IX_UserName on Users(UserName,Age)
【图片暂缺】
我们可以看到查询2、查询3的书签查找已经消失,因为索引IX_UserName包含了查询中用到得所有列(UserID,UserName,Age),查询4因为选择返回所有列我们的索引没有包含Gender和CreateTime列,故还是会进行书签查找
这时索引IX_UserName结构表示如下
【图片暂缺】
可见对于查询2、查询3仅仅通过索引IX_UserName既可以拿到需要的列UserName,Age,UserID,而对于查询4索引并没有全部覆盖还是需要进行书签查找
代码如下:
drop index IX_UserName on Userscreate index IX_UserName on Users(UserName,Age) include(Gender,CreateTime)
【图片暂缺】
可以看到我们修改索引使用include包含了Gender,CreateTime后,索引IX_UserName达到了对数据表Users的所有列的全覆盖,这时候毫无疑问的查询2、查询3没有出现书签查找,查询4的书签查找也消失了。
此时索引IX_UserName 结构如下
【图片暂缺】
索引IX_UserName已经达到了对Users表的全覆盖,对于我们的查询2、查询3、查询4来说,仅通过索引IX_UserName即可完成查询,不需要进行书签查找。
这时我们再来看一下这两个查询的开销及查询计划,可以看到不需要我们进行索引提示,查询优化器已经自动选择了我们的索引,逻辑读也降至了2次
select * from Users where UserName like 'ja%'select * from Users with(index(IX_UserName)) where UserName like 'ja%'
【图片暂缺】
【图片暂缺】
关于Include请参考 SQL Server 索引中include的魅力(具有包含性列的索引)本文来自:http://www.q1010.com/179/7927-0.html
注:关于SQL Server 查询性能优化之不可小觑的书签查找介绍的内容就先介绍到这里,更多相关文章的可以留意四海网的其他信息。
关键词:SQL SERVER
四海网收集整理一些常用的php代码,JS代码,数据库mysql等技术文章。