在SQLSERVER中通过索引进行查询优化
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
在SQLSERVER中通过索引进⾏查询优化
索引算是查询优化中最常见,也算是知名度最⾼的⼀种⼿段了,不少于计算机沾边的专业甚⾄在⼤学的时候就已经接触过了索引,甚⾄有了很多使⽤索引优化查询的实际操作经验。
⽤⼀种不是很严谨的⽅式去理解,索引可以认为是把索引所在的数据表中的⼀部分(即索引本⾝的字段以及其包含列)进⾏排序,再保存到额外的存储空间之中。
由于索引本⾝是具有⼀定顺序的,⽽且索引中包含的字段通常⽐实际数据表中的字段要少,数据库引擎在进⾏查找的时候可以⽤更少的IO次数查找更多的记录,因此⼤多数情况下,通过索引进⾏查询的效率会⽐不使⽤索引的查询快很多。
可以⽤⼀个实际的例⼦来体验⼀下索引带来的查询性能的提升。
1、建⽴⼀张结构简单的数据表,并初始化⼀定量的数据:
CREATE TABLE[TestTable] (
id INT NOT NULL IDENTITY (1, 1),
val INT NOT NULL DEFAULT0,
createtime DATETIME NOT NULL DEFAULT GETDATE(),
PRIMARY KEY (id)
) ON[PRIMARY];
View Code
2、为我们的测试数据表初始化约1600万条数据:
DECLARE@i INT;
SET@i=0;
WHILE@i<1000
BEGIN
INSERT INTO TestTable (val) VALUES (@i);
SET@i=@i+1;
END;
DECLARE@ct INT;
SET@ct=0;
WHILE@ct<14
BEGIN
INSERT INTO[TestTable] (val)
SELECT val
FROM[TestTable]WITH (NOLOCK);
SET@ct=@ct+1;
END;
View Code
3、将数据表的表结构及数据复制⼀份⼉,做为⽐对:
SELECT*INTO TestTableNoIndex
FROM[TestTable]WITH (NOLOCK);
View Code
此时,两张表的数据结构及数据量完全相同,但是表TestTable的id列有聚集索引(主键),⽽TestTableNoIndex表没有任何索引,如下图所⽰:
接下来我们尝试随机抽取1个id,并在两张表中根据id对记录进⾏查找,来⽐对两张表中相同记录的查找速度。
以TestTable表为例,SQL如下:
--清除SQL SERVER的缓存
DBCC DROPCLEANBUFFERS;
DBCC FREEPROCCACHE;
DECLARE@beginIndex DATETIME
SET@beginIndex=GETDATE();
SELECT id, val, createtime
FROM[TestTable]
WHERE id =695523;
SELECT DATEDIFF(MS, @beginIndex, GETDATE()) AS'查询时间(有索引)';
View Code
执⾏结果⽅⾯,对于相同的记录,TestTable表的执⾏时间为30毫秒,⽽TestTableNoIndex表需要18260毫秒,可以看到差距已经相当明
显了。
具体分析两张表的实际查询计划,可以看出对TestTable的执⾏计划为“聚集索引查找”
⽽对TestTableNoIndex表的执⾏计划中⼤部分的开销来源于“表扫描”,主要原因就是对于没有索引的表,SQL SERVER引擎只好使⽤最笨的⽅法,根据表中的记录⼀条⼀条的进⾏查找。
可以想象⼀下我们在⼀个已经从⼩到⼤排好序的数组⾥查找⼀条记录,只要当前元素⼤于待检索的元素就可以结束循环了,从⽽节省不少的开销。
此处说明的情况和这种场景有类似之处。
需要说明的是,由于机器的硬件配置差异,或者⽤于测试时表中数据量的差异,都可能导致结果与⽂中描述不同。
此外,如果将上述查询中条件进⾏变更,如根据val字段进⾏查询,那么针对这两张表的查询相应时间都会出现变化,这涉及到包括索引覆盖、聚集索引与⾮聚集索引等多⽅⾯的问题,⽇后视具体情况继续。