程序员眼中的 SQL Server-非聚集索引能给我们带来什么?
写在前面
最近在做的一个项目,页面访问的时候很慢(大概几秒钟的样子),然后用日志记录的方式,来排查这个问题,最后发现是 Entity Framework 初始化的一个坑(大概要花 6-7 秒),详见:《来,给Entity Framework热热身》,但是除了这个问题,还发现当一些用户数据量很大的时候,访问也是有些慢,这个就不是 Entity Framework 的问题了(因为初始化已完成),用 Sql Server Profiler 来跟踪页面访问的时 SQL 的执行情况,因为应用程序很简单,页面加载的时候,跟踪检测到三个 SQL 执行,看了下也没什么问题(两个获取数量,一个获取列表),数量获取的 SQL,这个应该执行会很快,所以把分析焦点放在了那个获取列表的 SQL 上,因为 SQL 没什么问题,那应该是关于这条 SQL 建的索引有问题。注:上面所说项目中大概有 100 万的数据。
关于数据库中的索引概念,记得在很早之前整理了一篇博文《T-Sql(八)字段索引和数据加密》,现在来看,写的真是一坨屎,概念讲的再多没个毛用,关键在于对实际应用中产生问题的分析。在研究这个问题之前,搜了一些相关资料,主要来自园中的几位 SQL Server 大神(CareySon、桦仔、听风吹雨等),稍微看了下,关于索引,主要是一些数据库专业术语,看的不是很明白,作为程序员,我们知道索引分为聚集性索引和非聚集性索引,聚集性索引一般为主键(也可以不是),在创建表的时候会自动创建,针对上面我那个应用查询问题,查询条件是一些非主键字段,所以这边探讨下非聚集性索引。
我不会说一些数据库概念,所以只能用做一些实践来理解概念的意义,以下应用场景中的用例是虚拟出来的,只是作为个人研究使用。
程序员应该有刨根问底的怪癖,虽然这是个数据库问题。
应用场景
有一个 Product 表,字段如下:

数据添加脚本:
begin tran
declare @index int
set @index=0
while(@index<1000000)
begin
insert into [dbo].[Product]([Name],Remarks,ProviderID,[Time],[State])
values('我是测试标题1','我是测试备注1我是测试备注1我是测试备注1我是测试备注1我是测试备注1我是测试备注1',1,GETDATE(),0)
insert into [dbo].[Product]([Name],Remarks,ProviderID,[Time],[State])
values('我是测试标题2','我是测试备注2我是测试备注2我是测试备注2我是测试备注2我是测试备注2我是测试备注2',1,GETDATE(),1)
insert into [dbo].[Product]([Name],Remarks,ProviderID,[Time],[State])
values('我是测试标题3','我是测试备注3',3,GETDATE(),1)
insert into [dbo].[Product]([Name],Remarks,ProviderID,[Time],[State])
values('我是测试标题4','我是测试备注4我是测试备注4我是测试备注4我是测试备注4我是测试备注4我是测试备注4',4,GETDATE(),1)
set @index=@index+1
end
commit
Product 表中插入了四百万的数据,为了接近我们现实生产环境,所以对数据进行了不同插入。
一般应用环境查询,有时候我们会针对一个字段进行 where 查询,有时候也会 and 另一个字段进行查询,这个时候,关于这两个字段的索引怎么建?还是不需要建?是分别建两个?还是建一个组合的?其实说真的,可能看到这的数据库大神会莞尔一笑,但是作为程序员,这些我真不知道,搜索的资料中也并没有对这些鸡毛蒜皮进行的说明,没办法,只能自己瞎折腾下。我们下面要做是 ProviderID 和 State 的查询操作,有分别查询,也有组合查询,然后我们再对 Product 表建立这两个字段的索引,看看有什么不同之处?还有就是针对不同的索引方式,查询又会有什么不同?我们睁大眼睛来看一下。
问题分析
我再对上面的分析进行说明下,首先,查询主要为2种:
- where ProviderID=?
- where ProviderID=? and State=?
非聚集性索引的创建主要为3种:
- 不创建索引
- ProviderID 字段索引
- ProviderID 和 State 字段索引
针对这个应用场景和上面的分析,会得出 3*2 六种结果,其实我最想知道的是下面的第三种,即创建一个组合字段索引,对单个字段的查询会不会有影响?还有就是反过来,单个字段的索引创建,对组合字段查询会不会有影响?当然试过了才知道,看一下执行结果。
执行结果
测试脚本:
declare @begin_date datetime
declare @end_date datetime
select @begin_date = getdate()
select * from [dbo].[Product] where ...
select @end_date = getdate()
select datediff(ms,@begin_date,@end_date) as '用时/毫秒'
为了接近测试结果,每次语句执行三次,然后再取平均值,截图太麻烦了,这边就直接贴下执行结果。
不创建索引
where ProviderID=1(二百万数据)
执行结果:13806毫秒,13380毫秒,12730毫秒
平均结果:13305毫秒where ProviderID=1 and State=1(一百万数据)
执行结果:6556毫秒,6613毫秒,6706毫秒
平均结果:6625毫秒
创建索引字段 ProviderID

where ProviderID=1
执行结果:13986毫秒,13810毫秒,15853毫秒
平均结果:14549毫秒where ProviderID=1 and State=1
执行结果:7153毫秒,7190毫秒,13950毫秒
平均结果:7122毫秒
创建索引字段 ProviderID 和 State

where ProviderID=1
执行结果:13840毫秒,14163毫秒,15853毫秒
平均结果:14618毫秒where ProviderID=1 and State=1
执行结果:7033毫秒,7220毫秒,7023毫秒
平均结果:7152毫秒
结果分析

虽然测试的有些不完整,但是看到结果,哥有些凌乱了(建了索引,性能反而会降低?),难道是我插入的数据有问题?还是创建索引有问题?还是我人品有问题???坐等数据库大神指教。。。
程序员眼中的 SQL Server-非聚集索引能给我们带来什么?的更多相关文章
- 程序员眼中的 SQL Server-执行计划教会我如何创建索引?
先说点废话 以前有 DBA 在身边的时候,从来不曾考虑过数据库性能的问题,但是,当一个应用程序从头到脚都由自己完成,而且数据库面对的是接近百万的数据,看着一个页面加载速度像乌龟一样,自己心里真是有种挫 ...
- SQL查询优化:详解SQL Server非聚集索引(转载)
本文是转载,原文地址 http://tech.it168.com/a2011/1228/1295/000001295176.shtml 在SQL SERVER中,非聚集索引其实可以看作是一个含有聚集索 ...
- SQL Server 非聚集索引的覆盖,连接,交叉和过滤 <第二篇>
在SQL Server中,非聚集索引其实可以看做是一个含有聚集索引的表,但相对实际的表来说,非聚集索引中所存储的表的列数要少得多,一般就是索引列,聚集键(或RID).非聚集索引仅仅包含源表中的非聚集索 ...
- T-SQL查询高级--理解SQL SERVER中非聚集索引的覆盖,连接,交叉和过滤
写在前面:这是第一篇T-SQL查询高级系列文章.但是T-SQL查询进阶系列还远远没有写完.这个主题放到高级我想是因为这个主题需要一些进阶的知识作为基础..如果文章中有错误的地方请不吝指正.本篇文章 ...
- SQL Server的聚集索引和非聚集索引
微软的SQL SERVER提供了两种索引:聚集索引(clustered index,也称聚类索引.簇集索引)和非聚集索引(nonclustered index,也称非聚类索引.非簇集索引)…… (一) ...
- 但从谈论性能点SQL Server选择聚集索引键
简单介绍 在SQL Server中,数据是按页进行存放的.而为表加上聚集索引后,SQL Server对于数据的查找就是依照聚集索引的列作为keyword进行了. 因此对于聚集索引的选择对性能的影响就变 ...
- 探究SQL添加非聚集索引,性能提高几十倍之谜
上周,技术支持反映:客户的一个查询操作需要耗时6.1min左右,在跟进代码后,简化了数据库的查询后仍然收效甚微.后来,技术总监分析了sql后,给其中的一个表添加的一个非聚集索引(三个字段)后,同样的查 ...
- SQL SERVER中非聚集索引的覆盖,连接,交叉,过滤
1.覆盖索引:select和where中包含的结果集中应存在“非聚集索引列”,这样就不用查找基表了,索引表即可搞定: 2.索引交叉:索引的交叉可以理解成建立多个非聚集索引之间的join,如表实体一 ...
- 图解SQL Server:聚集索引、唯一索引、主键
http://www.cnblogs.com/chenxizhang/archive/2010/01/14/1648042.html
随机推荐
- 安装windows服务批处理代码
批处理是DOS时代比较常用的方法之一,目前来说也是一种高效的方法,复制代码到文本文件中,保存并修改文件扩展名为“*.bat”. 安装windows服务批处理代码如下: @echo off set fi ...
- Odoo 二次开发教程(四)-只读、唯一性验证和ORM方法介绍
一.只读和唯一性验证 只读的设置有两种方法,一种是实在字段定义时设置为只读,第二种是在页面视图中进行设置. 接前例,我们将学生(tech.student)的名字name字段设置成只读. 方法一:字段定 ...
- syntax error near unexpected token‘(
用虚拟机的时候出现这样的: 上网查了资料之后,在括号"( " 前加上"$"字符就暂时不会提示出错了.
- 谢欣伦 - OpenDev原创教程 - 媒体开发库libMedia
libMedia是一个免费的简单的媒体开发库,其中的接口类与函数大都以小写的x打头,来源于我的姓氏首字母(谢欣伦). 下载 OpenDev for VS2012 libMedia提供四大功能,一是视频 ...
- java身份证验证
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; impor ...
- canvas初探1
刚申请的博客,当然这也是第一篇.对于canvas也是刚开始着手进行学习,有哪些不对的地方,还望看到本篇博文的朋友指正. 1.canvas的历史 首先,它是HTML5的一个标签. 它是为了客户端矢量图形 ...
- 思科交换机配置DHCP的四个方面
这里我们主要讲解了思科交换机配置DHCP的相关内容.我们对网络拓扑先进行一下了解,然后对于其在进行一下说明,之后对于配置的代码和命令再进行一下解析. 思科交换机配置DHCP一.网络拓扑 思科交换机配置 ...
- 函数randint的使用
摘自百科: ANDINT 在MATLAB中用于产生基质的均匀分布的随机整数. 用法: 1.OUT = RANDINT 产生一个“ 0 ”或“ 1 ”等概率 2.OUT = RANDINT(M) 生成的 ...
- 关于JQuery的一个Bug
关于JQuery的什么问题了? .parents()这个方法与form放在一起有些不对 上码 <!DOCTYPE html> <html> <head> <m ...
- HTTPS工作原理
HTTPS是什么 HTTPS全称为Hypertext Transfer Protocol over Secure Socket Layer,及以安全为目标的HTTP通道,简单说就是HTTP的安全版本. ...