原文: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开发中容易忽视的一些小地方(四)的更多相关文章

  1. SQL开发中容易忽视的一些小地方(五)

    原文:SQL开发中容易忽视的一些小地方(五) 背景: 索引分类:众所周知,索引分为聚集索引和非聚集索引. 索引优点:加速数据查询. 问题:然而我们真的清楚索引的应用吗?你写的查询语句是否能充分应用上索 ...

  2. SQL开发中容易忽视的一些小地方(一)

    原文:SQL开发中容易忽视的一些小地方(一) 写此系列文章缘由: 做开发三年来(B/S),发现基于web 架构的项目技术主要分两大方面: 第一:C#,它是程序的基础,也可是其它开发语言,没有开发语言也 ...

  3. SQL开发中容易忽视的一些小地方(二)

    原文:SQL开发中容易忽视的一些小地方(二) 目的:继上一篇:SQL开发中容易忽视的一些小地方(一) 总结SQL中的null用法后,本文我将说说表联接查询. 为了说明问题,我创建了两个表,分别是学生信 ...

  4. SQL开发中容易忽视的一些小地方(六)

    原文:SQL开发中容易忽视的一些小地方(六) 本文主旨:条件列上的索引对数据库delete操作的影响. 事由:今天在博客园北京俱乐部MSN群中和网友讨论了关于索引对delete的影响问题,事后感觉非常 ...

  5. SQL开发中容易忽视的一些小地方( 三)

    原文:SQL开发中容易忽视的一些小地方( 三) 目的:这篇文章我想说说我在工作中关于in和union all 的用法. 索引定义 : 微软的SQL SERVER提供了两种索引:聚集索引(cluster ...

  6. ios开发——错误总结篇&开发中常见错误和警告总结(四)

    ios开发——开发总结&开发中常见错误和警告总结(四) 网易彩票实战总结(错误) 错误总结之类的实现 经典错误之重复定义与导入错误 经典错误关于父类的实现 通知对象: 控制器的定义 Xcode ...

  7. PL/SQL开发中动态SQL的使用方法

    一般的PL/SQL程序设计中,在DML和事务控制的语句中可以直接使用SQL,但是DDL语句及系统控制语句却不能在PL/SQL中直接使用,要想实现在PL/SQL中使用DDL语句及系统控制语句,可以通过使 ...

  8. SQL Server 中关于 @@error 的一个小误区

    在SQL Server中,我常常会看到有些前辈这样写: ) ROLLBACK TRANSACTION T else COMMIT TRANSACTION T 一开始,我看见别人这么写,我就想当然的以为 ...

  9. ASP.NET MVC 开发中遇到的两个小问题

    最近在做一个网站,用asp.net MVC4.0来开发,今天遇到了两个小问题,通过查找相关渠道解决了,在这里把这两个问题写出来,问题非常简单,不喜勿喷,mark之希望可以给遇到相同问题的初学者一点帮助 ...

随机推荐

  1. Hibernate 配置详解(11)

    hibernate.session_factory_name_is_jndi 配置hibernate.cfg.xml中SessionFactory的name属性是否作为JNDI名称绑定.默认是true ...

  2. 使用psftp.exe

    使用psftp.exe 点击打开psftp.exe,出现如下图的命令窗口.  

  3. 使用JavaMail发送和接收电子邮件

    一. 为什么要学习JavaMail 为什么要学习JavaMail开发? 如今非常多WEB应用在开发时都须要集成邮件发送功能.比如: 1. 给新注冊的用户自己主动发送一封包括其注冊信息的欢迎E-Mail ...

  4. activity点击时各种方法的区别

    用到不同方法时候某些系统有不太一样的情况: public class MainActivity extends Activity { private static String TAG = " ...

  5. 《实验数据的结构化程序设计》 2.4.4Calendar个人意见,寻求指引

    题目大意: 制作一个日历系统,输入年份.一些周年纪念日,及服务要求日期,依据要求日期输出,输出重要程度小于发生日期的周年纪念日. 题目地址: UVA  145 个人见解: 纯模拟,在闰年,输出顺序及输 ...

  6. WPF动态加载3D 放大-旋转-平移

    原文:WPF动态加载3D 放大-旋转-平移 WavefrontObjLoader.cs 第二步:ModelVisual3DWithName.cs public class ModelVisual3DW ...

  7. 【原创】leetCodeOj ---Partition List 解题报告

    原题地址: https://oj.leetcode.com/problems/partition-list/ 题目内容: Given a linked list and a value x, part ...

  8. HDoj-2084-号码塔-dp

    号码塔 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submis ...

  9. 使用Emacs muse制作幻灯片

    PPT太受欢迎.总是必要的交流会议.我看到一个很酷javascript实现,取代PPT. 不过还是很喜欢Emacs要做的事,即使文件难听点. 现在,用muse slidy, 一大区别. 简单的说mus ...

  10. 从头开始编写项目Makefile(八):型号规则

    [版权声明:转载请保留源:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com]     上创建的文件夹谈及.没有生产目标文件到相应的文件夹,在这里 ...