设为首页 加入收藏

TOP

SQLServerDBA调优日记(一)――大数据量查询记录数优化及原理探讨(二)
2014-11-23 22:26:29 来源: 作者: 【 】 浏览:31
Tags:SQLServerDBA 日记 数据 查询 记录 优化 原理 探讨
es测试相同。测试结果用时790毫秒,我们查看此时的执行计划,如图十一。执行计划不变。

\

图十一 聚集索引使用sysindexes测试

聚集索引测试完毕,现在我们开始测试非聚集索引。删除聚集索引,建立非聚集索引,语句如下:

DROP INDEX idx_clu_count_test_id ON count_Test.id;
CREATE NONCLUSTERED INDEX idx_nonclu_count_test ON count_Test(id);

删除聚集索引用时16分37秒。创建非聚集索引用时时40分20秒,数据文件占用空间9.38G (9839680K)。

在有非聚集索引的情况下,使用count(*)测试。语句和没有任何索引的情况下使用count(*)测试相同。测试结果用时6分59秒,我们查看此时的执行计划,如图十二。此时走非聚集索引,开销主要在此。

\

图十二 非聚集索引使用count(*)测试

在有非聚集索引的情况下,使用sysindexes测试。语句和没有任何索引的情况下使用sysindexes测试相同。测试结果用时413毫秒,我们查看此时的执行计划,如图十三。执行计划不变。

\

图十三 非聚集索引使用sysindexes测试

接着我们做一个组合测试,包括有普通索引和聚集索引的情况、有普通索引和非聚集索引的情况、有普通索引、聚集索引和非聚集索引的情况。首先测试有普通索引和聚集索引的情况,我们首先删除非聚集索引,然后建立普通索引和聚集索引,语句如下:

DROP INDEX idx_nonclu_count_test ON count_Test.id;
CREATE INDEX idx_nor_count_test_id ON count_Test(id);
CREATE CLUSTERED INDEX idx_clu_count_test_id ON count_Test(id);

删除用时1秒,空间不变。创建聚集索引和普通索引索引用时1:57:27,数据文件占用空间12.9G (13541440 )。

在有普通索引和聚集索引的情况下,使用count(*)测试。语句和没有任何索引的情况下使用count(*)测试相同。测试结果用时5分27秒,我们查看此时的执行计划,如图十四。此时走普通索引,开销主要在此。

\

图十四 聚集索引、普通索引使用count(*)测试

在有普通索引和聚集索引的情况下,使用sysindexes测试。语句和没有任何索引的情况下使用sysindexes测试相同。测试结果用时200毫秒,我们查看此时的执行计划,如图十五,执行计划不变。

\

图十五 聚集索引、普通索引使用sysindexes测试

接着测试有普通索引和非聚集索引的情况,我们删除聚集索引,建立非聚集索引,语句如下:

DROP INDEX idx_clu_count_test_id ON count_Test.id;
CREATE NONCLUSTERED INDEX idx_nonclu_count_test ON count_Test(id); 

删除普通索引用时1:23:10,创建非聚集索引用时6分50秒,数据文件空间占用12.9G。

在有普通索引和非聚集索引的情况下,使用count(*)测试。语句和没有任何索引的情况下使用count(*)测试相同。测试结果用时52秒,我们查看此时的执行计划,如图十六。此时走非聚集索引,开销主要在此。

\

图十六 非聚集索引、普通索引使用count(*)测试

在有普通索引和非聚集索引的情况下,使用sysindexes测试。语句和没有任何索引的情况下使用sysindexes测试相同。测试结果用时203毫秒,我们查看此时的执行计划,如图十七。执行计划不变。

\

图十七 非聚集索引、普通索引使用sysindexes测试

最后,测试有普通索引、聚集索引和非聚集索引的情况。我们创建普通索引,语句如下:

CREATE NONCLUSTERED INDEX idx_nonclu_count_test ON count_Test(id);

创建普通索引用时1:11:21,数据文件占用空间16.3G(17116224KB)。

在有普通索引、聚集索引和非聚集索引的情况下,使用count(*)测试。语句和没有任何索引的情况下使用count(*)测试相同。测试结果用时2分51秒,我们查看此时的执行计划,如图十八。此时走非聚集索引,开销主要在此。

\

图十八 普通索引、聚集索引、非聚集索引使用count(*)测试

在有普通索引、聚集索引和非聚集索引的情况下,使用sysindexes测试。语句和没有任何索引的情况下使用sysindexes测试相同。测试结果用时203毫秒,我们查看此时的执行计划,如图十九。执行计划不变。

\

图十九 普通索引、聚集索引、非聚集索引使用sysindexes测试

加入indid大于1用时86毫秒,执行计划如图二十;加入indid等于1用时23毫秒,执行计划如图二十一。所有的测试完成后,数据文件和日志文件占用空间如图二十二。

\

图二十 加入indid大于1执行时间

\

图二十一 加入indid等于1执行时间\

图二十二 所有的测试完成后,数据文件和日志文件占用空间

我们可以看出以上几种方式在效率上简直是天壤之别。count(*)不管在有什么索引的情况下都较慢,而sysindexes相对快多了。

原理分析

好了,接着我试着分析count(*)和sysindexes为什么会有那么大的差距。首先我查了下帮助文档,里面对sys.indexes 是这样介绍的:Contains one row for eachindex and table in the current database. XML indexes are not supported in thisview. Partitioned tables and indexes are not fully supported in this view; usethe sys.indexes catalog view instead.(当前数据库中的每个索引和表各对应一行。此视图不支持 XML 索引。此视图不完全支持分区表和索引;请改用 sys.indexes 目录视图)。在MS SSQL数据库中,每个数据表都在sys.sysindexes系统表中拥有至少一条记录,记录中的rows 或rowcnt字段会定时记录表的记录总数。请注意是定时,而不是实时,这说明了用这个方法得到的总记录数并不是一个精确值,原因是MS SQL并不是实时更新该字段的值,而是定时更新,但从实践来看该值和精确值误差不大,如果你希望快速粗略估算表的记录总数,建议你采用该方法。如果您希望查看实时的记录数,可以先执行DBCC UpdateUSAGE(DatabaseName,[TABLENAME])WITH ROW_COUNTS 强制更新该字段的值,再使用该SQL进行查询,这样得到的值就是实时的记录数。

在CBO的基础上,count(*)统计记录数是这样的:当对数据进行查询时,得到一条数据则对应的记录数加1,直到返回总共的记录数。在没有索引的情况下,count(*)则是Table Full Scan,也就是全表扫描,对于数据量大的表,全表扫描速度肯定慢,这一点是毋庸置疑的。如果有索引,那么会使用INDEX SCAN,速度相对较快。那如果使用

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇SQL高级查询 下一篇SQLServer中的存储过程

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: