图片 37

索引的作用,Server中关于跟踪

前言

)深入浅出理解索引结构

写在前面

  记得在自己学习数据库知识的时候特别喜欢看案例,因为优化的手段容易掌握的,但是整体的优化思想很难学会的。这也是为什么自己特别喜欢看案例,今天也分享自己做的优化案例。

  之前分享过OA系统、HIS系统,今天我们来一个最常见的ERP,ERP系统各行各业都在用,不同行业也有不同的特点,博主在做研发的时候还自己写过ERP也算是比较熟悉了。

  不管是本文分享的零售类,还是鞋服门店、家居、汽车、地产等等,也不管是某友、某碟,ERP有一个共同的特点,单据流程长,业务复杂,热点表明显,数据量大,涉及众多系统接口,各种大数据的统计报表….传统行业又缺乏DBA精心管理。

  慢是普遍的!

  最近一直很忙,博客产出也少的可怜,今天整理了一下自己做过优化或各种方案的客户已经超过千家,涉及各行各业,今天分享的案例算是在这些客户中比较典型的了!没有什么高大上都是常见的问题!在之前的博客中都有过提及,那么本篇我们就结合之前的技术点来看看这个案例。学习优化手段的看官们可以参见我的优化系列:

 

一提到跟踪俩字,很多人想到警匪片中的场景,同样在我们的SQL
Server数据库中“跟踪”也是无处不在的,如果我们利用好了跟踪技巧,就可以针对某些特定的场景做定向分析,找出充足的证据来破案。

实际上,您可以把索引理解为一种特殊的目录。微软的SQL
SERVER提供了两种索引:聚集索引(clustered
index,也称聚类索引、簇集索引)和非聚集索引(nonclustered
index,也称非聚类索引、非簇集索引)。下面,我们举例来说明一下聚集索引和非聚集索引的区别:

SQL SERVER全面优化——-Expert for SQL Server 诊断系列

 

————–博客地址—————————————————————————————

Expert 诊断优化系列 

 

 

废话不多说,直接开整—————————————————————————————–

 

简单的举几个应用场景:

其实,我们的汉语字典的正文本身就是一个聚集索引。比如,我们要查“安”字,就会很自然地翻开字典的前几页,因为“安”的拼音是“an”,而按照拼音排序汉字的字典是以英文字母“a”开头并以“z”结尾的,那么“安”字就自然地排在字典的前部。如果您翻完了所有以“a”开头的部分仍然找不到这个字,那么就说明您的字典中没有这个字;同样的,如果查“张”字,那您也会将您的字典翻到最后部分,因为“张”的拼音是“zhang”。也就是说,字典的正文部分本身就是一个目录,您不需要再去查其他目录来找到您需要找的内容。我们把这种正文内容本身就是一种按照一定规则排列的目录称为“聚集索引”。

用户现象

  系统慢!保存个单据要好几分钟,很多操作都超时,尤其到下午4点左右各种超时,收款什么的都收不了,

  查个报表一个小时,下班了还没查完,经常因为系统慢而加班,

  业务部门已经怨声载道,这个事情已经上报公司高层IT部分压力非常大!

在线生产库为何突然宕机?数百张数据表为何不翼而飞?刚打好补丁的系统为何屡遭黑手?新添加的信息表为何频频丢失?某张表字段的突然更改,究竟为何人所为?这些个匿名的访问背后,究竟是人是鬼?突然增加的增量数据,究竟是对是错?数百兆的日志爆炸式的增长背后又隐藏着什么?这一且的背后,是应用程序的BUG还是用户品质的缺失?

如果您认识某个字,您可以快速地从自动中查到这个字。但您也可能会遇到您不认识的字,不知道它的发音,这时候,您就不能按照刚才的方法找到您要查的字,而需要去根据“偏旁部首”查到您要找的字,然后根据这个字后的页码直接翻到某页来找到您要找的字。但您结合“部首目录”和“检字表”而查到的字的排序并不是真正的正文的排序方法,比如您查“张”字,我们可以看到在查部首之后的检字表中“张”的页码是672页,检字表中“张”的上面是“驰”字,但页码却是63页,“张”的下面是“弩”字,页面是390页。很显然,这些字并不是真正的分别位于“张”字的上下方,现在您看到的连续的“驰、张、弩”三字实际上就是他们在非聚集索引中的排序,是字典正文中的字在非聚集索引中的映射。我们可以通过这种方式来找到您所需要的字,但它需要两个过程,先找到目录中的结果,然后再翻到您所需要的页码。我们把这种目录纯粹是目录,正文纯粹是正文的排序方式称为“非聚集索引”。

系统环境

  首先我们来看一下这个系统配置及现状,为什么说这个客户经典?往下看就知道了…

  

  先来看看系统配置 :

  

  图片 1

 

   服务器的配置是:8路 24 core 做了超线程
384个逻辑CPU,内存1T,磁盘全闪

   图片 2

     SQL用了2012版本,补丁已经最新,而且服务器配置全部能够识别

    没错。相当牛逼得配置!

  

     图片 3

  

  数据库的大小在1.2个T

 

  咋一看也许数据量太大了,导致性能的问题!可又一想这么强力的服务器也不至于那么慢呀,难道是代码的问题?难道需要分库分表?

请关注本篇文章,让我们一起利用数据库的“跟踪”(Trace)走进数据库背后,查看其内部原理。

通过以上例子,我们可以理解到什么是“聚集索引”和“非聚集索引”。进一步引申一下,我们可以很容易的理解:每个表只能有一个聚集索引,因为目录只能按照一种方法进行排序。

数据库指标

  那么我们再看一下数据库的一些表象:

  每秒请求数量:

  图片 4

  用户连接数:

  图片 5

 

 

  语句执行情况:

  图片 6

  图片 7

  

 

 

  等待情况:

  图片 8

 

  图片 9

 

  等待时间:

  图片 10

 

   CPU指标:

  图片 11

 

  内存一些指标:

  图片 12

 

  图片 13

 

 

  磁盘队列:

  图片 14

 

 

 ——————-还很多指标就不一一展示了——————

 

   看到这些基本的指标,除了慢你能看出什么?问题出在哪里?怎么样快速解决?能有一个优化的步骤呈现在眼前么?

 

 

二、何时使用聚集索引或非聚集索引

分析

  系统是真的很慢,慢语句数量很多系统阻塞也很严重,确实和客户反映的慢可以吻合。那为什么这么慢?什么原因导致的?

  我总结一般性能慢常和6大因素有关:

  1.   业务压力
  2.   硬件
  3.   环境
  4.   代码
  5.   数据库内部运行因素
  6.   架构

 

 奉上一幅草图

  图片 15

  系统压力:访问压力(也是我们常说的并发)其实并不大,用户连接数也没想像的那么多

  硬件:在内存和磁盘IO确实存在压力

  环境 :服务器和数据库版本什么的没什么问题,具体配置一会儿再看。

  代码 :最不想分析代码,我们留到最后

  数据库内部运行因素:从各种指标来分析,系统语句等待时间太长,导致语句完成慢,而等待主要有两部分:

  1.  硬件资源确实有压力
  2.  语句之前的阻塞太严重了,"LCK_M_",而且等待时间过长,竟然平均达到几百秒

  再分析…这么强的硬件,并不大的访问压力,竟然造成瓶颈?语句写的烂?程序实现的不好?缺索引?环境配置不对?

  下面我们来看看….

 

我相信如用过SQL Server数据库的人,都会或多或少的利用过SQL
Profiler工具。这个玩意就是利用SQL
Trace形成的一个图形化操作工具,我们直接进入本篇的正题。

下面的表总结了何时使用聚集索引或非聚集索引(很重要):

优化阶段一(常规优化)

  很多时候系统慢要究其原因,难道上线时候就这么慢?那不可能,厂商根本无法交付的!那么问题来了,什么时候开始慢的?对系统做过哪些调整?

  简单的调研开始…

  我靠!!!厂商完全不配合,工程师对系统及其不熟悉,一问三不知,最近做什么改动也说不清,用户也不知道。厂商给的结论:继续加硬件….更强的IO….数据分离减小数据量!

  协调厂商完全协调不动,基本没戏了!

  既然是数据库问题,那我们就数据库下手吧!从一名数据库从业人员来说,看到这样的系统一定要先解决大面积等待问题!个人经验来看很多系统大面积等待解决系统会有个很大的提升和改善!

  配合一些常规的调优手段阶段一开始了,主要给系统大面积创建影响高开销大的索引,调整系统参数,优化tempDB等….具体不细说了,前面系列文章中都有!

 

  预期:

  一般系统上面一轮优化会有明显的改善,我认为这一轮以后系统会明显变快,语句运行环境合适,索引什么的合理资源消耗自然就少,内存和IO压力也会有所减少。

  结果:

  系统内存,IO压力趋于平稳,慢语句数量有所减少,但依然很多,阻塞依然存在,超过2分钟的语句依然很多。

  

  优化前

  图片 16

 

  优化后

  图片 17

 

 

  优化前

  图片 9

  优化后

  图片 19

 

  

 

动作描述

使用聚集索引

使用非聚集索引

列经常被分组排序

返回某范围内的数据

不应

一个或极少不同值

不应

不应

小数目的不同值

不应

大数目的不同值

不应

频繁更新的列

不应

外键列

主键列

频繁修改索引列

不应

优化阶段二(针对语句)

   再次分析解决大面积语句阻塞的系统,发现现在的情况,主要有如下几个:

  1. 内存某些时候还是存在波动,但整体IO 内存已经不是瓶颈。
  2. 系统中有SLEEPING的程序阻塞时间长
  3. 部分功能语句依然慢,消耗的资源很高。

  再次对系统调研:

  1. 执行的慢语句是什么业务,是业务功能?还是报表?还是接口?
  2. 系统中频繁且较慢的语句。
  3. 系统中阻塞的操作是什么。  

  

  调研后,我遇到了最常见也是最大的问题:
语句慢由于程序!在HIS的优化案例中就是因为程序大量使用自定义函数,我们没法改,我们巧妙的绕过。那么这次我们如何绕过?

   

  一:报表

  分析中发现程序系统中消耗最多资源的主要是报表。

  报表通过一系列复杂的查询插入到物理临时表,啥叫物理临时表?
就是非#temp 而是真真正正的插入到表中,用完在delete!

  插入在删除,中间还有跟业务表关联操作,导致报表也会阻塞业务!

  插入删除的数据量是多少? 你们猜一下??

  千万级别….

  

  二:接口

  接口程序中频繁调用业务数据并发更新频繁….导致业务受阻…

 

  三:问题代码

  代码的问题主要有两个:

  1.代码较复杂,需要细致优化。

  2.程序中存在连接泄露,简单理解成程序报错后事务不能有效处理,导致事务未提交阻塞系统

  图片 20

 

  针对第一部分报表,语句更是复杂至极…这东西不是短期就可以优化的,考虑分出去

  针对第二部分接口,修改接口视图,包括写法优化、添加索引、调用频率等;

  针对第三部分业务语句进行细致优化,查询提示,计划向导、重编译等等手段…

  

  

一.查看系统默认跟踪信息(Default Trace)

事实上,我们可以通过前面聚集索引和非聚集索引的定义的例子来理解上表。如:返回某范围内的数据一项。比如您的某个表有一个时间列,恰好您把聚合索引建立在了该列,这时您查询2004年1月1日至2004年10月1日之间的全部数据时,这个速度就将是很快的,因为您的这本字典正文是按日期进行排序的,聚类索引只需要找到要检索的所有数据中的开头和结尾数据即可;而不像非聚集索引,必须先查到目录中查到每一项数据对应的页码,然后再根据页码查到具体内容。

优化阶段三(报表分离)

  经过前两个阶段的优化一般系都会明显好转,只剩报表没有处理,和一部分高消耗的频繁接口查询,这部分我们采用报表分离的方式去解决。

  这里面我们遇到一个问题,报表要写物理表!用2012
自带的AlwaysOn是没有办法实现的(辅助节点只能读)

  

  使用发布订阅,又不能同时满足数据安全和业务连续的要求,客户又不满意。

  

  我们想到是否可以把写入物理表变成写入#temp 临时表?
软件厂商给出的结论是:不可能….

  

     那这里面我们使用了第三方的产品Moebius集群(这里真的不是广告….)

 

  如何实现:  

  多活集群,几个节点数据实时一致,这样的基本知识就不普及了…集群介绍也免了

  首先程序只有一个连接字符串没法把报表指向到辅助服务器,我们只能通过Moebius集群的前端调度引擎,定制规则把报表所使用的存储过程定点指向到第二台服务器,解决了程序不能分离的问题。

  其次Moebius集群可以实现两个节点都可写,以满足辅助节点报表查询写入物理表的需要。

  再次临时表的写入量太大,千万级别数据同步也是问题,这里好就好在程序中写入的物理临时表都是以“Temp_”
开头并以GUID类型结尾。我们在这里设置了只要这样的表写入不会反向同步给主节点,这样根据规则控制双向同步满足了报表的要求,最终实现了报表的分离。

  报表快了? 当然没有,只是分离不可能快,但是好处有两个:

  1.   OLAP和OLTP分离事务阻塞得到解决
  2.   报表服务器和业务服务器可以根据自身的业务特别进行单独的个性化设置
  3.   根据报表的要求我们配置高速IO的硬件

 

  预期:

  语句已经优化,阻塞情况也被解决,CPU、内存、磁盘压力也没有了,系统肯定快起来了!

  结果:

  系统快起来了!

  

  最终业务系统节点全天24小时的慢语句数量:(虽然还有慢语句存在,毕竟是TB级别的数据量,不影响业务运行客户完全可以接受!)

  图片 21

 

————–博客地址—————————————————————————————

Expert 诊断优化系列 

 

 


 

  总结 : 系统慢往往我们要全面分析,本文提供的维度:

  1.   业务压力
  2.   硬件
  3.   环境
  4.   代码
  5.   数据库内部运行因素
  6.   架构

 

    往往优化真的不是简单的调一调语句,加一加硬件,全面地分析是根本解决性能问题的首要任务。

  当然不是所有的优化都可以彻底解决,如本文中报表的改善是通过读写分离的方式实现,很多时候在ERP系统中报表的处理方式都是如此,报表如果细致优化,那需要多长时间呀!也许都是重写了。

 

  本文的优化过程主要是:全面分析系统问题——〉宏观层面解决(环境、数据库内部运行因素、硬件压力)——〉低效代码调整——〉架构方案实现(稳定、安全、高效)——〉最终系统顺畅
无压力

 

  当然此案例中客户的数据量已经到了可以做数据分离,分区分表的阶段,但分享本案例的原因也在于,不要认为上TB的数据一定就要分库分表的各种拆分,在性能调优的简单付出中依然可以收获更大的收益,真心希望看官们在选择分库分表付出的极大代价之前可以找专业的人全面分析一下,仔细评估你的系统到底是什么瓶颈!

 

 

 —————————————————————————————————-

注:此文章为原创,欢迎转载,请在文章页面明显位置给出此文链接!
若您觉得这篇文章还不错请点击下右下角的推荐,非常感谢!

如果您也遇到类似问题欢迎添加微信技术交流

 图片 22

 

Trace作为一个很好的数据库追踪工具,在SQL Server
2005中便集成到系统功能中去,并且默认是开启的,当然我们也可以手动的关掉它,它位于sp_config配置参数中,我们可以通过以下语句查看:

三、结合实际,谈索引使用的误区

select * from sys.configurations where configuration_id = 1568

理论的目的是应用。虽然我们刚才列出了何时应使用聚集索引或非聚集索引,但在实践中以上规则却很容易被忽视或不能根据实际情况进行综合分析。下面我们将根据在实践中遇到的实际问题来谈一下索引使用的误区,以便于大家掌握索引建立的方法。

图片 23

1、主键就是聚集索引

我们也可以通过下面的语句找到这个跟踪的记录

这种想法笔者认为是极端错误的,是对聚集索引的一种浪费。虽然SQL
SERVER默认是在主键上建立聚集索引的。

select * from sys.traces

通常,我们会在每个表中都建立一个ID列,以区分每条数据,并且这个ID列是自动增大的,步长一般为1。我们的这个办公自动化的实例中的列Gid就是如此。此时,如果我们将这个列设为主键,SQL
SERVER会将此列默认为聚集索引。这样做有好处,就是可以让您的数据在数据库中按照ID进行物理排序,但笔者认为这样做意义不大。

图片 24

显而易见,聚集索引的优势是很明显的,而每个表中只能有一个聚集索引的规则,这使得聚集索引变得更加珍贵。

如果没有开启,我们也可以利用如下语句进行开启,或者关闭等操作

从我们前面谈到的聚集索引的定义我们可以看出,使用聚集索引的最大好处就是能够根据查询要求,迅速缩小查询范围,避免全表扫描。在实际应用中,因为ID号是自动生成的,我们并不知道每条记录的ID号,所以我们很难在实践中用ID号来进行查询。这就使让ID号这个主键作为聚集索引成为一种资源浪费。其次,让每个ID号都不同的字段作为聚集索引也不符合“大数目的不同值情况下不应建立聚合索引”规则;当然,这种情况只是针对用户经常修改记录内容,特别是索引项的时候会负作用,但对于查询速度并没有影响。

图片 25

在办公自动化系统中,无论是系统首页显示的需要用户签收的文件、会议还是用户进行文件查询等任何情况下进行数据查询都离不开字段的是“日期”还有用户本身的“用户名”。

--开启Default Trace
sp_configure 'show advanced options' , 1 ;
GO
RECONFIGURE;
GO
sp_configure 'default trace enabled' , 1 ;
GO
RECONFIGURE;
GO

--测试是否开启
EXEC sp_configure 'default trace enabled';
GO

--关闭Default Trace
sp_configure 'default trace enabled' , 0 ;
GO
RECONFIGURE;
GO
sp_configure 'show advanced options' , 0 ;
GO
RECONFIGURE;
GO

通常,办公自动化的首页会显示每个用户尚未签收的文件或会议。虽然我们的where语句可以仅仅限制当前用户尚未签收的情况,但如果您的系统已建立了很长时间,并且数据量很大,那么,每次每个用户打开首页的时候都进行一次全表扫描,这样做意义是不大的,绝大多数的用户1个月前的文件都已经浏览过了,这样做只能徒增数据库的开销而已。事实上,我们完全可以让用户打开系统首页时,数据库仅仅查询这个用户近3个月来未阅览的文件,通过“日期”这个字段来限制表扫描,提高查询速度。如果您的办公自动化系统已经建立的2年,那么您的首页显示速度理论上将是原来速度8倍,甚至更快。

图片 26

在这里之所以提到“理论上”三字,是因为如果您的聚集索引还是盲目地建在ID这个主键上时,您的查询速度是没有这么高的,即使您在“日期”这个字段上建立的索引(非聚合索引)。下面我们就来看一下在1000万条数据量的情况下各种查询的速度表现(3个月内的数据为25万条):

通过以下命令找到默认跟踪的文件路径

(1)仅在主键上建立聚集索引,并且不划分时间段:

select * from ::fn_trace_getinfo(0)

1.Select gid,fariqi,neibuyonghu,title from tgongwen

图片 27

用时:128470毫秒(即:128秒)

以上命令返回的结果值,各个值(property)代表的含义如下:

(2)在主键上建立聚集索引,在fariq上建立非聚集索引:

第一个:2表示滚动文件;

1.select gid,fariqi,neibuyonghu,title from Tgongwen

第二个:表示当前使用的trace文件路径,根据它我们可以找到其它的跟踪文件,默认是同一目录下

2.where fariqi> dateadd(day,-90,getdate())

第三个:表示滚动文件的大小(单位MB),当到达这个值就会创建新的滚动文件

用时:53763毫秒(54秒)

第四个:跟踪的停止时间,这里为Null,表示没有固定的停止时间

(3)将聚合索引建立在日期列(fariqi)上:

第五个:当前跟踪的状态:0 停止;1 运行

1.select gid,fariqi,neibuyonghu,title from Tgongwen

 

2.where fariqi> dateadd(day,-90,getdate())

找到该目录,我们查看下该文件:

用时:2423毫秒(2秒)

图片 28

虽然每条语句提取出来的都是25万条数据,各种情况的差异却是巨大的,特别是将聚集索引建立在日期列时的差异。事实上,如果您的数据库真的有1000万容量的话,把主键建立在ID列上,就像以上的第1、2种情况,在网页上的表现就是超时,根本就无法显示。这也是我摒弃ID列作为聚集索引的一个最重要的因素。得出以上速度的方法是:在各个select语句前加:

系统默认提供5个跟踪文件,并且每一个文件默认大小都是20MB,SQL
Server会自己维护这5个文件,当实例重启的时候或者到达最大值的时候,之后会重新生成新的文件,将最早的跟踪文件删除,依次滚动更新。

1.declare @d datetime

 

2.set @d=getdate()

我们通过以下命令来查看跟踪文件中的内容:

并在select语句后加:

图片 29

1.select [语句执行花费时间(毫秒)]=datediff(ms,@d,getdate())

 默认的跟踪文件,提供的跟踪信息还是很全的,从中我们可以找到登录人,操作信息等,上面的截图只是包含的部分信息。我们可以利用该语句进行自己的加工,然后获得更有用的信息。

2、只要建立索引就能显著提高查询速度

图片 30

事实上,我们可以发现上面的例子中,第2、3条语句完全相同,且建立索引的字段也相同;不同的仅是前者在fariqi字段上建立的是非聚合索引,后者在此字段上建立的是聚合索引,但查询速度却有着天壤之别。所以,并非是在任何字段上简单地建立索引就能提高查询速度。

--获取跟踪文件中前100行执行内容
SELECT TOP 100
 gt.[HostName] 
,gt.[ServerName] 
,gt.[DatabaseName] 
,gt.[SPID] 
,gt.[ObjectName] 
,gt.[objecttype] [ObjectTypeID] 
,sv.[subclass_name] [ObjectType] 
,e.[category_id] [CategoryID] 
,c.[Name] [Category] 
,gt.[EventClass] [EventID] 
,e.[Name] [EventName] 
,gt.[LoginName] 
,gt.[ApplicationName] 
,gt.[StartTime] 
,gt.[TextData] 
FROM fn_trace_gettable('E:\dataDefaultFileManger\MSSQL10.MSSQLSERVER\MSSQL\Log\log_1267.trc', DEFAULT) gt 
LEFT JOIN sys.trace_subclass_values sv 
ON gt.[eventclass] = sv.[trace_event_id] AND sv.[subclass_value] = gt.[objecttype] 
INNER JOIN sys.trace_events e 
ON gt.[eventclass] = e.[trace_event_id] 
INNER JOIN sys.trace_categories c 
ON e.[category_id] = c.[category_id] 
WHERE gt.[spid] > 50 AND --50以内的spid为系统使用
    gt.[DatabaseName] = 'master' AND --根据DatabaseName过滤
    gt.[ObjectName] = 'fn_trace_getinfo' AND --根据objectname过滤
    e.[category_id]  = 5 AND --category 5表示对象,8表示安全
    e.[trace_event_id] = 46 
    --trace_event_id 
    --46表示Create对象(Object:Created),
    --47表示Drop对象(Object:Deleted),
    --93表示日志文件自动增长(Log File Auto Grow),
    --164表示Alter对象(Object:Altered),
    --20表示错误日志(Audit Login Failed)
ORDER BY [StartTime] DESC

从建表的语句中,我们可以看到这个有着1000万数据的表中fariqi字段有5003个不同记录。在此字段上建立聚合索引是再合适不过了。在现实中,我们每天都会发几个文件,这几个文件的发文日期就相同,这完全符合建立聚集索引要求的:“既不能绝大多数都相同,又不能只有极少数相同”的规则。由此看来,我们建立“适当”的聚合索引对于我们提高查询速度是非常重要的。

图片 31

3、把所有需要提高查询速度的字段都加进聚集索引,以提高查询速度

图片 32

上面已经谈到:在进行数据查询时都离不开字段的是“日期”还有用户本身的“用户名”。既然这两个字段都是如此的重要,我们可以把他们合并起来,建立一个复合索引(compound
index)。

 我创建了一张表,通过上面的跟踪,可以跟踪到该记录的信息,根据不同的过滤信息,我们可以查询出到跟踪的某个库的某个表的更改信息,包括:46创建(Created)、47删除(Deleted)、93文件自动增长信息(Log
File Auto Grow)、146修改(Alter)、20表示错误日志(Login Failed)

很多人认为只要把任何字段加进聚集索引,就能提高查询速度,也有人感到迷惑:如果把复合的聚集索引字段分开查询,那么查询速度会减慢吗?带着这个问题,我们来看一下以下的查询速度(结果集都是25万条数据):(日期列fariqi首先排在复合聚集索引的起始列,用户名neibuyonghu排在后列):

 

1.(1)select gid,fariqi,neibuyonghu,title from Tgongwen where
fariqi>”2004-5-5”

在生产环境中,以上几个分类都是比较常用的,对定位部分问题的定位能够在找到充分的证据可循,比如某厮将数据库数据删除掉了还不承认等,这里面的Login
Failed信息,能够追踪出有那么用户尝试登陆过数据库,并且失败,如果大面积的出现这种情况,那就要谨防黑客袭击了。

查询速度:2513毫秒

 

1.(2)select gid,fariqi,neibuyonghu,title from Tgongwen where
fariqi>”2004-5-5” and neibuyonghu=”办公室”

当然,这里我还可以利用SQL
Server自带的Profile工具,打开查看跟踪文件中的内容。

查询速度:2516毫秒

图片 33

1.(3)select gid,fariqi,neibuyonghu,title from Tgongwen where
neibuyonghu=”办公室”

这个图像化的工具就比较熟悉了,直接打开进行筛选就可以了。

查询速度:60280毫秒

这种方式看似不错,但是它也有本身的缺点,我们来看:

从以上试验中,我们可以看到如果仅用聚集索引的起始列作为查询条件和同时用到复合聚集索引的全部列的查询速度是几乎一样的,甚至比用上全部的复合索引列还要略快(在查询结果集数目一样的情况下);而如果仅用复合聚集索引的非起始列作为查询条件的话,这个索引是不起任何作用的。当然,语句1、2的查询速度一样是因为查询的条目数一样,如果复合索引的所有列都用上,而且查询结果少的话,这样就会形成“索引覆盖”,因而性能可以达到最优。同时,请记住:无论您是否经常使用聚合索引的其他列,但其前导列一定要是使用最频繁的列。

1、这5个文件是滚动更新的,而且每个文件默认最大都为20MB,并且没有提供更改的接口,所以当文件填充完之后就会删除掉,所以会找不到太久以前的内容;

四、其他书上没有的索引使用经验总结

2、本身默认的跟踪,只是提供一些关键信息的追踪,其中包括:auditing
events,database events,error events,full text events,object
creation,object deletion,object
alteration,想要找到其它更详细的内容,此方式可能无能为力;

1、用聚合索引比用不是聚合索引的主键速度快

3、在SQL Server2012后续版本的 Microsoft SQL Server
将删除该功能,改用扩展事件。

下面是实例语句:(都是提取25万条数据)

 

1.select gid,fariqi,neibuyonghu,reader,title from Tgongwen where
fariqi=”2004-9-16”

二.自定义跟踪信息(Default Trace)

使用时间:3326毫秒

根据上面SQL Server自带的跟踪信息有一些局限性,SQL
Server为我们提供了自定义跟踪的接口,我们可以自己定义跟踪,充分扩展方法。

1.select gid,fariqi,neibuyonghu,reader,title from Tgongwen where
gid<=250000

利用如下系统存储过程,我们可以创建自定义的Trace

使用时间:4470毫秒

sp_trace_create [ @traceid = ] trace_id OUTPUT 
          , [ @options = ] option_value  
          , [ @tracefile = ] 'trace_file' 
     [ , [ @maxfilesize = ] max_file_size ]
     [ , [ @stoptime = ] 'stop_time' ]
     [ , [ @filecount = ] 'max_rollover_files' ]

这里,用聚合索引比用不是聚合索引的主键速度快了近1/4。

@traceid  系统默认分配跟踪的ID号

2、用聚合索引比用一般的主键作order by时速度快,特别是在小数据量情况下

@options 指定为跟踪设置的选项,系统默认提供的几个选项:

1.select gid,fariqi,neibuyonghu,reader,title from Tgongwen order by
fariqi

                  2表示当文件写满的时候,关闭当前跟踪并创建新文件。

用时:12936

                  4表示如果不能将跟踪写入文件,不管什么原因导致,SQL
Server则会关闭。这个可以利用此选项,追踪问题

1.select gid,fariqi,neibuyonghu,reader,title from Tgongwen order by gid

                  8制定服务器产生的最后5MB的跟踪信息记录由服务器保存。

用时:18843

@tracefile 跟踪文件的路径,这里可以是share的路径

这里,用聚合索引比用一般的主键作order
by时,速度快了3/10。事实上,如果数据量很小的话,用聚集索引作为排序列要比使用非聚集索引速度快得明显的多;而数据量如果很大的话,如10万以上,则二者的速度差别不明显。

@maxfilesize 跟踪文件的大小,单位是MB,默认不设置为5MB

3、使用聚合索引内的时间段,搜索时间会按数据占整个数据表的百分比成比例减少,而无论聚合索引使用了多少个:

@stoptime 跟踪停止的时间,利用它我们可以定时跟踪结束的日期

1.select gid,fariqi,neibuyonghu,reader,title from Tgongwen where
fariqi>”2004-1-1”

@filecount 默认生产的跟踪文件的数量,比如默认的为5个,那就在第5个文件写完的时候进行覆盖第1个文件滚动

用时:6343毫秒(提取100万条)

 

1.select gid,fariqi,neibuyonghu,reader,title from Tgongwen where
fariqi>”2004-6-6”

比如我们可以利用如下脚本进行创建 

用时:3170毫秒(提取50万条)

图片 34

1.select gid,fariqi,neibuyonghu,reader,title from Tgongwen where
fariqi=”2004-9-16”

--创建跟踪文件返回值
declare @rc int
--创建一个跟踪句柄
declare @TraceID int
--创建跟踪文件路径
declare @TraceFilePath nvarchar(500)
set @TraceFilePath=N'F:\SQLTest\'
--跟踪文件的大小
declare @maxfilesize bigint
set @maxfilesize=5
--设置停止的时间
declare @EndTime datetime
set @EndTime=null
--设置系统默认的操作
declare @options int
set @options=2
--设置默认滚动文件的数目
declare @filecount int
set @filecount=5

exec @rc=sp_trace_Create
@TraceID output,
@options,
@TraceFilePath,
@maxfilesize,
@EndTime,
@filecount
if(@rc=0)
select  @TraceID

用时:3326毫秒(和上句的结果一模一样。如果采集的数量一样,那么用大于号和等于号是一样的)

图片 35

1.select gid,fariqi,neibuyonghu,reader,title from Tgongwen where
fariqi>”2004-1-1” and fariqi<”2004-6-6”

我们通过上面的跟踪创建的过程,可以在系统自带的默认的sys.traces中找到该跟踪的明细
图片 36

用时:3280毫秒

select * from sys.traces
where id=2

4、日期列不会因为有分秒的输入而减慢查询速度

图片 37

下面的例子中,共有100万条数据,2004年1月1日以后的数据有50万条,但只有两个不同的日期,日期精确到日;之前有数据50万条,有5000个不同的日期,日期精确到秒。

通过上面的脚本,我们已经创建了一个新的跟踪(trace),但是这个跟踪状态为0,也就是说还没有运行,下面我们的步骤就是要为这个跟踪添加事件(event)

1.select gid,fariqi,neibuyonghu,reader,title from Tgongwen where
fariqi>”2004-1-1” order by fariqi

 

用时:6390毫秒

这个也是利用SQL Server为我们提供的操作函数

1.select gid,fariqi,neibuyonghu,reader,title from Tgongwen where
fariqi<”2004-1-1” order by fariqi

sp_trace_setevent [ @traceid = ] trace_id  
          , [ @eventid = ] event_id 
          , [ @columnid = ] column_id 
          , [ @on = ] on

用时:6453毫秒

@traceid 要修改的跟踪的 ID号

五、其他注意事项

@eventid 要打开的事件的 ID

“水可载舟,亦可覆舟”,索引也一样。索引有助于提高检索性能,但过多或不当的索引也会导致系统低效。因为用户在表中每加进一个索引,数据库就要做更多的工作。过多的索引甚至会导致索引碎片。

@columnid 要为该事件添加的列的 ID

所以说,我们要建立一个“适当”的索引体系,特别是对聚合索引的创建,更应精益求精,以使您的数据库能得到高性能的发挥。

@on 表示事件状态

当然,在实践中,作为一个尽职的数据库管理员,您还要多测试一些方案,找出哪种方案效率最高、最为有效。

其中最主要的就是时间ID,这个是SQL
Server为我们提供的一些列的码表时间值,具体值可以参考联机丛书 sp_trace_setevent
(Transact-SQL).aspx)

(二)改善SQL语句

这里面最常用的就是:

很多人不知道SQL语句在SQL
SERVER中是如何执行的,他们担心自己所写的SQL语句会被SQL
SERVER误解。比如:

事件号

事件名称

说明

10                 

RPC:Completed

在完成了远程过程调用 (RPC) 时发生。

11

RPC:Starting

在启动了 RPC 时发生。

12

SQL:BatchCompleted

在完成了 Transact-SQL 批处理时发生。

13

SQL:BatchStarting

在启动了 Transact-SQL 批处理时发生。

14

Audit Login

在用户成功登录到 SQL Server 时发生。

15

Audit Logout

在用户从 SQL Server 注销时发生。

16

Attention

在发生需要关注的事件(如客户端中断请求或客户端连接中断)时发生。

17

ExistingConnection

检测在启动跟踪前连接到 SQL Server 的用户的所有活动。

18

Audit Server Starts and Stops

在修改 SQL Server 服务状态时发生。

20

Audit Login Failed

指示试图从客户端登录到 SQL Server 失败。

21

EventLog

指示已将事件记录到 Windows 应用程序日志中。

22

ErrorLog

指示已将错误事件记录到 SQL Server 错误日志中。

23

Lock:Released

指示已释放某个资源(如页)的锁。

24

Lock:Acquired

指示获取了某个资源(如数据页)的锁。

25

Lock:Deadlock

指示两个并发事务由于试图获得对方事务拥有的资源的不兼容锁而发生了相互死锁。

26

Lock:Cancel

指示已取消获取资源锁(例如,由于死锁)。

27

Lock:Timeout

指示由于其他事务持有所需资源的阻塞锁而使对资源(例如页)锁的请求超时。 超时由 @@LOCK_TIMEOUT 函数确定,并可用 SET LOCK_TIMEOUT 语句设置。

28

Degree of Parallelism Event(7.0 插入)

在执行 SELECT、INSERT 或 UPDATE 语句之前发生。

33

Exception

指示 SQL Server 中出现了异常。

34

SP:CacheMiss

指示未在过程缓存中找到某个存储过程。

35

SP:CacheInsert

指示某个项被插入到过程缓存中。

36

SP:CacheRemove

指示从过程缓存中删除了某个项。

37

SP:Recompile

指示已重新编译存储过程。

38

SP:CacheHit

指示在过程缓存中找到了存储过程。

40

SQL:StmtStarting

在启动了 Transact-SQL 语句时发生。

41

SQL:StmtCompleted

在完成了 Transact-SQL 语句时发生。

42

SP:Starting

指示启动了存储过程。

43

SP:Completed

指示完成了存储过程。

44

SP:StmtStarting

指示已开始执行存储过程中的 Transact-SQL 语句。

45

SP:StmtCompleted

指示存储过程中的 Transact-SQL 语句已执行完毕。

46

Object:Created

指示 CREATE INDEX、CREATE TABLE 和 CREATE DATABASE 这样的语句已创建了一个对象。

47

Object:Deleted

指示已在 DROP INDEX 和 DROP TABLE 这样的语句中删除了对象。

50

SQL Transaction

跟踪 Transact-SQL BEGIN、COMMIT、SAVE 和 ROLLBACK TRANSACTION 语句。

51

Scan:Started

指示启动了表或索引扫描

52

Scan:Stopped

指示停止了表或索引扫描。

53

CursorOpen

指示 ODBC、OLE DB 或 DB-Library 在 Transact-SQL 语句中打开了一个游标。

54

TransactionLog

将事务写入事务日志时进行跟踪。

55

Hash Warning

指示未在缓冲分区进行的某一哈希操作(例如,哈希联接、哈希聚合、哈希 union 运算、哈希非重复)已恢复为替换计划。 发生此事件的原因可能是递归深度、数据扭曲、跟踪标记或位计数。

58

Auto Stats

指示发生了自动更新索引统计信息。

59

Lock:Deadlock Chain

为导致死锁的每个事件而生成。

60

Lock:Escalation

指示较细粒度的锁转换成了较粗粒度的锁(例如,页锁升级或转换为 TABLE 或 HoBT 锁)。

61

OLE DB Errors

指示发生了 OLE DB 错误。

67

Execution Warnings

指示在执行 SQL Server 语句或存储过程期间发生的任何警告。

68

Showplan Text (Unencoded)

显示所执行 Transact-SQL 语句的计划树。

69

Sort Warnings

指示不适合内存的排序操作。 不包括与创建索引有关的排序操作;只包括某查询内的排序操作(如 SELECT 语句中使用的 ORDER BY 子句)。

70

CursorPrepare

指示已准备了 ODBC、OLE DB 或 DB-Library 用于 Transact-SQL 语句的游标。

71

Prepare SQL

ODBC、OLE DB 或 DB-Library 已准备好了一个或多个要使用的 Transact-SQL 语句。

72

Exec Prepared SQL

ODBC、OLE DB 或 DB-Library 已执行了一个或多个准备好的 Transact-SQL 语句。

73

Unprepare SQL

ODBC、OLE DB 或 DB-Library 已撤消(删除)了一个或多个准备好的 Transact-SQL 语句。

74

CursorExecute

执行了先前由 ODBC、OLE DB 或 DB-Library 为 Transact-SQL 语句准备的游标。

75

CursorRecompile

由 ODBC 或 DB-Library 为 Transact-SQL 语句打开的游标已直接重新编译或由于架构更改而重新编译。

为 ANSI 和非 ANSI 游标触发。

76

CursorImplicitConversion

SQL Server 将 Transact-SQL 语句的游标从一种类型转换为另一种类型。

为 ANSI 和非 ANSI 游标触发。

77

CursorUnprepare

ODBC、OLE DB 或 DB-Library 撤消(删除)了准备好的 Transact-SQL 语句的游标。

78

CursorClose

关闭了先前由 ODBC、OLE DB 或 DB-Library 为 Transact-SQL 语句打开的游标。

79

Missing Column Statistics

可能曾经对优化器有用的列统计信息不可用。

80

Missing Join Predicate

正在执行没有联接谓词的查询。 这可能导致长时间运行查询。

81

Server Memory Change

SQL Server 内存的使用量已增加或减少了 1 MB 或最大服务器内存的 5%(两者中较大者)。

82-91

User Configurable (0-9)

用户定义的事件数据。

92

Data File Auto Grow

指示服务器已自动扩展了数据文件。

93

Log File Auto Grow

指示服务器已自动扩展了日志文件。

94

Data File Auto Shrink

指示服务器已自动收缩了数据文件。

95

Log File Auto Shrink

指示服务器已自动收缩了日志文件。

96

Showplan Text

显示来自查询优化器的 SQL 语句的查询计划树。 请注意,TextData 列不包含此事件的显示计划。

97

Showplan All

显示查询计划,并显示已执行的 SQL 语句的完整编译时详细信息。 请注意,TextData 列不包含此事件的显示计划。

98

Showplan Statistics Profile

显示查询计划,并显示已执行的 SQL 语句的完整运行时详细信息。 请注意,TextData 列不包含此事件的显示计划。

100

RPC Output Parameter

生成每个 RPC 的参数的输出值。

108

Audit Add Login to Server Role Event

在从固定服务器角色添加或删除登录时发生;针对 sp_addsrvrolemember 和 sp_dropsrvrolemember。

112

Audit App Role Change Password Event

在更改应用程序角色的密码时发生。

113

Audit Statement Permission Event

在使用语句权限(如 CREATE TABLE)时发生。

114

Audit Schema Object Access Event

在成功或未成功使用了对象权限(如 SELECT)时发生。

115

Audit Backup/Restore Event

在发出 BACKUP 或 RESTORE 命令时发生。

116

Audit DBCC Event

在发出 DBCC 命令时发生。

117

Audit Change Audit Event

在修改审核跟踪时发生。

118

Audit Object Derived Permission Event

在发出 CREATE、ALTER 和 DROP 对象命令时发生。

119

OLEDB Call Event

为分布式查询和远程存储过程调用 OLE DB 访问接口时发生。

120

OLEDB QueryInterface Event

为分布式查询和远程存储过程调用 OLE DB QueryInterface 时发生。

121

OLEDB DataRead Event

对 OLE DB 访问接口调用数据请求时发生。

122

Showplan XML

在执行 SQL 语句时发生。 包括该事件可以标识 Showplan 运算符。 每个事件都存储在格式正确的 XML 文档中。 请注意,此事件的 Binary 列包含已编码的显示计划。 使用 SQL Server Profiler 可打开跟踪并查看显示计划。

123

SQL:FullTextQuery

执行全文查询时发生。

124

Broker:Conversation

报告 Service Broker 会话的进度。

125

Deprecation Announcement

使用将从 SQL Server 的未来版本中删除的功能时发生。

126

Deprecation Final Support

使用将从 SQL Server 的下一个主版本中删除的功能时发生。

127

Exchange Spill Event

在 tempdb 数据库临时写入并行查询计划中的通信缓冲区时发生。

128

Audit Database Management Event

创建、更改或删除数据库时发生。

129

Audit Database Object Management Event

对数据库对象(如架构)执行 CREATE、ALTER 或 DROP 语句时发生。

130

Audit Database Principal Management Event

创建、更改或删除数据库的主体(如用户)时发生。

131

Audit Schema Object Management Event

创建、更改或删除服务器对象时发生。

132

Audit Server Principal Impersonation Event

服务器范围中发生模拟(如 EXECUTE AS LOGIN)时发生。

133

Audit Database Principal Impersonation Event

数据库范围中发生模拟(如 EXECUTE AS USER 或 SETUSER)时发生。

134

Audit Server Object Take Ownership Event

服务器范围中的对象的所有者发生更改时发生。

135

Audit Database Object Take Ownership Event

数据库范围中的对象的所有者发生更改时发生。

136

Broker:Conversation Group

Service Broker 创建新的会话组或删除现有会话组时发生。

137

Blocked Process Report

进程被阻塞的时间超过了指定的时间时发生。 不包括系统进程或正在等待未发现死锁的资源的进程。 请使用 sp_configure 来配置生成报表时的阈值和频率。

138

Broker:Connection

报告 Service Broker 管理的传输连接的状态。

139

Broker:Forwarded Message Sent

Service Broker 转发消息时发生。

140

Broker:Forwarded Message Dropped

Service Broker 删除用于转发的消息时发生。

141

Broker:Message Classify

Service Broker 确定消息的路由时发生。

142

Broker:Transmission

指示在 Service Broker 传输层中发生了错误。 错误号和状态值指示了错误源。

143

Broker:Queue Disabled

指示检测到有害消息,这是由于在 Service Broker 队列中有五个连续的事务回滚。 该事件包含数据库 ID 和包含有害消息的队列的队列 ID。

146

Showplan XML Statistics Profile

在执行 SQL 语句时发生。 标识 Showplan 运算符,并显示完整的编译时数据。 请注意,此事件的 Binary 列包含已编码的显示计划。 使用 SQL Server Profiler 可打开跟踪并查看显示计划。

148

Deadlock Graph

取消获取锁的尝试时发生,这是因为该尝试是死锁的一部分,并且被选为死锁牺牲品。 提供死锁的 XML 说明。

149

Broker:Remote Message Acknowledgement

Service Broker 发送或收到消息确认时发生。

150

Trace File Close

跟踪文件在回滚期间关闭时发生。

152

Audit Change Database Owner

使用 ALTER AUTHORIZATION 更改数据库的所有者,并且检查执行该操作的权限时发生。

153

Audit Schema Object Take Ownership Event

使用 ALTER AUTHORIZATION 来将所有者分配给对象,并且检查执行该操作的权限时发生。

155

FT:Crawl Started

全文爬网(填充)开始时发生。 用于检查工作线程任务是否拾取了爬网请求。

156

FT:Crawl Stopped

全文爬网(填充)停止时发生。 爬网成功完成或发生错误时停止。

157

FT:Crawl Aborted

在全文爬网过程中遇到异常时发生。 通常导致全文爬网停止。

158

Audit Broker Conversation

报告与 Service Broker 对话安全性相关的审核消息。

159

Audit Broker Login

报告与 Service Broker 传输安全性相关的审核消息。

160

Broker:Message Undeliverable

Service Broker 无法保留收到的消息时发生,该消息应当已传递给某个服务。

161

Broker:Corrupted Message

Service Broker 收到损坏的消息时发生。

162

User Error Message

显示出现错误或异常时用户看到的错误消息。

163

Broker:Activation

队列监视器启动激活存储过程时,发送 QUEUE_ACTIVATION 通知时,或者队列监视器启动的激活存储过程退出时发生。

164

Object:Altered

数据库对象更改时发生。

165

Performance statistics

将经过编译的查询计划第一次缓存、重新编译或从计划缓存中删除时发生。

166

SQL:StmtRecompile

发生语句级别的重新编译时发生。

167

Database Mirroring State Change

镜像数据库的状态更改时发生。

168

Showplan XML For Query Compile

编译 SQL 语句时发生。 显示完整的编译时数据。 请注意,此事件的 Binary 列包含已编码的显示计划。 使用 SQL Server Profiler 可打开跟踪并查看显示计划。

169

Showplan All For Query Compile

编译 SQL 语句时发生。 显示完整的编译时数据。 用于标识 Showplan 运算符。

170

Audit Server Scope GDR Event

指示在服务器范围中发生了权限的授予、拒绝或撤消事件(如创建登录)。

171

Audit Server Object GDR Event

指示发生了对架构对象(如表或函数)的授予、拒绝或撤消事件。

172

Audit Database Object GDR Event

指示发生了对数据库对象(如程序集和架构)的授予、拒绝或撤消事件。

173

Audit Server Operation Event

使用了安全审核操作(如使用了更改设置、资源、外部访问或授权)时发生。

175

Audit Server Alter Trace Event

检查语句的 ALTER TRACE 权限时发生。

176

Audit Server Object Management Event

创建、更改或删除服务器对象时发生。

177

Audit Server Principal Management Event

创建、更改或删除了服务器主体时发生。

178

Audit Database Operation Event

发生数据库操作(如检查或订阅查询通知)时发生。

180

Audit Database Object Access Event

访问数据库对象(如架构)时发生。

181

TM: Begin Tran starting

BEGIN TRANSACTION 请求开始时发生。

182

TM: Begin Tran completed

BEGIN TRANSACTION 请求完成时发生。

183

TM: Promote Tran starting

PROMOTE TRANSACTION 请求开始时发生。

184

TM: Promote Tran completed

PROMOTE TRANSACTION 请求完成时发生。

185

TM: Commit Tran starting

COMMIT TRANSACTION 请求开始时发生。

186

TM: Commit Tran completed

COMMIT TRANSACTION 请求完成时发生。

187

TM: Rollback Tran starting

ROLLBACK TRANSACTION 请求开始时发生。

188

TM: Rollback Tran completed

ROLLBACK TRANSACTION 请求完成时发生。

189

Lock:Timeout (timeout > 0)

对资源(如页)的锁请求超时时发生。

190

Progress Report: Online Index Operation

报告生成进程正在运行时,联机索引生成操作的进度。

191

TM: Save Tran starting

SAVE TRANSACTION 请求开始时发生。

192

TM: Save Tran completed

SAVE TRANSACTION 请求完成时发生。

193

Background Job Error

后台作业不正常终止时发生。

194

OLEDB Provider Information

分布式查询运行并收集对应于提供程序连接的信息时发生。

195

Mount Tape

收到磁带装入请求时发生。

196

Assembly Load

发生加载 CLR 程序集的请求时发生。

198

XQuery Static Type

执行 XQuery 表达式时发生。 此事件类提供静态类型的 XQuery 表达式。

199

QN: subscription

无法订阅查询注册时发生。 TextData 列包含事件的有关信息。

200

QN: parameter table

有关活动订阅的信息存储在内部参数表中。 在创建或删除参数表时发生该事件类。 通常,重新启动数据库时将创建或删除这些表。 TextData 列包含事件的有关信息。

201

QN: template

查询模板代表订阅查询的类。 通常,除参数值以外,相同类中的查询是相同的。 当新的订阅请求针对已存在的类 (Match)、新类 (Create) 或 Drop 类(指示清除没有活动订阅的查询类的模板)时,发生此事件类。 TextData 列包含事件的有关信息。

202

QN: dynamics

跟踪查询通知的内部活动。 TextData 列包含事件的有关信息。

213

Database Suspect Data Page

指示何时将某页添加到 msdb 的 suspect_pages 表。

214

CPU threshold exceeded

指示资源调控器检测到查询超过 CPU 阈值 (REQUEST_MAX_CPU_TIME_SEC) 的时间。

215

指示 LOGON 触发器或资源调控器分类器函数开始执行的时间。

指示 LOGON 触发器或资源调控器分类器函数开始执行的时间。

216

PreConnect:Completed

指示 LOGON 触发器或资源调控器分类器函数完成执行的时间。

217

Plan Guide Successful

指示 SQL Server 已成功为计划指南中包含的查询或批处理生成执行计划。

218

Plan Guide Unsuccessful

指示 SQL Server 无法为包含计划指南的查询或批处理生成执行计划。 SQL Server 尝试在不应用计划指南的情况下为此查询或批处理生成执行计划。 无效的计划指南可能是导致此问题的原因。 您可以通过使用 sys.fn_validate_plan_guide 系统函数验证该计划指南。

1.select * from table1 where name=”zhangsan” and tID >
10000和执行select * from table1 where tID > 10000 and
name=”zhangsan”

发表评论

电子邮件地址不会被公开。 必填项已用*标注

标签:
网站地图xml地图