sql server建表语句 2005 查询语句的简单问题 看看下面的语法哪里错了?尽量不要改动太多。。

对于SQL Server的优化来说,优化查询可能是很常见的工作。因为数据库的优化,本身也是一个涉及面对照的广的话题,是以本文只谈优化查询时如何看懂SQL Server查询设计。事实我对SQL Server的熟悉有限,如有错误,也恳请您在发现后适敝刚刚
首先,打开【SQL Server Management Studio】,输进一个查询语句看看SQL Server是如何显示查询设计的吧。
说明:本文所演示的数据库,是我为一个演示程序专用预备的数据库,可以在此网页中下载。
select v.OrderID, v.CustomerID, v.CustomerName, v.OrderDate, v.SumMoney, v.Finishedfrom&& OrdersView as vwhere v.OrderDate &= '' and v.OrderDate & '';
个中,OrdersView是一个视图,其定义如下:
SELECT&&&& dbo.Orders.OrderID, dbo.Orders.CustomerID, dbo.Orders.OrderDate, &&&&&&&&&&& dbo.Orders.SumMoney, dbo.Orders.Finished, &&&&&&&&&&& ISNULL(dbo.Customers.CustomerName, N'') AS CustomerNameFROM&&&&&&&& dbo.Orders LEFT OUTER JOIN&&&&&&&&&&&&&&& dbo.Customers ON dbo.Orders.CustomerID = dbo.Customers.CustomerID
对于前一句查询,SQL Server给出的查询设计如下(点击对象栏上的【显示估量的执行设计】按钮):
从这个图中,我们至少可以获得3个有用的信息:
1. 哪些执行步骤花费的成本对照高。显然,最右边的二个步骤的成本是对照高的。
2. 哪些执行步骤发生的数据量对照多。对于每个步骤所发生的数据量,SQL Server的执行设计是用【线条粗细】来透露显示的,是以也很随意马虎地从分辩出来。
3. 每一步执行了什幺样的动作。
对于一个对照慢的查询来说,我们通常要知道哪些步骤的成本对照高,进而,可以测验考试一些改善的方法。一般来说,假如您不能经由过程:提高硬件机能或者调整OS,SQL Server的设置之类的体式格局来解决问题,那幺剩下的可选方法通常也只有以下这些了:
1. 为【scan】这类操作增加响应字段的索引。
2. 有时重建索引或许也是有效的,具体景遇请参考后文。
3. 调整语句结构,指导SQL Server采用其它的查询方案往执行。
4. 调整表结构(分表或者分区)。
下面再来说说一些很重要的理论常识,这些内容对于执行设计的理解是很有匡助的。
SQL Server 查找记录的方法
说到这里,不得不说SQL Server的索引了。SQL Server有二种索引:群集索引和非群集索引。二者的差别在于:【群集索引】直接决意了记录的存放位置,或者说:根据群集索引可以直接获取到记录。【非群集索引】留存了二个信息:1.响应索引字段的值,2.记录对应群集索引的位置(假如表没有群集索引则留存记录指针)。是以,假如能经由过程【群集索引】来查找记录,显然也是最快的。
SQL Server 会有以下方法来查找您需要的数据记录:
1. 【Table Scan】:遍历整个表,查找所有匹配的记录行。这个操作将会一行一行的搜检,当然,效率也是最差的。
2. 【Index Scan】:根据索引,从表中过滤出来一部分记录,再查找所有匹配的记录行,显然比第一种体式格局的查找局限要小,是以比【Table Scan】要快。
3. 【Index Seek】:根据索引,定位(获取)记录的存放位置,然后取得记录,是以,比起前二种体式格局会更快。
4. 【Clustered Index Scan】:和【Table Scan】一样。属意:不要认为这里有个Index,就认为不一样了。其实它的意思是说:按群集索引来逐行扫描每一行记录,因为记录就是按群集索引来递次存放的。而【Table Scan】只是说:要扫描的表没有群集索引而已,是以这二个操作本质上也是一样的。
5. 【Clustered Index Seek】:直接根据群集索引获取记录,最快!
所以,当发现某个查询对照慢时,可以首先搜检哪些操作的成本对照高,再看看那些操作在查找记录时,是不是【Table Scan】或者【Clustered Index Scan】,假如确实和这二种操作类型有关,则要考虑增加索引来解决了。不过,增加索引后,也会影响数据表的修改动作,因为修改数据表时,要更新响应字段的索引。所以索引过多,也会影响机能。还有一种情况是不适合增加索引的:某个字段用0或1透露显示的状况。例如可能有尽大多半是1,那幺此时加索引根本就没有意义。这时只能考虑为0或者1这二种情况分隔隔离涣散来留存了,分表或者分区都是不错的选择。
假如不能经由过程增加索引和调整表来解决,那幺可以试试调整语句结构,指导SQL Server采用其它的查询方案往执行。这种方法要求:1.对语句所要完成的功能很清楚,2.对要查询的数据表结构很清楚,3.对相关的营业背景常识很清楚。假如能经由过程这种方法往解决,当然也是很好的解决方法了。不过,有时SQL Server对照智能,即使你调整语句结构,也不会影响它的执行设计。
如何对照二个沟通功能的SQL语句的机能好坏呢,我建议采用二种方法:1. 直接把二个查询语句放在【SQL Server Management Studio】,然后往看它们的【执行设计】,SQL Server会以百分比的体式格局告诉你二个查询的【查询开销】。这种方法简单,通常也是可以参考的,不过,有时也会不剩咛逶蚯虢幼磐驴(可能索引统计信息过旧)。
2. 根据真实的程序调用,写响应的测试代码往调用:这种方法就麻烦一些,然则它更能代显示实调用情况,获得的结果也是更具有参考价值的,是以也是值得的。
SQL Server Join 体式格局
在SQL Server中,每个join敕令,都邑在内部执行时采用三种更具体的体式格局来运行:
1. 【Nested Loops join】,假如一个联接输进很小,而另一个联接输进很大而且已在其联接列上创建了索引,则索引 Nested Loops 连接是最快的联接操作,因为它们需要的 I/O 和对照都起码。
嵌套轮回联接也称为“嵌套迭代”,它将一个联接输进用作外部输进表(显示为图形执行设计中的顶端输进),将另一个联接输进用作内部(底端)输进表。外部轮回逐行处理外部输进表。内部轮回会针对每个外部行执行,在内部输进表中搜索匹配行。可以用下面的伪码来理解:
foreach(row r1 in outer table)&&& foreach(row r2 in inner table)&&&&&&& if( r1, r2 相符匹配前提 )&&&&&&&&&&& output(r1, r2);
最简单的情况是,搜索时扫描整个表或索引;这称为“单一嵌套轮回联接”。假如搜索时使用索引,则称为“索引嵌套轮回联接”。假如将索引生成为查询设计的一部分(并在查询完成后立即将索引损坏),则称为“暂时索引嵌套轮回联接”。查询优化器考虑了所有这些不同情况。
假如外部输进较小而内部输进较大且预先创建了索引,则嵌套轮回联接尤其有效。在很多小事务中(如那些只影响较小的一组行的事务),索引嵌套轮回联接优于合并联接和哈希联接。但在大型查询中,嵌套轮回联接通常不是最佳选择。
2. 【Merge Join】,假如两个联接输进并不小但已在二者联接列上排序(例如,假如它们是经由过程扫描已排序的索引获得的),则合并联接是最快的联接操作。假如两个联接输进都很大,而且这两个输进的大小差不久不多,则预先排序的合并联接提供的机能与哈希联接相近。然则,假如这两个输进的大小相差很大,则哈希联接操作通常快得多。
合并联接要求两个输进都在合并列上排序,而合并列由联接谓词的等效 (ON) 子句定义。通常,查询优化器扫描索引(假如在适当的一组列上存在索引),或在合并联接的下面放一个排序运算符。在极少数情况下,固然可能有多个等效子句,但只用个中一些可用的等效子句获得合并列。
因为每个输进都已排序,是以 Merge Join 运算符将从每个输进获取一行并将其进行对照。例如,对于内联接操作,假如行相等则返回。假如行不相等,则废弃值较小的行并从该输进获得另一行。这一过程将反复进行,直到处理完所有的行为止。
合并联接操作可所以常规操作,也可所以多对多操作。多对多合并联接使用暂时表存储行(会影响效率)。假如每个输进中有反复值,则在处理个中一个输进中的每个反复项时,另一个输进必需重绕到反复项的最先位置。可以创建独一索引告诉SQL Server不会有反复值。
假如存在驻留谓词,则所有知足合并谓词的行都将对该驻留谓词取值,而只返回那些知足该驻留谓词的行。
合并联接本身的速度很快,但假如需要排序操作,选择合并联接就会异常费时。然而,假如数据量很大且能够从现有 B 树索引中获得预排序的所需数据,则合并联接通常是最快的可用联接算法。
3. 【Hash Join】,哈希联接可以有效处理未排序的大型非索引输进。它们对复杂查询的中间结果很有用,因为:1. 中间结果未经索引(除非已经显式留存到磁盘上然后创建索引),而且通常不为查询设计中的下一个操作进行适当的排序。2. 查询优化器只估量中间结果的大小。因为对于复杂查询,估量可能有很大的误差,是以假如中间结果比预期的大得多,则处理中间结果的算法不仅必需有效而且必需适度弱化。
哈希联接可以削减使用非规范化。非规范化一般经由过程削减联接操作获得更好的机能,尽管这样做有冗余之险(如不一致的更新)。哈希联接则削减使用非规范化的需要。哈希联接使垂直分区(用零丁的文件或索引代表单个表中的几组列)得以成为物理数据库设计的可行选项。
哈希联接有两种输进:生成输进和探测输进。查询优化器指派这些角色,使两个输进中较小的那个作为生成输进。
哈希联接用于多种设置匹配操作:内部联接;左外部联接、右外部联接和完全外部联接;左半联接和右半联接;交集;联合和差异。此外,哈希联接的某种变形可以进行反复删除和分组,例如 SUM(salary) GROUP BY department。这些修改对生成和探测角色只使用一个输进。
哈希联接又分为3个类型:内存中的哈希联接、Grace 哈希联接和递回哈希联接。
内存中的哈希联接:哈希联接先扫描或较劲争论整个生成输进,然后在内存中生成哈希表。根据较劲争论得出的哈希键的哈希值,将每行插进哈希存储桶。假如整个生成输进小于可用内存,则可以将所有行都插进哈希表中。生成阶段之后是探测阶段。一次一行地对整个探测输进进行扫描或较劲争论,并为每个探测行较劲争论哈希键的值,扫描响应的哈希存储桶并生成匹配项。
Grace 哈希联接:假如生成输进大于内存,哈希联接将分为几步进行。这称为“Grace 哈希联接”。每一步都分为生成阶段和探测阶段。首先,消费整个生成和探测输进并将其分区(使用哈希键上的哈希函数)为多个文件。对哈希键使用哈希函数可以保证随意率性两个联接记录必然位于沟通的文件对中。是以,联接两个大输进的义务简化为沟通义务的多个较小的实例。然后将哈希联接应用于每对分区文件。
递回哈希联接:假如生成输进异常大,以至于标释獠亢喜⒌氖浣枰喔龊喜⒓侗穑蛐枰喔龇智街韬投喔龇智侗稹<偃缰挥心承┓智洗螅蛑恍瓒阅切┓智褂酶郊拥姆智街琛N耸顾蟹智街杈】赡芸欤褂么蟮囊觳 I/O 操作以便单个线程就能使多个磁盘驱动器繁忙工作。
在优化过程中不能始终确定使用哪种哈希联接。是以,SQL Server 最先时使用内存中的哈希联接,然后根据生成输进的大小逐渐转换到 Grace 哈希联接和递回哈希联接。
假如优化器错误地预计两个输进中哪个较小并由此确定哪个作为生成输进,生成角色和探测角色将动态反转。哈希联接确保使用较小的溢出文件作为生成输进。这一手艺称为“角色反转”。至少一个文件溢出到磁盘后,哈希联接中才会发生角色反转。
说明:您也可以显式的指定联接体式格局,SQL Server会尽量尊敬您的选择。比如你可以这样写:inner loop join, left outer merge join, inner hash join
然则,我照样建议您不要这样做,因为SQL Server的选择根本上都是正确的,不信您可以试一下。
好了,说了一大堆理论器械,再来个实际的例子注释一下吧。
更具体执行过程
前面,我给出一张图片,它反映了SQL Server在执行某个查询的执行设计,但它反映的信息可能不太细致,当然,您可以把鼠标指标移动某个节点上,会有以下信息泛起:
正好,我装的是中文版的,上面都是汉字,我也不久不多说了。我要说的是另一种体式格局的执行过程,比这个包含更多的执行信息,而且是实际的执行情况。(当然,您也可以继续使用图形体式格局,在运行查询前点击对象栏上的【包含实际的执行设计】按钮)
让我们再次回到【SQL Server Management Studio】,输进以下语句,然后执行。
set statistics profile on select v.OrderID, v.CustomerID, v.CustomerName, v.OrderDate, v.SumMoney, v.Finishedfrom&& OrdersView as vwhere v.OrderDate &= '' and v.OrderDate & '';
属意:现在加了一句,【set statistics profile on 】,获得的结果如下:
可以从图片上看到,执行查询后,获得二个表格,上面的表格显示了查询的结果,下面的表格显示了查询的执行过程。相比本文的第一张图片,这张图片可能在直观上不太友好,然则,它能反映更多的信息,而且尤其在对照复杂的查询时,可能看起来更随意马虎,因为对于复杂的查询,【执行设计】的步骤太多,图形体式格局会造成图形过大,不随意马虎观察。而且这张执行过程表格能反映2个很有价值的数据(前二列)。
照样来看看这个【执行过程表格】吧。我来挑几个重要的说一下。
【Rows】:透露显示在一个执行步骤中,所发生的记录条数。(真实数据,非预期)
【Executes】:透露显示某个执行步骤被执行的次数。(真实数据,非预期)
【Stmt Text】:透露显示要执行的步骤的描述。
【EstimateRows】:透露显示要预期返回若干行数据。
在这个【执行过程表格】中,对于优化查询来说,我认为前三列是对照重要的。对于前二列,我上面也注释了,意思也很清楚。前二列的数字也大体反映了那些步骤所花的成本,对于对照慢的查询中,应该属意它们。【Stmt Text】会告诉你每个步骤做了什幺工作。对于这种表格,它所要表达的其实是一种树型信息(一行就透露显示在图形体式格局下的一个节点),所以,我建议从最内层最先往读它们。做为示例,我来注释一下这张表格它所表达的执行过程。
第5行:【Clustered Index Seek(OBJECT:([MyNorthwind].[dbo].[Customers].[PK_Customers]), SEEK:([MyNorthwind].[dbo].[Customers].[CustomerID]=[MyNorthwind].[dbo].[Orders].[CustomerID]) ORDERED FORWARD)】,意思是说,SQL Server在对表Customers做Seek操作,而且是按照【Clustered Index Seek】的体式格局,对应的索引是【PK_Customers】,seek的值起原于[Orders].[CustomerID]
第4行:【Clustered Index Scan(OBJECT:([MyNorthwind].[dbo].[Orders].[PK_Orders]), WHERE:([MyNorthwind].[dbo].[Orders].[OrderDate]&=' 00:00:00.000' AND [MyNorthwind].[dbo].[Orders].[OrderDate]&' 00:00:00.000'))】,意思是说,SQL Server在对表Customers做Scan操作,即:最差的【表扫描】的体式格局,原因是,OrderDate列上没有索引,所以只能这样了。
第3行:【Nested Loops(Left Outer Join, OUTER REFERENCES:([MyNorthwind].[dbo].[Orders].[CustomerID]))】,意思是说,SQL Server把第5行和第4行发生的数据用【Nested Loops】的体式格局联接起来,个中Outer表是Orders,要联接的匹配操作也在第5行中指出了。
第2行:【Compute Scalar(DEFINE:([Expr1006]=isnull([MyNorthwind].[dbo].[Customers].[CustomerName],N'')))】,意思是说,要执行一个isnull()函数的调用。具体原因请参考本文前部分中给出视图定义代码。
第1行:【SELECT [v].[OrderID],[v].[CustomerID],[v].[CustomerName],[v].[OrderDate],[v].[SumMoney],[v].[Finished] FROM [OrdersView] [v] WHERE [v].[OrderDate]&=@1 AND [v].[OrderDate]&@2】,通常第1行就是整个查询,透露显示它的返回值。
索引统计信息:查询设计的选择依据
前面一直说到【执行设计】,既然是设计,就透露显示要在具体执行前就能确定下来的操作方案。那幺SQL Server是如何选择一个执行设计的呢?SQL Server怎幺知道什幺时刻该用索引或者用哪个索引呢?对于SQL Server来说,每当要执行一个查询时,都要首先搜检这个查询的执行设计是否存在缓存中,假如没有,就要生成一个执行设计,具体在发生执行设计时,并不是看有哪些索引可用(随机选择),而是会参考一种被称为【索引统计信息】的数据。假如您细心地看一下前面的执行设计或者执行过程表格,会发现SQL Server能预估每个步骤所发生的数据量,恰是因为SQL Server能预估这些数据量,SQL Server才干选择一个它认为最合适的方法往执行查询过程,此时【索引统计信息】就能告诉SQL Server这些信息。说到这里,您是不是有点好奇呢,为了让您对【索引统计信息】有个感性的熟悉,我们来看看【索引统计信息】是个什幺样子的。请在【SQL Server Management Studio】,输进以下语句,然后执行。
dbcc show_statistics (Products, IX_CategoryID)
获得的结果如下图:
首先,照样注释一下敕令:【dbcc show_statistics】这个敕令可以显示我们想知道的【索引统计信息】,它需要二个参数,1. 表名,2. 索引名
再来看看敕令的结果,它有三个表格组成:
1. 第一个表格,它列出了这个索引统计信息的首要信息。
说明Name统计信息的名称。Updated上一次更新统计信息的日期和时间。Rows表中的行数。Rows Sampled统计信息的抽样行数。Steps数据可分成若干个组,与第三个表对应。Density第一个索引列前缀的选择性(不包含 EQ_ROWS)。Average key length所有索引列的平均长度。String Index假如为“是”,则统计信息中包含字符串摘要索引,以支撑为 LIKE 前提估算结果集大小。仅合用于 char、varchar、nchar 和 nvarchar、varchar(max)、nvarchar(max)、text 以及 ntext 数据类型的前导列。
2. 第二个表格,它列出各类字段组合的选择性,数据越小透露显示反复越性越小,当然选择性也就越高。
说明All density索引列前缀集的选择性(包含 EQ_ROWS)。属意:这个值越小就透露显示选择性越高。
假如这个值小于0.1,这个索引的选择性就对照高,反之,则透露显示选择性就不高了。Average length索引列前缀集的平均长度。Columns为其显示 All density 和 Average length 的索引列前缀的名称。
3. 第三个表格,数据分布的直方图,SQL Server就是靠它预估一些执行步骤的数据量。
说明RANGE_HI_KEY每个组中的最大值。RANGE_ROWS每组数据组的估算行数,不包含最大值。EQ_ROWS为了能让您更好的理解这些数据,尤其是第三组,请看下图:
当时我在填充测试数据时,有意把CategoryId分为1到8(10是后光降时加的),每组填充了78条数据。所以【索引统计信息】的第三个表格的数据也都是正确的,也恰是根据这些统计信息,SQL Server才干对每个执行步骤预估响应的数据量,从而影响Join之类的选择。当然了,在选择Join体式格局时,也要参考第二个表格中字段的选择性。SQL Server在为查询生成执行设计时,查询优化器将使用这些统计信息并结合相关的索引来评估每种方案的开销来选择最佳的查询设计。
再来个例子说明一下统计信息对于查询设计的重要性。首先多加点数据,请看以下代码:
declare @newCategoryIinsert into dbo.Categories (CategoryName) values(N'Test statistics');set @newCategoryId = scope_identity();declare @set @count = 0;while( @count & 100000 )begin&&& insert into Products (ProductName, CategoryID, Unit, UnitPrice, Quantity, Remark) &&& values( cast(newid() as nvarchar(50)), @newCategoryId, N'个', 100, @count +1, N'');&&& set @count = @count + 1;endgoupdate statistics Pgo
再来看看索引统计信息:
再来看看同一个查询,但因为查询参数值不同时,SQL Server选择的执行设计:
select p.ProductId, t.Quantity from Products as p left outer join [Order Details] as t on p.ProductId = t.ProductId where p.CategoryId = 26;&&& -- 26 就是最新发生的CategoryId,是以这个查询会返回10W笔记录select p.ProductId, t.Quantity from Products as p left outer join [Order Details] as t on p.ProductId = t.ProductId where p.CategoryId = 6;&&& -- 这个查询会返回95笔记录
从上图可以看出,因为CategoryId的参数值不同,SQL Server会选择完全不同的执行设计。统计信息重要性在这里体现的很清楚吧。
创建统计信息后,数据库引擎对列值(根据这些值创建统计信息)进行排序,并根据这些值(最多 200 个,按距离分隔开)创建一个“直方图”。直方图指定有若干行精确匹配每个距离值,有若干行在距离局限内,以及距离中值的密度大小或反复值的发生率。
SQL Server 2005 引进了对 char、varchar、varchar(max)、nchar、nvarchar、nvarchar(max)、text 和 ntext 列创建的统计信息收集的其他信息。这些信息称为“字符串摘要”,可以匡助查询优化器估量字符串模式中查询谓词的选择性。查询中有 LIKE 前提时,使用字符串摘要可以更正确地估量结果集大小,并赓续优化查询设计。这些前提包含诸如 WHERE ProductName LIKE '%Bike' 和 WHERE Name LIKE '[CS]heryl' 之类的前提。
既然【索引统计信息】这幺重要,那幺它会在什幺时刻生成或者更新呢?事实上,【索引统计信息】是不用我们手工往维护的,SQL Server会自动往维护它们。而且在SQL Server中也有个参数来节制这个更新体式格局:
统计信息自动功能工作体式格局
创建索引时,查询优化器自动存储有关索引列的统计信息。另外,当 AUTO_CREATE_STATISTICS 数据库选项设置为 ON(默认值)时,数据库引擎自动为没有用于谓词的索引的列创建统计信息。
跟着列中数据发生变化,索引和列的统计信息可能会过时,从而导致查询优化器选择的查询处理方法不是最佳的。例如,假如创建一个包含一个索引列和 1,000 行数据的表,每一行在索引列中的值都是独一的,则查询优化器将把该索引列视为收集查询数据的好方法。假如更新列中的数据后存在很多反复值,则该列不再是用于查询的幻想候选列。然则,查询优化器仍然根据索引的过时分布统计信息(基于更新前的数据),将其视为好的候选列。
当 AUTO_UPDATE_STATISTICS 数据库选项设置为 ON(默认值)时,查询优化器会在表中的数据发生变化时自动按期更新这些统计信息。每当查询执行设计中使用的统计信息没有经由过程针对当前统计信息的测试时就会启动统计信息更新。采样是在各个数据页上随机进行的,取自表或统计信息所需列的最小非群集索引。从磁盘读取一个数据页后,该数据页上的所有行都被用来更新统计信息。常规情况是:在大约有 20% 的数据行发生变化时更新统计信息。然则,查询优化器始终确保采样的行数尽量少。对于小于 8 MB 的表,则始终进行完整扫描来收集统计信息。
采样数据(而不是分析所有数据)可以将统计信息自动更新的开销降至最低。在某些情况下,统计采样无法获得表中数据的精确特征。可以使用 UPDATE STATISTICS 语句的 SAMPLE 子句和 FULLSCAN 子句,节制按逐个表的体式格局手动更新统计信息时采样的数据量。FULLSCAN 子句指定扫描表中的所有数据来收集统计信息,而 SAMPLE 子句用来指定采样的行数百分比或采样的行数
在 SQL Server 2005 中,数据库选项 AUTO_UPDATE_STATISTICS_ASYNC 提供了统计信息异步更新功能。当此选项设置为 ON 时,查询不守候统计信息更新,即可进行编译。而过时的统计信息置于队列中,由后台进程中的工作线程来更新。查询和任何其他并发查询都经由过程使用现有的过时统计信息立即编译。因为不存在守候更新后的统计信息的延迟,是以查询响应时间可猜测;然则过时的统计信息可能导致查询优化器选择低效的查询设计。在更新后的统计信息停当后启动的查询将使用那些统计信息。这可能会导致从新编译缓存的设计(取决于较旧的统计信息版本)。假如在同一个显式用户事务中泛起某些数据定义语言 (DDL) 语句(例如,CREATE、ALTER 和 DROP 语句),则无法更新异步统计信息。
AUTO_UPDATE_STATISTICS_ASYNC 选项设置于数据库级别,并确定用于数据库中所有统计信息的更新方法。它只合用于统计信息更新,而无法用于以异步体式格局创建统计信息。只有将 AUTO_UPDATE_STATISTICS 设置为 ON 时,将此选项设置为 ON 才有效。默认情况下,AUTO_UPDATE_STATISTICS_ASYNC 选项设置为 OFF。
从以上说明中,我们可以看出,对于大表,照样有可能存在统计信息更新不适钡氖笨蹋馐保涂赡芑嵊跋觳檠呕鞯钠识狭恕
有些人可能有个经验:对于一些慢的查询,他们会想到重建索引来测验考试解决。其实这样做是有事理的。因为,在某些时刻一个查询溘然变慢了,可能和统计信息更新不适庇泄兀嵊跋觳檠呕鞯钠识稀<偃缢故敝亟ㄋ饕涂梢匀貌檠呕髦雷钚碌氖莘植迹匀痪涂梢员芸飧鑫侍狻;辜堑梦仪懊嬗谩set statistics profile on】显示的执行过程表格吗?属意哦,那个表格就显示每个步骤的实际数据量和预估的数据量。要不要重建索引,其实我们可以用【set statistics profile on】来看一下,假如实际数据量和预估的数据量的差值对照大,那幺我们可以考虑手工往更新统计信息,然后再往试试。
优化视图查询
再来说说优化视图查询,固然视图也是由一个查询语句定义的,本质上也是一个查询,但它和一般的查询语句在优化时,照样有所区其余。这里首要的区别在于,视图固然是由一个查询语句定义的,但假如只往分析这个查询定义,可能获得的意义不大,因为视图多半时刻就不是直接使用,而是在使用前,会加上where语句,或者放在其它语句中供from子句所使用。下面照样举个例子吧,在我的演示数据库中有个视图OrdersView,定义代码前面有。我们来看看,假如直接使用这个视图,会有什幺样的执行设计出来:
从这个视图可以看出,SQL Server会对表Orders做全表扫描,应该是很低效的。再来看看下面这个查询:
从这个执行设计可以看出,与上面那个就不一样了。前一个查询中对Orders表的查找是使用【Clustered Index Scan】的体式格局,而现在在使用【Clustered Index Seek】的体式格局了,最右边二个步骤的成本的百分比也发生了改变。这样就足以说明,优化视图时,最好能根据实际需求,应用不同的过滤前提,再来决意如何往优化。
再来一个由三个查询组成的情况来看看这个视图的执行设计。
select * from dbo.OrdersView where OrderId = 1;select * from dbo.OrdersView where CustomerId = 1;select * from dbo.OrdersView where OrderDate &= '' and OrderDate & '';
很分明,对于同一个视图,在不同的过滤前提下,执行设计的差别很分明。
推荐阅读-MSDN文章
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
Copyright © 2013- 网站备案号:
TOM在线版权所有

我要回帖

更多关于 sql语句 的文章

 

随机推荐