SQL开发中容易忽视的一些小地方(四)
本篇我想针对网上一些对于非聚集索引使用场合的某些说法进行一些更正. 下面引用下MSDN对于非聚集索引结构的描述.
非聚集索引结构:
1:非聚集索引与聚集索引具有相同的 B 树结构,它们之间的显著差别在于以下两点:
* 基础表的数据行不按非聚集键的顺序排序和存储。
* 非聚集索引的叶层是由索引页而不是由数据页组成。
2:非聚集索引行中的行定位器或是指向行的指针,或是行的聚集索引键,如下所述:
* 如果表是堆(意味着该表没有聚集索引),则行定位器是指向行的指针。该指针由文件标识符 (ID)、页码和页上的行数生成。整个指针称为行 ID (RID)。
* 如果表有聚集索引或索引视图上有聚集索引,则行定位器是行的聚集索引键。如果聚集索引不是唯一的索引,SQL Server 将添加在内部生成的值(称为唯一值)以使所有重复键唯一。此四字节的值对于用户不可见。仅当需要使聚集键唯一以用于非聚集索引中时,才添加该值。SQL Server 通过使用存储在非聚集索引的叶行内的聚集索引键搜索聚集索引来检索数据行。
网络观点:order by 子句中使用了的列,可以在此列上建非聚集索引以提高查询速度.
原文地址:http://gocom.primeton.com/blog10697_1221.htm
本人观点:总之一句话,环境不同,表结构不同,数据分布不同,最终结果也不一定相同.
案例:本人最近做一个项目时有两个大表关联,都接近千万.一个表是订单表order,另一个是会员表member,订单中有一字段create_date:类型为datatime,其中的值都是不相同且唯一,而且并不连续,下面是一些值:
create_date
-----------------------
2008-10-05 04:00:56.000
2008-10-05 03:55:55.000
2008-10-05 03:55:42.000
2008-10-05 03:54:40.000
2008-10-05 03:54:32.000
2008-10-05 03:54:23.000
2008-10-05 03:47:16.000
2008-10-05 03:46:08.000
2008-10-05 03:42:28.000
2008-10-05 03:42:09.000
订单表和会员表有一个关联字段为proxyID,各自均建有索引.查询语句如下:
select * from order inner join member on order.proxyID=member.proxyID
where leaveDate between '开始时间' and '结束时间' order by create_date desc
测试:
情况一:在create_date上创建非聚集索引.执行的IO和所用时间消耗如下图:可以看出这种情况对memer表进行了大量的表扫描. 83588次.
情况二:删除create_date上的索引,按理来说应该会比有索引会慢些,下面是执行的IO和时间消耗图:
对此我有以下发现:
1:order by 字段没有创建索引的情况下,对member表只扫描了9次.远少于创建索引时的83588次.
2:还有一个现象就是如果按在查询分析器中全部显示出数据来看,没有创建索引最终所用时更少.
3:创建索引的查询会比没有创建索引的查询早一步显示数据,不过最终完成的时间要长.
测试未知难题:
1:就查询速度来说,是早一步在查询分析器中显示数据的查询快还是说要看最终完全的时间来判断.(create_date创建索引的情况会更早显示数据,不过总共用时会比不创建索引的慢)园友zping曾告诉我不要看时间要看IO数量.不知道大家是怎么分析的.
2:在一个字段上创建索引为什么会引发member表的多次表扫描.
测试说明:由于SQL2005有缓存功能,所有两次查询的时间段并不相同,但数据量都差不多.
根据园友 perfectdesign的观点,order by 时,如果字段是聚集索引将会是最优的,这点我个人以及MSDN都同意,奇怪的是,上面的语句中,leave_date上即聚集索引,然后order by leave_date desc,然而也会产生5万多次的member表扫描,好像是order by 索引字段,无论是聚集还是非聚集都会大量增加对member表的扫描.真是百思不得其解.下面是详细的ID情况:
(2000 row(s) affected)
Table 'member'. Scan count 52796, logical reads 234885, physical reads 0, read-ahead reads 3687, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'v_hotel'. Scan count 1, logical reads 3121, physical reads 0, read-ahead reads 28, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
测试结论:这种情况足以说明对于order by 字段创建索引并不一定能发挥非聚集索引的优势,至于其中原因本人不才,目前并无答案,如大家有答案还望指教一二.数据库的调优虽然有一定的原则及准则,但这些所谓准则并一定全对.本人觉的都仅供参考,还是要按实际情况来分析.
下面贴下MSDN对于非聚集索引应用场合的说明,我觉的还是可能参考的:
在创建非聚集索引之前,应先了解访问数据的方式。考虑对具有以下属性的查询使用非聚集索引:
- 使用 JOIN 或 GROUP BY 子句。
应为联接和分组操作中所涉及的列创建多个非聚集索引,为任何外键列创建一个聚集索引。 - 不返回大型结果集的查询。
创建筛选索引以覆盖从大型表中返回定义完善的行子集的查询。 - 包含经常包含在查询的搜索条件(例如返回完全匹配的 WHERE 子句)中的列。
注:
本文引用:MSDN
SQL开发中容易忽视的一些小地方(四)的更多相关文章
- SQL开发中容易忽视的一些小地方(五)
原文:SQL开发中容易忽视的一些小地方(五) 背景: 索引分类:众所周知,索引分为聚集索引和非聚集索引. 索引优点:加速数据查询. 问题:然而我们真的清楚索引的应用吗?你写的查询语句是否能充分应用上索 ...
- SQL开发中容易忽视的一些小地方(一)
原文:SQL开发中容易忽视的一些小地方(一) 写此系列文章缘由: 做开发三年来(B/S),发现基于web 架构的项目技术主要分两大方面: 第一:C#,它是程序的基础,也可是其它开发语言,没有开发语言也 ...
- SQL开发中容易忽视的一些小地方(二)
原文:SQL开发中容易忽视的一些小地方(二) 目的:继上一篇:SQL开发中容易忽视的一些小地方(一) 总结SQL中的null用法后,本文我将说说表联接查询. 为了说明问题,我创建了两个表,分别是学生信 ...
- SQL开发中容易忽视的一些小地方(六)
原文:SQL开发中容易忽视的一些小地方(六) 本文主旨:条件列上的索引对数据库delete操作的影响. 事由:今天在博客园北京俱乐部MSN群中和网友讨论了关于索引对delete的影响问题,事后感觉非常 ...
- SQL开发中容易忽视的一些小地方( 三)
原文:SQL开发中容易忽视的一些小地方( 三) 目的:这篇文章我想说说我在工作中关于in和union all 的用法. 索引定义 : 微软的SQL SERVER提供了两种索引:聚集索引(cluster ...
- ios开发——错误总结篇&开发中常见错误和警告总结(四)
ios开发——开发总结&开发中常见错误和警告总结(四) 网易彩票实战总结(错误) 错误总结之类的实现 经典错误之重复定义与导入错误 经典错误关于父类的实现 通知对象: 控制器的定义 Xcode ...
- PL/SQL开发中动态SQL的使用方法
一般的PL/SQL程序设计中,在DML和事务控制的语句中可以直接使用SQL,但是DDL语句及系统控制语句却不能在PL/SQL中直接使用,要想实现在PL/SQL中使用DDL语句及系统控制语句,可以通过使 ...
- SQL Server 中关于 @@error 的一个小误区
在SQL Server中,我常常会看到有些前辈这样写: ) ROLLBACK TRANSACTION T else COMMIT TRANSACTION T 一开始,我看见别人这么写,我就想当然的以为 ...
- ASP.NET MVC 开发中遇到的两个小问题
最近在做一个网站,用asp.net MVC4.0来开发,今天遇到了两个小问题,通过查找相关渠道解决了,在这里把这两个问题写出来,问题非常简单,不喜勿喷,mark之希望可以给遇到相同问题的初学者一点帮助 ...
随机推荐
- Bootstrap网站模板
根据一篇文章,我再想想写下,无意义,他决定收手. 或者直接做一个简单的基本的模板它 主要知识点包含栅格系统.响应式图片.导航条(固定在顶部和底部).搜索框等等 详细每一个知识点不再赘述,參考Boots ...
- Sql SUBSTR函数
SUBSTR( ) 从一个字符表达式或备注字段中返回一个字符串.该字符串起始于字符表达式或备注字段的指定位置,到指定数目字符结束. 例如: SUBSTR(“A1”, 1 1]) 结果:A
- 《Javascript高级程序设计》读书笔记之继承
1.原型链继承 让构造函数的原型对象等于另一个类型的实例,利用原型让一个引用类型继承另一个引用类型的属性和方法 function SuperType() { this.property=true; } ...
- J2EE请求和响应—Servlet
一.什么是Servlet? Servlet是执行Webserver上的一个特殊Java类.其特殊用途是响应client请求并做出处理.使得client与server端进行交互. 二.生命周期 Ser ...
- jQuery插件之-瀑布流插件
jquery.wookmark.js 一个实现瀑布流自适应宽度布局的jQuery插件—jquery.wookmark.js , wookmark使用非常简单到只需要一句代码就能实现,除此之外,当页面宽 ...
- BackTrack5 (BT5)无线password破解教程WPA/WPA2-PSK无线password皴
昨天公布了BackTrack5 (BT5)无线weppassword破解教程之minidwep-gtk破解法一文,对BT5下破解wep无线password的简单方法做了介绍,今天奶牛为朋友们介绍下怎样 ...
- C# Out和Ref区别
rel是有进有出,out是只出不进 ref 要求参数在传递给函数前要初始化,out则不需要
- 【原创】纯OO:从设计到编码写一个FlappyBird (六)
第五部分请看这里 终于到了最后一个部分了! 这里使用SimpleJudge类来实现Judge接口. 首先是SimpleJudge需要的实例变量: 0.final LinkedList<Pilla ...
- 9、Cocos2dx 3.0游戏开发找小三之工厂方法模式与对象传值
重开发人员的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27704153 工厂方法模式 工厂方法是程序设计中一个 ...
- C# List使用District去重复数据
class ListDistinctDemo { static void Main(string[] args) { List<Person> personList = new List& ...