<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_CareySon</title><subtitle type="text">保持学徒心态！</subtitle><id>http://feed.cnblogs.com/blog/u/38931/rss</id><updated>2012-05-25T07:26:05Z</updated><author><name>CareySon</name><uri>http://www.cnblogs.com/CareySon/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/CareySon/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/38931/rss"/><entry><id>http://www.cnblogs.com/CareySon/archive/2012/05/25/2518012.html</id><title type="text">SQL压力测试用的语句和相关计数器</title><summary type="text">将数据库中所有表的所有的内容选一遍: IF object_id('tempdb..#temp') is not null BEGIN DROP TABLE #temp ENDDECLARE @index int DECLARE @count int DECLARE @schemaname varchar(50) DECLARE @tablename ...</summary><published>2012-05-25T06:46:00Z</published><updated>2012-05-25T06:46:00Z</updated><author><name>CareySon</name><uri>http://www.cnblogs.com/CareySon/</uri></author><link rel="alternate" href="http://www.cnblogs.com/CareySon/archive/2012/05/25/2518012.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/CareySon/archive/2012/05/25/2518012.html"/><content type="html">&lt;p&gt;将数据库中所有表的所有的内容选一遍:&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &amp;#160;&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;IF object_id('tempdb..#temp')&amp;#160;&amp;#160; is&amp;#160;&amp;#160; not&amp;#160;&amp;#160; null&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;BEGIN  &lt;br /&gt;DROP TABLE #temp   &lt;br /&gt;END&lt;/p&gt;&lt;p&gt;DECLARE @index int  &lt;br /&gt;DECLARE @count int  &lt;br /&gt;&amp;#160; DECLARE @schemaname varchar(50)  &lt;br /&gt;DECLARE @tablename varchar(50)  &lt;br /&gt;set @index=1  &lt;br /&gt;set @count=(select count(*) from sysobjects where xtype='U')&lt;/p&gt;&lt;p&gt;&amp;#160; select row_number() over(order by name) as rowNumber,name,  &lt;br /&gt;&amp;#160; ( SELECT a.name from sys.tables t inner join sys.schemas a   &lt;br /&gt;ON t.schema_id=a.schema_id  &lt;br /&gt;WHERE t.name=ob.name) as schemaname  &lt;br /&gt;into #temp from sysobjects ob where xtype='U'&lt;/p&gt;&lt;p&gt;WHILE(@index&amp;lt;@count)  &lt;br /&gt;BEGIN  &lt;br /&gt;set @schemaname=(SELECT schemaname from #temp where rowNumber=@index)  &lt;br /&gt;set @tablename=(SELECT name from #temp where rowNumber=@index)&lt;/p&gt;&lt;p&gt;exec('select * from '+ @schemaname+'.'+@tablename)&lt;/p&gt;&lt;p&gt;set @index=@index+1&lt;/p&gt;&lt;p&gt;END&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;通常来说，需要看如下几个计数器（下面资料参考自&lt;a title="http://www.sqlservercentral.com/articles/Miscellaneous/2634/" href="http://www.sqlservercentral.com/articles/Miscellaneous/2634/"&gt;http://www.sqlservercentral.com/articles/Miscellaneous/2634/&lt;/a&gt;）:&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;Memory: Pages/sec &lt;/li&gt;  &lt;li&gt;Memory: Available Bytes &lt;/li&gt;  &lt;li&gt;Network Interface: Bytes Total/Sec &lt;/li&gt;  &lt;li&gt;Physical Disk: % Disk time &lt;/li&gt;  &lt;li&gt;Physical Disk: Avg. Disk Queue Length &lt;/li&gt;  &lt;li&gt;Processor: % Processor Time &lt;/li&gt;  &lt;li&gt;System: Processor Queue Length &lt;/li&gt;  &lt;li&gt;SQL Server Buffer: Buffer Cache Hit Ratio &lt;/li&gt;  &lt;li&gt;SQL Server General: User Connections &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;Memory: Pages/sec:最好不要大于5，否则有内存问题&lt;/p&gt;&lt;p&gt;Memory: Available Bytes :这个可以望文生义，不解释&lt;/p&gt;&lt;p&gt;Network Interface: Bytes Total/Sec :如果这个计数器下降的太快有可能是网络出现问题&lt;/p&gt;&lt;p&gt;Physical Disk: Avg Disk Queue Length:每个逻辑盘的等待队列，大于2有可能是IO瓶颈问题&lt;/p&gt;&lt;p&gt;Physical Disk: % Disk time: 读/写活动的百分比，不要大于90%,和上面的计数器一起可以显示IO瓶颈&lt;/p&gt;&lt;p&gt;Processor: % Processor Time :CPU瓶颈，不要大于90%，大多数情况下，内存和IO瓶颈要更多&lt;/p&gt;&lt;p&gt;System: Processor Queue Length :同样，和上面计数器一起找出IO瓶颈&lt;/p&gt;&lt;p&gt;SQL Server Buffer: Buffer Cache Hit Ratio :缓存命中率，不要低于85%,否则考虑加内存&lt;/p&gt;&lt;p&gt;SQL Server General:并发数,压测时快到某一瓶颈看看这个数字，可以作为基准(BaseLine)记下来&lt;/p&gt;&lt;img src="http://www.cnblogs.com/CareySon/aggbug/2518012.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/CareySon/archive/2012/05/25/2518012.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/CareySon/archive/2012/05/23/CoreConceptOfExcutionEngine.html</id><title type="text">SQL Server中的执行引擎入门</title><summary type="text">简介 当查询优化器(Query Optimizer)将T-SQL语句解析后并从执行计划中选择最低消耗的执行计划后，具体的执行就会交由执行引擎(Execution Engine)来进行执行。本文旨在分类讲述执行计划中每一种操作的相关信息。 数据访问操作 首先最基本的操作就是访问数据。这既可以通过直接访问表，也可以通过访问索引来进行。表内数据的组织方式分为堆(Heap)和B树，其中表中没有建立聚集索引时数据是通过堆进行组织的，这个是无序的，表中建立聚集索引后和非聚集索引的数据都是以B树方式进行组织，这种方式数据是有序存储的。通常来说，非聚集索引仅仅包含整个表的部分列，对...</summary><published>2012-05-23T14:48:00Z</published><updated>2012-05-23T14:48:00Z</updated><author><name>CareySon</name><uri>http://www.cnblogs.com/CareySon/</uri></author><link rel="alternate" href="http://www.cnblogs.com/CareySon/archive/2012/05/23/CoreConceptOfExcutionEngine.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/CareySon/archive/2012/05/23/CoreConceptOfExcutionEngine.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;简介&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 当查询优化器(Query Optimizer)将T-SQL语句解析后并从执行计划中选择最低消耗的执行计划后，具体的执行就会交由执行引擎(Execution Engine)来进行执行。本文旨在分类讲述执行计划中每一种操作的相关信息。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;数据访问操作&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 首先最基本的操作就是访问数据。这既可以通过直接访问表，也可以通过访问索引来进行。表内数据的组织方式分为堆(Heap)和B树，其中表中没有建立聚集索引时数据是通过堆进行组织的，这个是无序的，表中建立聚集索引后和非聚集索引的数据都是以B树方式进行组织，这种方式数据是有序存储的。通常来说，非聚集索引仅仅包含整个表的部分列，对于过滤索引，还仅仅包含部分行。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 除去数据的组织方式不同外，访问数据也分为两种方式，扫描(Scan)和查找(Seek),扫描是扫描整个结构的所有数据，而查找只是查找整个结构中的部分数据。因此可以看出，由于堆是无序的，所以不可能在堆上面进行查找(Seek)操作,而相对于B树的有序，使得在B树中进行查找成为可能。当针对一个以堆组织的表进行数据访问时，就会进行堆扫描,如图1所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232246579487.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="1" border="0" alt="1" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232246581307.png" width="363" height="160" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图1.表扫描&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 可以看出，表扫描的图标很清晰的表明表扫描的性质，在一个无序组织表中从头到尾扫描一遍。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 而对于B树结构的聚集索引和非聚集索引，同样可以进行扫描，通常来讲，为了获取索引表中的所有数据或是获得索引行树占了数据大多数使得扫描的成本小于查找时，会进行聚集索引扫描。如图2所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232246599256.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="3" border="0" alt="3" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247006093.png" width="361" height="111" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图2.聚集索引扫描&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 聚集索引扫描的图标也同样能够清晰的表明聚集索引扫描的性质，找到最左边的叶子节点后，依次扫描所有叶子节点,达到扫描整个结构的作用。当然对于非聚集索引也是同样的概念，如图3所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247011533.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="2" border="0" alt="2" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247028370.png" width="338" height="120" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图3.非聚集索引的扫描&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 而对于仅仅选择B树结构中的部分数据，索引查找(Seek)使得B树变得有意义。根据所查找的关键值，可以使得从仅仅从B树根部向下走单一路径，因此免去了扫描不必要页的消耗，图4是查询计划中的一个索引查找。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247034334.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="4" border="0" alt="4" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247051170.png" width="354" height="136" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图4.聚集索引查找&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 索引查找的图标也是很传神的，可以看到图标那根线从根节点一路向下到叶子节点。也就是找到所求数据所在的页，不难看出，如果我们需要查找多条数据且分散在不同的页中，这个查找操作需要重复执行很多回，当这个次数大到一定程度时，SQL Server会选择消耗比较低的索引扫描而不是再去重复索引查找。对于非聚集索引查找，概念是一样的，就不再上图片了。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;书签查找(Bookmark Lookup)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;font color="#000000"&gt;你也许会想，假如非聚集索引可以快速的找到所求的数据，但遗憾的是，非聚集索引却不包含所有所求列时该怎么办？这时SQL Server会面临两个选择，直接访问基本表去获取数据或是在非聚集索引中找到数据后，再去基本表获得非聚集索引没有覆盖到的所求列。这个选择取决于所估计的行数等统计信息。查询分析器会选择消耗比较少的那个。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 一个简单的书签查找如图5所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247067134.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="5" border="0" alt="5" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247071462.png" width="523" height="182" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图5.一个简单的书签查找&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 从图5可以看出，首先通过非聚集索引找到所求的行，但这个索引并不包含所有的列，因此还要额外去基本表中找到这些列，因此要进行键查找，如果基本表是以堆进行组织的，那么这个键查找(Key Lookup)就会变成RID查找(RID Lookup),键查找和RID查找统称为书签查找。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 不过有时候索引查找所返回的行数过多导致书签查找的性能远不如直接进行扫描操作，因此SQL Server这时会选择扫描而不是书签查找。如图6所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247094329.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="6" border="0" alt="6" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/2012052322471052.png" width="442" height="300" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图6.StateProvinceID列有非聚集索引，但由于返回行数过多，分析器会选择扫描而不是书签查找&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这个估计是根据统计信息进行的，关于统计信息，可以看我之前的一篇博文：&lt;a href="http://www.cnblogs.com/CareySon/archive/2012/05/14/HowStatisticImpactQuery.html"&gt;浅谈SQL Server中统计对于查询的影响&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;聚合操作(Aggregation)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 聚合函数会导致聚合操作。聚合函数是将一个集合的数据按照某种规则汇总成1个数据，或基于分组按照规则汇总成多个数据的过程。一些聚合函数比如:avg,sum,min，另外还有distinct关键字都有可能导致两类聚合操作:流聚合(Stream Aggregation)和哈希聚合(Hash Aggregation)。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;流聚合(Stream Aggregation)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 流聚合需要再执行聚合函数之前，被聚合的数据集合是有序的，这个有序数据既可以通过执行计划中的Sort进行，也可以直接从聚集或是非聚集索引中直接获得有序数据，另外，没有Group by的聚合操作被成为标量聚合，这类操作一定是会执行流聚合。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 比如，我们直接进行标量聚合，如图7所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247112952.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="7" border="0" alt="7" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247137803.png" width="646" height="220" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图7.流聚合&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; 但对于加了Group by的子句，因为需要数据按照group by 后面的列有序，就需要Sort来保证排序。注意,Sort操作是占用内存的操作，当内存不足时还会去占用tempdb。SQL Server总是会在Sort操作和散列匹配中选择成本最低的。一个需要Sort的操作如图8所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247149274.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="8" border="0" alt="8" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247164126.png" width="633" height="264" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图8.需要排序的流聚合&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图8中排序操作按照ProductLine进行排序后，然后就根据各自的分组做聚合操作了。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;散列聚合(Hash aggregation)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 上面的流聚合适合比较少的数据，但是对于相对大一点的表。使用散列集合成本会比排序要低。散列集合通过在内存中建立散列表来实现聚合，因此无需对数据集合进行排序。内存中所建立的散列表以Group by后面的列作为键值，如图9所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247171453.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="9" border="0" alt="9" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247209029.png" width="944" height="350" /&gt;&lt;/a&gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 图9.散列聚合&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 在内存中建立好散列表后，会按照group by后面的值作为键，然后依次处理集合中的每条数据，当键在散列表中不存在时，向散列表添加条目，当键已经在散列表中存在时，按照规则（规则是聚合函数，比如Sum,avg什么的）计算散列表中的值（Value）。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;连接(Join)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 当多表连接时(书签查找，索引之间的连接都算)，SQL Server会采用三类不同的连接方式:循环嵌套连接(Nested Loops Join),合并连接(Merge Join),散列连接(Hash Join)。这几种连接并不是哪种会比另一种更好，而是每种连接方式都会适应特定场景。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;循环嵌套连接(Nested Loops Join)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 由图10可以看到一个简单的循环嵌套连接。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247218515.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="10" border="0" alt="10" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/20120523224723858.png" width="578" height="367" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图10.一个循环嵌套连接的实例&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 循环嵌套连接的图标同样十分传神，处在上面的外部输入(Outer input)，这里也就是聚集索引扫描。和处在下面的内部输入(Inner Input),这里也就是聚集索引查找。外部输入仅仅执行一次，根据外部输入满足Join条件的每一行，对内部输入进行查找。这里由于是290行，对于内部输入执行290次。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 可以通过属性窗口看到.如图11所示：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247246058.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="13" border="0" alt="13" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247264432.png" width="268" height="383" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图11.内部输入的执行次数&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 根据嵌套循环的原理不难看出，由于外部输入是扫描，内部输入是查找，当两个Join的表外部输入结果集比较小，而内部输入所查找的表非常大时，查询优化器更倾向于选择循环嵌套方式。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;合并连接(Merge Join)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 不同于循环嵌套的是，合并连接是从每个表仅仅执行一次访问。从这个原理来看，合并连接要比循环嵌套要快了不少。下面来看一个典型的合并连接，如图12所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247282871.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="11" border="0" alt="11" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247296610.png" width="903" height="390" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图12.合并连接&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 从合并连接的原理不难想象，首先合并连接需要双方有序.并且要求Join的条件为等于号。因为两个输入条件已经有序，所以从每一个输入集合中取一行进行比较，相等的返回，不相等的舍弃，从这里也不难看出Merge join为什么只允许Join后面是等于号。从图11的图标中我们可以看出这个原理。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 如果输入数据的双方无序，则查询分析器不会选择合并连接，我们也可以通过索引提示强制使用合并连接，为了达到这一目的，执行计划必须加上一个排序步骤来实现有序，如图13所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/2012052322473133.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="12" border="0" alt="12" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247324884.png" width="569" height="340" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图13.通过排序来实现Merge Join&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;散列连接(Hash Join)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 散列连接同样仅仅只需要只访问1次双方的数据。散列连接通过在内存中建立散列表实现。这比较消耗内存，如果内存不足还会占用tempdb。但并不像合并连接那样需要双方有序。一个典型的散列连接如图14所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247344163.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="14" border="0" alt="14" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247383144.png" width="588" height="388" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图14.散列连接&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这里我删除了Costomer的聚集索引，否则两个有序输入SQL Server会选择代价更低的合并连接。SQL Server利用两个上面的输入生成哈希表，下面的输入来探测，可以在属性窗口看到这些信息，如图15所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247427698.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="15" border="0" alt="15" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247471314.png" width="323" height="232" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图15.散列键生成和散列键探测&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 通常来说，在两个输入数据比较大，且所求数据在其中一方或双方没有排序的条件达成时，会选用散列匹配。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;并行&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;font color="#000000"&gt;当多个表连接时，SQL Server还允许在多CPU或多核的情况下允许查询并行，这样无疑提高了效率，一个并行的例子如图16所示。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247498118.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="16" border="0" alt="16" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205232247507429.png" width="743" height="339" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; 图16.并行提高效率&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;总结&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 本文简单介绍了SQL Server执行计划中常见的操作极其原理，了解这些步骤和原理是优化查询的基本功。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/CareySon/aggbug/2515442.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/CareySon/archive/2012/05/23/CoreConceptOfExcutionEngine.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/CareySon/archive/2012/05/17/2506223.html</id><title type="text">有关锁和内存使用的DMV</title><summary type="text">查看连接当前数据库的SPID所加的锁 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT DB_NAME(resource_database_id) AS DatabaseName , request_session_id , resource_type , CASE WHEN resource_type = 'OBJECT' THEN OBJECT_NAME(resource_associated_entity_id) WHEN resource_type IN ('KEY', 'PA...</summary><published>2012-05-17T06:53:00Z</published><updated>2012-05-17T06:53:00Z</updated><author><name>CareySon</name><uri>http://www.cnblogs.com/CareySon/</uri></author><link rel="alternate" href="http://www.cnblogs.com/CareySon/archive/2012/05/17/2506223.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/CareySon/archive/2012/05/17/2506223.html"/><content type="html">&lt;p&gt;&lt;font color="#0000ff"&gt;查看连接当前数据库的SPID所加的锁&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT DB_NAME(resource_database_id) AS DatabaseName    &lt;br /&gt;, request_session_id    &lt;br /&gt;, resource_type    &lt;br /&gt;, CASE     &lt;br /&gt;WHEN resource_type = 'OBJECT'     &lt;br /&gt;THEN OBJECT_NAME(resource_associated_entity_id)     &lt;br /&gt;WHEN resource_type IN ('KEY', 'PAGE', 'RID')     &lt;br /&gt;THEN (SELECT OBJECT_NAME(OBJECT_ID)     &lt;br /&gt;FROM sys.partitions p    &lt;br /&gt;WHERE p.hobt_id = l.resource_associated_entity_id)    &lt;br /&gt;END AS resource_type_name    &lt;br /&gt;, request_status    &lt;br /&gt;, request_mode    &lt;br /&gt;FROM sys.dm_tran_locks l     &lt;br /&gt;WHERE request_session_id !=@@spid     &lt;br /&gt;ORDER BY request_session_id &lt;/p&gt;  &lt;p&gt;结果如图:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/20120517145254312.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="1" border="0" alt="1" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171452569274.png" width="717" height="254" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;如果像查看更多的锁，调整where条件即可&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;查看没关闭事务的空闲Session&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT es.session_id, es.login_name, es.host_name, est.text    &lt;br /&gt;&amp;#160; , cn.last_read, cn.last_write, es.program_name    &lt;br /&gt;FROM sys.dm_exec_sessions es     &lt;br /&gt;INNER JOIN sys.dm_tran_session_transactions st     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON es.session_id = st.session_id    &lt;br /&gt;INNER JOIN sys.dm_exec_connections cn     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON es.session_id = cn.session_id    &lt;br /&gt;CROSS APPLY sys.dm_exec_sql_text(cn.most_recent_sql_handle) est     &lt;br /&gt;LEFT OUTER JOIN sys.dm_exec_requests er&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON st.session_id = er.session_id    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AND er.session_id IS NULL&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;查看被阻塞的语句和它们的等待时间&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT     &lt;br /&gt;&amp;#160; Waits.wait_duration_ms / 1000 AS WaitInSeconds    &lt;br /&gt;&amp;#160; , Blocking.session_id as BlockingSessionId    &lt;br /&gt;&amp;#160; , DB_NAME(Blocked.database_id) AS DatabaseName    &lt;br /&gt;&amp;#160; , Sess.login_name AS BlockingUser     &lt;br /&gt;&amp;#160; , Sess.host_name AS BlockingLocation     &lt;br /&gt;&amp;#160; , BlockingSQL.text AS BlockingSQL    &lt;br /&gt;&amp;#160; , Blocked.session_id AS BlockedSessionId    &lt;br /&gt;&amp;#160; , BlockedSess.login_name AS BlockedUser    &lt;br /&gt;&amp;#160; , BlockedSess.host_name AS BlockedLocation     &lt;br /&gt;&amp;#160; , BlockedSQL.text AS BlockedSQL    &lt;br /&gt;&amp;#160; , SUBSTRING (BlockedSQL.text, (BlockedReq.statement_start_offset/2) + 1,     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ((CASE WHEN BlockedReq.statement_end_offset = -1    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; THEN LEN(CONVERT(NVARCHAR(MAX), BlockedSQL.text)) * 2    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ELSE BlockedReq.statement_end_offset     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; END - BlockedReq.statement_start_offset)/2) + 1)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS [Blocked Individual Query]    &lt;br /&gt;&amp;#160; , Waits.wait_type    &lt;br /&gt;FROM sys.dm_exec_connections AS Blocking&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;INNER JOIN sys.dm_exec_requests AS Blocked     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON Blocking.session_id = Blocked.blocking_session_id     &lt;br /&gt;INNER JOIN sys.dm_exec_sessions Sess     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON Blocking.session_id = sess.session_id&amp;#160; &lt;br /&gt;INNER JOIN sys.dm_tran_session_transactions st     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON Blocking.session_id = st.session_id    &lt;br /&gt;LEFT OUTER JOIN sys.dm_exec_requests er     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON st.session_id = er.session_id    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AND er.session_id IS NULL    &lt;br /&gt;INNER JOIN sys.dm_os_waiting_tasks AS Waits     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON Blocked.session_id = Waits.session_id     &lt;br /&gt;CROSS APPLY sys.dm_exec_sql_text(Blocking.most_recent_sql_handle)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS BlockingSQL    &lt;br /&gt;INNER JOIN sys.dm_exec_requests AS BlockedReq&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON Waits.session_id = BlockedReq.session_id     &lt;br /&gt;INNER JOIN sys.dm_exec_sessions AS BlockedSess     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON Waits.session_id = BlockedSess.session_id     &lt;br /&gt;CROSS APPLY sys.dm_exec_sql_text(Blocked.sql_handle) AS BlockedSQL     &lt;br /&gt;ORDER BY WaitInSeconds    &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;查看超过30秒等待的查询&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT     &lt;br /&gt;&amp;#160; Waits.wait_duration_ms / 1000 AS WaitInSeconds    &lt;br /&gt;&amp;#160; , Blocking.session_id as BlockingSessionId    &lt;br /&gt;&amp;#160; , Sess.login_name AS BlockingUser     &lt;br /&gt;&amp;#160; , Sess.host_name AS BlockingLocation     &lt;br /&gt;&amp;#160; , BlockingSQL.text AS BlockingSQL    &lt;br /&gt;&amp;#160; , Blocked.session_id AS BlockedSessionId    &lt;br /&gt;&amp;#160; , BlockedSess.login_name AS BlockedUser    &lt;br /&gt;&amp;#160; , BlockedSess.host_name AS BlockedLocation     &lt;br /&gt;&amp;#160; , BlockedSQL.text AS BlockedSQL    &lt;br /&gt;&amp;#160; , DB_NAME(Blocked.database_id) AS DatabaseName    &lt;br /&gt;FROM sys.dm_exec_connections AS Blocking&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;INNER JOIN sys.dm_exec_requests AS Blocked     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON Blocking.session_id = Blocked.blocking_session_id     &lt;br /&gt;INNER JOIN sys.dm_exec_sessions Sess     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON Blocking.session_id = sess.session_id&amp;#160; &lt;br /&gt;INNER JOIN sys.dm_tran_session_transactions st     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON Blocking.session_id = st.session_id    &lt;br /&gt;LEFT OUTER JOIN sys.dm_exec_requests er     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON st.session_id = er.session_id    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AND er.session_id IS NULL    &lt;br /&gt;INNER JOIN sys.dm_os_waiting_tasks AS Waits     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON Blocked.session_id = Waits.session_id     &lt;br /&gt;CROSS APPLY sys.dm_exec_sql_text(Blocking.most_recent_sql_handle)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS BlockingSQL    &lt;br /&gt;INNER JOIN sys.dm_exec_requests AS BlockedReq&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON Waits.session_id = BlockedReq.session_id     &lt;br /&gt;INNER JOIN sys.dm_exec_sessions AS BlockedSess     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ON Waits.session_id = BlockedSess.session_id     &lt;br /&gt;CROSS APPLY sys.dm_exec_sql_text(Blocked.sql_handle) AS BlockedSQL     &lt;br /&gt;WHERE Waits.wait_duration_ms &amp;gt; 30000     &lt;br /&gt;ORDER BY WaitInSeconds&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;buffer中缓存每个数据库所占的buffer&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;SET TRAN ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ISNULL(DB_NAME(database_id), 'ResourceDb') AS DatabaseName    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , CAST(COUNT(row_count) * 8.0 / (1024.0) AS DECIMAL(28,2))     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS [Size (MB)]     &lt;br /&gt;FROM sys.dm_os_buffer_descriptors     &lt;br /&gt;GROUP BY database_id     &lt;br /&gt;ORDER BY DatabaseName&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;结果如图:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171452577539.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="2" border="0" alt="2" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171452583536.png" width="430" height="215" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;当前数据库中每个表所占缓存的大小和页数&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; OBJECT_NAME(p.[object_id]) AS [TableName]     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; , (COUNT(*) * 8) / 1024&amp;#160;&amp;#160; AS [Buffer size(MB)]    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; , ISNULL(i.name, '-- HEAP --') AS ObjectName    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ,&amp;#160; COUNT(*) AS NumberOf8KPages    &lt;br /&gt;FROM sys.allocation_units AS a     &lt;br /&gt;INNER JOIN sys.dm_os_buffer_descriptors AS b    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ON a.allocation_unit_id = b.allocation_unit_id    &lt;br /&gt;INNER JOIN sys.partitions AS p     &lt;br /&gt;INNER JOIN sys.indexes i ON p.index_id = i.index_id     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AND p.[object_id] = i.[object_id]     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ON a.container_id = p.hobt_id    &lt;br /&gt;WHERE b.database_id = DB_ID()    &lt;br /&gt;&amp;#160; AND p.[object_id] &amp;gt; 100    &lt;br /&gt;GROUP BY p.[object_id], i.name     &lt;br /&gt;ORDER BY NumberOf8KPages DESC&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;结果如下:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/20120517145302566.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="3" border="0" alt="3" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/20120517145304957.png" width="656" height="258" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;数据库级别等待的IO&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;SET TRAN ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT DB_NAME(database_id) AS [DatabaseName]    &lt;br /&gt;&amp;#160; , SUM(CAST(io_stall / 1000.0 AS DECIMAL(20,2))) AS [IO stall (secs)]    &lt;br /&gt;&amp;#160; , SUM(CAST(num_of_bytes_read / 1024.0 / 1024.0 AS DECIMAL(20,2)))     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS [IO read (MB)    &lt;br /&gt;&amp;#160; , SUM(CAST(num_of_bytes_written / 1024.0 / 1024.0&amp;#160; AS DECIMAL(20,2)))     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS [IO written (MB)    &lt;br /&gt;&amp;#160; , SUM(CAST((num_of_bytes_read + num_of_bytes_written)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; / 1024.0 / 1024.0 AS DECIMAL(20,2))) AS [TotalIO (MB)    &lt;br /&gt;FROM sys.dm_io_virtual_file_stats(NULL, NULL)    &lt;br /&gt;GROUP BY database_id     &lt;br /&gt;ORDER BY [IO stall (secs)] DESC&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;结果如下:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171453057237.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="4" border="0" alt="4" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171453065710.png" width="558" height="168" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;按文件查看IO情况&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;SET TRAN ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT DB_NAME(database_id) AS [DatabaseName]    &lt;br /&gt;&amp;#160; , file_id    &lt;br /&gt;&amp;#160; , SUM(CAST(io_stall / 1000.0 AS DECIMAL(20,2))) AS [IO stall (secs)]    &lt;br /&gt;&amp;#160; , SUM(CAST(num_of_bytes_read / 1024.0 / 1024.0 AS DECIMAL(20,2)))     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS [IO read (MB)]    &lt;br /&gt;&amp;#160; , SUM(CAST(num_of_bytes_written / 1024.0 / 1024.0&amp;#160; AS DECIMAL(20,2)))     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS [IO written (MB)]    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; , SUM(CAST((num_of_bytes_read + num_of_bytes_written)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; / 1024.0 / 1024.0 AS DECIMAL(20,2))) AS [TotalIO (MB)]     &lt;br /&gt;FROM sys.dm_io_virtual_file_stats(NULL, NULL)    &lt;br /&gt;GROUP BY database_id, file_id     &lt;br /&gt;ORDER BY [IO stall (secs)] DESC&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;结果如下:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/20120517145308528.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="5" border="0" alt="5" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/20120517145313523.png" width="602" height="243" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/CareySon/aggbug/2506223.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/CareySon/archive/2012/05/17/2506223.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/CareySon/archive/2012/05/17/2506035.html</id><title type="text">有关查询和执行计划的DMV</title><summary type="text">查看被缓存的查询计划 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 st.text AS [SQL] , cp.cacheobjtype , cp.objtype , COALESCE(DB_NAME(st.dbid), DB_NAME(CAST(pa.value AS INT))+'*', 'Resource') AS [DatabaseName] , cp.usecounts AS [P...</summary><published>2012-05-17T05:02:00Z</published><updated>2012-05-17T05:02:00Z</updated><author><name>CareySon</name><uri>http://www.cnblogs.com/CareySon/</uri></author><link rel="alternate" href="http://www.cnblogs.com/CareySon/archive/2012/05/17/2506035.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/CareySon/archive/2012/05/17/2506035.html"/><content type="html">&lt;p&gt;&lt;font color="#0000ff"&gt;查看被缓存的查询计划&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT TOP 20    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; st.text AS [SQL]    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , cp.cacheobjtype    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , cp.objtype    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , COALESCE(DB_NAME(st.dbid),     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DB_NAME(CAST(pa.value AS INT))+'*',     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 'Resource') AS [DatabaseName]     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , cp.usecounts AS [Plan usage]    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , qp.query_plan     &lt;br /&gt;FROM sys.dm_exec_cached_plans cp&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st     &lt;br /&gt;CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) qp     &lt;br /&gt;OUTER APPLY sys.dm_exec_plan_attributes(cp.plan_handle) pa    &lt;br /&gt;WHERE pa.attribute = 'dbid'    &lt;br /&gt;&amp;#160; AND st.text LIKE '%这里是查询语句包含的内容%'&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;结果是:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171300102965.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="1" border="0" alt="1" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171300222201.png" width="903" height="236" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;可以根据查询字段来根据关键字查看缓冲的查询计划。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;查看某一查询是如何使用查询计划的&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT TOP 20     &lt;br /&gt;&amp;#160; SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160; ((CASE WHEN qs.statement_end_offset = -1     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ELSE qs.statement_end_offset    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; END - qs.statement_start_offset)/2) + 1) AS [Individual Query]    &lt;br /&gt;&amp;#160; , qt.text AS [Parent Query]    &lt;br /&gt;&amp;#160; , DB_NAME(qt.dbid) AS DatabaseName     &lt;br /&gt;&amp;#160; , qp.query_plan     &lt;br /&gt;FROM sys.dm_exec_query_stats qs     &lt;br /&gt;CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt     &lt;br /&gt;CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp     &lt;br /&gt;WHERE SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,     &lt;br /&gt;&amp;#160; ((CASE WHEN qs.statement_end_offset = -1     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ELSE qs.statement_end_offset    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; END - qs.statement_start_offset)/2) + 1)    &lt;br /&gt;LIKE '%指定查询包含的字段%'&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;结果是:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171300308584.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="2" border="0" alt="2" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171300355024.png" width="906" height="221" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;查看数据库中跑的最慢的前20个查询以及它们的执行计划&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT TOP 20     &lt;br /&gt;&amp;#160; CAST(qs.total_elapsed_time / 1000000.0 AS DECIMAL(28, 2))     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS [Total Duration (s)]    &lt;br /&gt;&amp;#160; , CAST(qs.total_worker_time * 100.0 / qs.total_elapsed_time     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS DECIMAL(28, 2)) AS [% CPU]    &lt;br /&gt;&amp;#160; , CAST((qs.total_elapsed_time - qs.total_worker_time)* 100.0 /     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; qs.total_elapsed_time AS DECIMAL(28, 2)) AS [% Waiting]    &lt;br /&gt;&amp;#160; , qs.execution_count    &lt;br /&gt;&amp;#160; , CAST(qs.total_elapsed_time / 1000000.0 / qs.execution_count     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS DECIMAL(28, 2)) AS [Average Duration (s)]    &lt;br /&gt;&amp;#160; , SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ((CASE WHEN qs.statement_end_offset = -1     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ELSE qs.statement_end_offset    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; END - qs.statement_start_offset)/2) + 1) AS [Individual Query    &lt;br /&gt;&amp;#160; , qt.text AS [Parent Query]    &lt;br /&gt;&amp;#160; , DB_NAME(qt.dbid) AS DatabaseName     &lt;br /&gt;&amp;#160; , qp.query_plan    &lt;br /&gt;FROM sys.dm_exec_query_stats qs     &lt;br /&gt;CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt     &lt;br /&gt;CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp     &lt;br /&gt;WHERE qs.total_elapsed_time &amp;gt; 0     &lt;br /&gt;ORDER BY qs.total_elapsed_time DESC&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171300412346.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="3" border="0" alt="3" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171300567173.png" width="923" height="244" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;查看数据库中哪个查询最耗费资源有助于你解决问题&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;被阻塞时间最长的前20个查询以及它们的执行计划&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT TOP 20     &lt;br /&gt;&amp;#160; CAST((qs.total_elapsed_time - qs.total_worker_time) /&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1000000.0 AS DECIMAL(28,2)) AS [Total time blocked (s)]    &lt;br /&gt;&amp;#160; , CAST(qs.total_worker_time * 100.0 / qs.total_elapsed_time     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS DECIMAL(28,2)) AS [% CPU]    &lt;br /&gt;&amp;#160; , CAST((qs.total_elapsed_time - qs.total_worker_time)* 100.0 /     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; qs.total_elapsed_time AS DECIMAL(28, 2)) AS [% Waiting]    &lt;br /&gt;&amp;#160; , qs.execution_count    &lt;br /&gt;&amp;#160; , CAST((qs.total_elapsed_time&amp;#160; - qs.total_worker_time) / 1000000.0     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; / qs.execution_count AS DECIMAL(28, 2)) AS [Blocking average (s)]    &lt;br /&gt;&amp;#160; , SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160; ((CASE WHEN qs.statement_end_offset = -1     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ELSE qs.statement_end_offset    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; END - qs.statement_start_offset)/2) + 1) AS [Individual Query]     &lt;br /&gt;&amp;#160; , qt.text AS [Parent Query]    &lt;br /&gt;&amp;#160; , DB_NAME(qt.dbid) AS DatabaseName     &lt;br /&gt;&amp;#160; , qp.query_plan    &lt;br /&gt;FROM sys.dm_exec_query_stats qs     &lt;br /&gt;CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt     &lt;br /&gt;CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp     &lt;br /&gt;WHERE qs.total_elapsed_time &amp;gt; 0     &lt;br /&gt;ORDER BY [Total time blocked (s)] DESC&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;结果如图:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171300582548.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="4" border="0" alt="4" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171301037003.png" width="876" height="234" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;找出这类查询也是数据库调优的必须品&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;最耗费CPU的前20个查询以及它们的执行计划 &lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT TOP 20     &lt;br /&gt;&amp;#160; CAST((qs.total_worker_time) / 1000000.0 AS DECIMAL(28,2))     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS [Total CPU time (s)]    &lt;br /&gt;&amp;#160; , CAST(qs.total_worker_time * 100.0 / qs.total_elapsed_time     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS DECIMAL(28,2)) AS [% CPU]    &lt;br /&gt;&amp;#160; , CAST((qs.total_elapsed_time - qs.total_worker_time)* 100.0 /     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; qs.total_elapsed_time AS DECIMAL(28, 2)) AS [% Waiting]    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; , qs.execution_count    &lt;br /&gt;&amp;#160; , CAST((qs.total_worker_time) / 1000000.0     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; / qs.execution_count AS DECIMAL(28, 2)) AS [CPU time average (s)]    &lt;br /&gt;&amp;#160; , SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ((CASE WHEN qs.statement_end_offset = -1     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ELSE qs.statement_end_offset    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; END - qs.statement_start_offset)/2) + 1) AS [Individual Query]     &lt;br /&gt;&amp;#160; , qt.text AS [Parent Query]    &lt;br /&gt;&amp;#160; , DB_NAME(qt.dbid) AS DatabaseName     &lt;br /&gt;&amp;#160; , qp.query_plan     &lt;br /&gt;FROM sys.dm_exec_query_stats qs     &lt;br /&gt;CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt     &lt;br /&gt;CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp     &lt;br /&gt;WHERE qs.total_elapsed_time &amp;gt; 0     &lt;br /&gt;ORDER BY [Total CPU time (s)] DESC&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;原理同上，就不上图了&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;最占IO的前20个查询以及它们的执行计划&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT TOP 20     &lt;br /&gt;&amp;#160; [Total IO] = (qs.total_logical_reads + qs.total_logical_writes)    &lt;br /&gt;&amp;#160; , [Average IO] = (qs.total_logical_reads + qs.total_logical_writes) /    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; qs.execution_count    &lt;br /&gt;&amp;#160; , qs.execution_count    &lt;br /&gt;&amp;#160; , SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160; ((CASE WHEN qs.statement_end_offset = -1     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ELSE qs.statement_end_offset    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; END - qs.statement_start_offset)/2) + 1) AS [Individual Query]     &lt;br /&gt;&amp;#160; , qt.text AS [Parent Query]    &lt;br /&gt;&amp;#160; , DB_NAME(qt.dbid) AS DatabaseName     &lt;br /&gt;&amp;#160; , qp.query_plan    &lt;br /&gt;FROM sys.dm_exec_query_stats qs     &lt;br /&gt;CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt     &lt;br /&gt;CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp     &lt;br /&gt;ORDER BY [Total IO] DESC&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&lt;/p&gt;  &lt;p&gt;结果如图:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171301067786.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="5" border="0" alt="5" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171301085079.png" width="912" height="153" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;能帮助找出占IO的查询&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt; 查找被执行次数最多的查询以及它们的执行计划&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT TOP 20     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; qs.execution_count    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ((CASE WHEN qs.statement_end_offset = -1     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ELSE qs.statement_end_offset    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; END - qs.statement_start_offset)/2) + 1) AS [Individual Query]     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , qt.text AS [Parent Query]    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , DB_NAME(qt.dbid) AS DatabaseName    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , qp.query_plan    &lt;br /&gt;FROM sys.dm_exec_query_stats qs     &lt;br /&gt;CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt     &lt;br /&gt;CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp     &lt;br /&gt;ORDER BY qs.execution_count DESC;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;结果如图:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171301196747.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="6" border="0" alt="6" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171301204630.png" width="917" height="141" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;可以针对用的最多的查询语句做特定优化。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;特定语句的最后运行时间&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED   &lt;br /&gt;SELECT DISTINCT TOP 20     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; qs.last_execution_time     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , qt.text AS [Parent Query]    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , DB_NAME(qt.dbid) AS DatabaseName     &lt;br /&gt;FROM sys.dm_exec_query_stats qs&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt     &lt;br /&gt;WHERE qt.text LIKE '%特定语句的部分%'     &lt;br /&gt;ORDER BY qs.last_execution_time DESC&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;结果如图:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171301325012.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="7" border="0" alt="7" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171301371485.png" width="694" height="204" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/CareySon/aggbug/2506035.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/CareySon/archive/2012/05/17/2506035.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/CareySon/archive/2012/05/17/2505981.html</id><title type="text">有关索引的DMV</title><summary type="text">有关索引的DMV 1.查看那些被大量更新，却很少被使用的索引 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT DB_NAME() AS DatabaseName , SCHEMA_NAME(o.Schema_ID) AS SchemaName , OBJECT_NAME(s.[object_id]) AS TableName , i.name A...</summary><published>2012-05-17T03:57:00Z</published><updated>2012-05-17T03:57:00Z</updated><author><name>CareySon</name><uri>http://www.cnblogs.com/CareySon/</uri></author><link rel="alternate" href="http://www.cnblogs.com/CareySon/archive/2012/05/17/2505981.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/CareySon/archive/2012/05/17/2505981.html"/><content type="html">&lt;p&gt;有关索引的DMV&lt;/p&gt;  &lt;p&gt;1.&lt;font color="#0000ff"&gt;查看那些被大量更新，却很少被使用的索引&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED     &lt;br /&gt;SELECT&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DB_NAME() AS DatabaseName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , SCHEMA_NAME(o.Schema_ID) AS SchemaName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , OBJECT_NAME(s.[object_id]) AS TableName       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , i.name AS IndexName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.user_updates      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.system_seeks + s.system_scans + s.system_lookups       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS [System usage]      &lt;br /&gt;INTO #TempUnusedIndexes       &lt;br /&gt;FROM&amp;#160;&amp;#160; sys.dm_db_index_usage_stats s       &lt;br /&gt;INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND s.index_id = i.index_id       &lt;br /&gt;INNER JOIN sys.objects o ON i.object_id = O.object_id&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;WHERE 1=2      &lt;br /&gt;EXEC sp_MSForEachDB 'USE [?];&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;INSERT INTO #TempUnusedIndexes       &lt;br /&gt;SELECT TOP 20      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DB_NAME() AS DatabaseName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , SCHEMA_NAME(o.Schema_ID) AS SchemaName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , OBJECT_NAME(s.[object_id]) AS TableName       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , i.name AS IndexName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.user_updates       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.system_seeks + s.system_scans + s.system_lookups       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS [System usage]       &lt;br /&gt;FROM&amp;#160;&amp;#160; sys.dm_db_index_usage_stats s       &lt;br /&gt;INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND s.index_id = i.index_id       &lt;br /&gt;INNER JOIN sys.objects o ON i.object_id = O.object_id&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;WHERE s.database_id = DB_ID()      &lt;br /&gt;AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0       &lt;br /&gt;AND s.user_seeks = 0      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND s.user_scans = 0       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND s.user_lookups = 0      &lt;br /&gt;AND i.name IS NOT NULL       &lt;br /&gt;ORDER BY s.user_updates DESC'&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;SELECT TOP 20 * FROM #TempUnusedIndexes ORDER BY [user_updates] DESC      &lt;br /&gt;DROP TABLE #TempUnusedIndexes&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;结果如图:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171156491192.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="1" border="0" alt="1" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171156508650.png" width="594" height="233" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;这类索引应该被Drop掉&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff" face="微软雅黑"&gt;最高维护代价的索引&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED     &lt;br /&gt;SELECT&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DB_NAME() AS DatabaseName       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , SCHEMA_NAME(o.Schema_ID) AS SchemaName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , OBJECT_NAME(s.[object_id]) AS TableName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , i.name AS IndexName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , (s.user_updates ) AS [update usage]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , (s.user_seeks + s.user_scans + s.user_lookups) AS [Retrieval usage]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , (s.user_updates) -       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (s.user_seeks + s.user_scans + s.user_lookups) AS [Maintenance cost]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.system_seeks + s.system_scans + s.system_lookups AS [System usage]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.last_user_seek      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.last_user_scan      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.last_user_lookup       &lt;br /&gt;INTO #TempMaintenanceCost       &lt;br /&gt;FROM&amp;#160;&amp;#160; sys.dm_db_index_usage_stats s       &lt;br /&gt;INNER JOIN sys.indexes i ON&amp;#160; s.[object_id] = i.[object_id]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND s.index_id = i.index_id      &lt;br /&gt;INNER JOIN sys.objects o ON i.object_id = O.object_id&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;WHERE 1=2      &lt;br /&gt;EXEC sp_MSForEachDB 'USE [?];&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;INSERT INTO #TempMaintenanceCost       &lt;br /&gt;SELECT TOP 20      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DB_NAME() AS DatabaseName       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , SCHEMA_NAME(o.Schema_ID) AS SchemaName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , OBJECT_NAME(s.[object_id]) AS TableName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , i.name AS IndexName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , (s.user_updates ) AS [update usage]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , (s.user_seeks + s.user_scans + s.user_lookups)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS [Retrieval usage]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , (s.user_updates) -       &lt;br /&gt;(s.user_seeks + user_scans +       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; s.user_lookups) AS [Maintenance cost]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.system_seeks + s.system_scans + s.system_lookups AS [System usage]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.last_user_seek      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.last_user_scan      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.last_user_lookup       &lt;br /&gt;FROM&amp;#160;&amp;#160; sys.dm_db_index_usage_stats s       &lt;br /&gt;INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND s.index_id = i.index_id      &lt;br /&gt;INNER JOIN sys.objects o ON i.object_id = O.object_id&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;WHERE s.database_id = DB_ID()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND i.name IS NOT NULL       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND (s.user_seeks + s.user_scans + s.user_lookups) &amp;gt; 0       &lt;br /&gt;ORDER BY [Maintenance cost] DESC'&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;SELECT top 20 * FROM #TempMaintenanceCost ORDER BY [Maintenance cost] DESC      &lt;br /&gt;DROP TABLE #TempMaintenanceCost&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;结果如图:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171156504157.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="2" border="0" alt="2" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171156515204.png" width="889" height="239" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;Maintenance cost高的应该被Drop掉&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff" face="微软雅黑"&gt;使用频繁的索引&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;--使用频繁的索引     &lt;br /&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED      &lt;br /&gt;SELECT&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DB_NAME() AS DatabaseName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; , SCHEMA_NAME(o.Schema_ID) AS SchemaName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , OBJECT_NAME(s.[object_id]) AS TableName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , i.name AS IndexName       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , (s.user_seeks + s.user_scans + s.user_lookups) AS [Usage]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.user_updates      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , i.fill_factor      &lt;br /&gt;INTO #TempUsage       &lt;br /&gt;FROM sys.dm_db_index_usage_stats s       &lt;br /&gt;INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND s.index_id = i.index_id       &lt;br /&gt;INNER JOIN sys.objects o ON i.object_id = O.object_id&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;WHERE 1=2      &lt;br /&gt;EXEC sp_MSForEachDB 'USE [?];&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;INSERT INTO #TempUsage       &lt;br /&gt;SELECT TOP 20      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DB_NAME() AS DatabaseName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , SCHEMA_NAME(o.Schema_ID) AS SchemaName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , OBJECT_NAME(s.[object_id]) AS TableName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , i.name AS IndexName       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , (s.user_seeks + s.user_scans + s.user_lookups) AS [Usage]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.user_updates      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , i.fill_factor      &lt;br /&gt;FROM&amp;#160;&amp;#160; sys.dm_db_index_usage_stats s       &lt;br /&gt;INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AND s.index_id = i.index_id       &lt;br /&gt;INNER JOIN sys.objects o ON i.object_id = O.object_id&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;WHERE s.database_id = DB_ID()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND i.name IS NOT NULL       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0       &lt;br /&gt;ORDER BY [Usage] DESC'&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;SELECT TOP 20 * FROM #TempUsage ORDER BY [Usage] DESC      &lt;br /&gt;DROP TABLE #TempUsage&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;结果如图&lt;/p&gt;    &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/20120517115651711.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="3" border="0" alt="3" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171156513502.png" width="853" height="235" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;这类索引需要格外注意，不要在优化的时候干掉&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff" face="微软雅黑"&gt;碎片最多的索引&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff" size="3" face="微软雅黑"&gt;&lt;/font&gt;      &lt;br /&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED      &lt;br /&gt;SELECT&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DB_NAME() AS DatbaseName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , SCHEMA_NAME(o.Schema_ID) AS SchemaName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , OBJECT_NAME(s.[object_id]) AS TableName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , i.name AS IndexName       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , ROUND(s.avg_fragmentation_in_percent,2) AS [Fragmentation %]       &lt;br /&gt;INTO #TempFragmentation       &lt;br /&gt;FROM sys.dm_db_index_physical_stats(db_id(),null, null, null, null) s       &lt;br /&gt;INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND s.index_id = i.index_id       &lt;br /&gt;INNER JOIN sys.objects o ON i.object_id = O.object_id&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;WHERE 1=2      &lt;br /&gt;EXEC sp_MSForEachDB 'USE [?];&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;INSERT INTO #TempFragmentation       &lt;br /&gt;SELECT TOP 20      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DB_NAME() AS DatbaseName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , SCHEMA_NAME(o.Schema_ID) AS SchemaName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , OBJECT_NAME(s.[object_id]) AS TableName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , i.name AS IndexName       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , ROUND(s.avg_fragmentation_in_percent,2) AS [Fragmentation %]       &lt;br /&gt;FROM sys.dm_db_index_physical_stats(db_id(),null, null, null, null) s       &lt;br /&gt;INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id]       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; AND s.index_id = i.index_id       &lt;br /&gt;INNER JOIN sys.objects o ON i.object_id = O.object_id&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;WHERE s.database_id = DB_ID()       &lt;br /&gt;&amp;#160; AND i.name IS NOT NULL      &lt;br /&gt;&amp;#160; AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0       &lt;br /&gt;ORDER BY [Fragmentation %] DESC'&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;SELECT top 20 * FROM #TempFragmentation ORDER BY [Fragmentation %] DESC      &lt;br /&gt;DROP TABLE #TempFragmentation&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;结果如下:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171156525105.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="4" border="0" alt="4" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171156528976.png" width="825" height="245" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;这类索引需要Rebuild,否则会严重拖累数据库性能&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff" face="微软雅黑"&gt;自上次SQL Server重启后，找出完全没有使用的索引&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED     &lt;br /&gt;SELECT&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DB_NAME() AS DatbaseName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , SCHEMA_NAME(O.Schema_ID) AS SchemaName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , OBJECT_NAME(I.object_id) AS TableName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , I.name AS IndexName      &lt;br /&gt;INTO #TempNeverUsedIndexes       &lt;br /&gt;FROM sys.indexes I INNER JOIN sys.objects O ON I.object_id = O.object_id       &lt;br /&gt;WHERE 1=2      &lt;br /&gt;EXEC sp_MSForEachDB 'USE [?];&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;INSERT INTO #TempNeverUsedIndexes       &lt;br /&gt;SELECT       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; DB_NAME() AS DatbaseName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , SCHEMA_NAME(O.Schema_ID) AS SchemaName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , OBJECT_NAME(I.object_id) AS TableName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , I.NAME AS IndexName      &lt;br /&gt;FROM sys.indexes I INNER JOIN sys.objects O ON I.object_id = O.object_id      &lt;br /&gt;LEFT OUTER JOIN sys.dm_db_index_usage_stats S ON S.object_id = I.object_id      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AND I.index_id = S.index_id      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AND DATABASE_ID = DB_ID()      &lt;br /&gt;WHERE OBJECTPROPERTY(O.object_id,''IsMsShipped'') = 0      &lt;br /&gt;&amp;#160; AND I.name IS NOT NULL      &lt;br /&gt;&amp;#160; AND S.object_id IS NULL'      &lt;br /&gt;SELECT * FROM #TempNeverUsedIndexes&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;ORDER BY DatbaseName, SchemaName, TableName, IndexName       &lt;br /&gt;DROP TABLE #TempNeverUsedIndexes&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;结果如图:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/20120517115652579.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="5" border="0" alt="5" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171156523370.png" width="514" height="231" /&gt;&lt;/a&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;这类索引应该小心对待，不能一概而论，要看是什么原因导致这种问题&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&lt;font color="#0000ff" face="微软雅黑"&gt;查看索引统计的相关信息&lt;/font&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED     &lt;br /&gt;SELECT       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ss.name AS SchemaName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , st.name AS TableName      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.name AS IndexName       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , STATS_DATE(s.id,s.indid) AS 'Statistics Last Updated'      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.rowcnt AS 'Row Count'      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , s.rowmodctr AS 'Number Of Changes'       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; , CAST((CAST(s.rowmodctr AS DECIMAL(28,8))/CAST(s.rowcnt AS       &lt;br /&gt;DECIMAL(28,2)) * 100.0)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; AS DECIMAL(28,2)) AS '% Rows Changed'       &lt;br /&gt;FROM sys.sysindexes s       &lt;br /&gt;INNER JOIN sys.tables st ON st.[object_id] = s.[id]      &lt;br /&gt;INNER JOIN sys.schemas ss ON ss.[schema_id] = st.[schema_id]       &lt;br /&gt;WHERE s.id &amp;gt; 100      &lt;br /&gt;&amp;#160; AND s.indid &amp;gt; 0      &lt;br /&gt;&amp;#160; AND s.rowcnt &amp;gt;= 500      &lt;br /&gt;ORDER BY SchemaName, TableName, IndexName &lt;/p&gt;    &lt;p&gt;     &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;结果如下:&lt;/p&gt;    &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/20120517115653513.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="6" border="0" alt="6" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205171156533304.png" width="896" height="212" /&gt;&lt;/a&gt;      &lt;br /&gt;&lt;/p&gt; &lt;/div&gt; &lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;            &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;因为查询计划是根据统计信息来的，索引的选择同样取决于统计信息，所以根据统计信息更新的多寡可以看出数据库的大体状况，20%的自动更新对于大表来说非常慢。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/CareySon/aggbug/2505981.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/CareySon/archive/2012/05/17/2505981.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/CareySon/archive/2012/05/14/HowStatisticImpactQuery.html</id><title type="text">浅谈SQL Server中统计对于查询的影响</title><summary type="text">简介 SQL Server查询分析器是基于开销的。通常来讲，查询分析器会根据谓词来确定该如何选择高效的查询路线,比如该选择哪个索引。而每次查询分析器寻找路径时，并不会每一次都去统计索引中包含的行数，值的范围等，而是根据一定条件创建和更新这些信息后保存到数据库中，这也就是所谓的统计信息。 如何查看统计信息 查看SQL Server的统计信息非常简单，使用如下指令： ...</summary><published>2012-05-14T08:31:00Z</published><updated>2012-05-14T08:31:00Z</updated><author><name>CareySon</name><uri>http://www.cnblogs.com/CareySon/</uri></author><link rel="alternate" href="http://www.cnblogs.com/CareySon/archive/2012/05/14/HowStatisticImpactQuery.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/CareySon/archive/2012/05/14/HowStatisticImpactQuery.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;简介&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; SQL Server查询分析器是基于开销的。通常来讲，查询分析器会根据谓词来确定该如何选择高效的查询路线,比如该选择哪个索引。而每次查询分析器寻找路径时，并不会每一次都去统计索引中包含的行数，值的范围等，而是根据一定条件创建和更新这些信息后保存到数据库中，这也就是所谓的统计信息。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;如何查看统计信息&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 查看SQL Server的统计信息非常简单，使用如下指令：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; DBCC SHOW_STATISTICS('表名','索引名')&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 所得到的结果如图1所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/20120514162559370.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="1" border="0" alt="1" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/20120514162846404.png" width="930" height="582" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图1.统计信息&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;统计信息如何影响查询&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 下面我们通过一个简单的例子来看统计信息是如何影响查询分析器。我建立一个测试表，有两个INT值的列，其中id为自增，ref上建立非聚集索引，插入100条数据，从1到100，再插入9900条等于100的数据。图1中的统计信息就是示例数据的统计信息。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 此时，我where后使用ref值作为查询条件，但是给定不同的值，我们可以看出根据统计信息，查询分析器做出了不同的选择，如图2所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205141628524727.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="3" border="0" alt="3" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205141628555510.png" width="614" height="500" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 图2.根据不同的谓词，查询优化器做了不同的选择&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 其实，对于查询分析器来说，柱状图对于直接可以确定的谓词非常管用，这些谓词比如:&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; where date = getdate()    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; where id= 12345     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; where monthly_sales &amp;lt; 10000 / 12     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; where name like “Careyson” + “%”&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 但是对于比如&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; where price = @vari    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; where total_sales &amp;gt; (select sum(qty) from sales)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; where a.id =b.ref_id&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; where col1 =1 and col2=2&lt;/p&gt;  &lt;p&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这类在运行时才能知道值的查询，采样步长就明显不是那么好用了。另外，上面第四行如果谓词是两个查询条件，使用采样步长也并不好用。因为无论索引有多少列，采样步长仅仅存储索引的第一列。当柱状图不再好用时，SQL Server使用密度来确定最佳的查询路线。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 密度的公式是：1/表中唯一值的 个数。当密度越小时，索引越容易被选中。比如图1中的第二个表，我们可以通过如下公式来计算一下密度:&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205141628575901.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="4" border="0" alt="4" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205141628583784.png" width="559" height="181" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图3.某一列的密度&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 根据公式可以推断，当表中的数据量逐渐增大时，密度会越来越小。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 对于那些不能根据采样步长做出选择的查询，查询分析器使用密度来估计行数,这个公式为:估计的行数=表中的行数*密度&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 那么，根据这个公式，如果我做查询时，估计的行数就会为如图4所示的数字。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205141629038239.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="5" border="0" alt="5" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/20120514162908219.png" width="782" height="229" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图4.估计的行数&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 我们来验证一下这个结论,如图5所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205141629184245.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="6" border="0" alt="6" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205141629238111.png" width="457" height="508" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图5.估计的行数&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 因此，可以看出，估计的行数是和实际的行数有出入的，当数据分布均匀时，或者数据量大时，这个误差将会变的非常小。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;统计信息的更新&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 由上面的例子可以看到，查询分析器由于依赖于统计信息进行查询，那么过时的统计信息则可能导致低效率的查询。统计信息既可以由SQL Server来进行管理，也可以手动进行更新，也可以由SQL Server管理更新时手动更新。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 当开启了自动更新后，SQL Server监控表中的数据更改，当达到临界值时则会自动更新数据。这个标准是:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; 向空表插入数据时 &lt;/li&gt;    &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; 少于500行的表增加500行或者更多 &lt;/li&gt;    &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; 当表中行多于500行时，数据的变化量大于20%时 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 上述条件的满足均会导致统计被更新。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 当然，我们也可以使用如下语句手动更新统计信息。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; UPDATE STATISTICS 表名[索引名]&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;列级统计信息&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; SQL Server还可以针对不属于任何索引的列创建统计信息来帮助查询分析器获取”估计的行数“.当我们开启数据库级别的选项“自动创建统计信息”如图6所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205141629279667.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="7" border="0" alt="7" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205141629332038.png" width="708" height="636" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图6.自动创建统计信息&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; 当这个选项设置为True时，当我们where谓词指定了不在任何索引上的列时，列的统计信息会被创建，但是会有以下两种情况例外:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; 创建统计信息的成本超过生成查询计划的成本 &lt;/li&gt;    &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; 当SQL Server忙时不会自动生成统计信息 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; 我们可以通过系统视图sys.stats来查看这些统计信息,如图7所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/20120514162945750.png"&gt;&lt;img style="background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px" title="8" border="0" alt="8" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205141630385411.png" width="726" height="361" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图7.通过系统视图查看统计信息&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 当然，也可以通过如下语句手动创建统计信息:&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; CREATE STATISTICS 统计名称 ON 表名 (列名 [,...n]) &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;总结&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 本文简单谈了统计信息对于查询路径选择的影响。过时的统计信息很容易造成查询性能的降低。因此，定期更新统计信息是DBA重要的工作之一。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/CareySon/aggbug/2499572.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/CareySon/archive/2012/05/14/HowStatisticImpactQuery.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/CareySon/archive/2012/05/08/HowRAIDImpactSQLServer.html</id><title type="text">【译】RAID的概念和RAID对于SQL性能的影响</title><summary type="text">简介 我们都听说过RAID，也经常作为SQL DBA、开发人员或构架师在工作中讨论RAID。但是，其实我们很多人都对RAID的原理，等级，以及RAID是如何影响SQL Server性能并不甚了解。 本篇文章就是为了补上这一课。 磁盘构架 今天的磁盘，和70年代45rpm(转/分钟)的唱片机很像(你还能记得吗?),仅仅是一个有着轴(磁道)旋转的媒体(面)并将数据存入称之为扇区的磁盘段。 就像唱片机那样，磁盘驱动器拥有一个摆臂来控制针(在这里可以称之为”磁头”)来访问数据。但对于磁盘来说，并不像唱片机那样只读，而是既可以读又可以写。 为了从...</summary><published>2012-05-08T08:56:00Z</published><updated>2012-05-08T08:56:00Z</updated><author><name>CareySon</name><uri>http://www.cnblogs.com/CareySon/</uri></author><link rel="alternate" href="http://www.cnblogs.com/CareySon/archive/2012/05/08/HowRAIDImpactSQLServer.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/CareySon/archive/2012/05/08/HowRAIDImpactSQLServer.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;简介&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 我们都听说过RAID，也经常作为SQL DBA、开发人员或构架师在工作中讨论RAID。但是，其实我们很多人都对RAID的原理，等级，以及RAID是如何影响SQL Server性能并不甚了解。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 本篇文章就是为了补上这一课。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;磁盘构架&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 今天的磁盘，和70年代45rpm(转/分钟)的唱片机很像(你还能记得吗?),仅仅是一个有着轴(磁道)旋转的媒体(面)并将数据存入称之为扇区的磁盘段。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 就像唱片机那样，磁盘驱动器拥有一个摆臂来控制针(在这里可以称之为”磁头”)来访问数据。但对于磁盘来说，并不像唱片机那样只读，而是既可以读又可以写。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 为了从特定的扇区读或者写数据，磁盘必须进行旋转然后摆臂移动使得磁头移动到垂直于指定扇区的正上方以访问数据。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这个过程就是基本的输入/输出操作的过程(I/O)。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;IOPS&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; IOPS这个术语也是被经常拿出来装X的，但同样，对这个术语真正理解的人并不多。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 很多人都明白IOPS是Input Output Operations per Second的缩写，但是将这个定义转换为实际的概念对于某些人就有点难了。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 对IOPS基本的理解是对满足特定输入输出请求的平均时间的一种衡量。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这里重点需要知道这个度量标准是基于读取0字节的文件,这仅仅是为了统计和标准化的目的因为一个磁盘扇区大小并不同。&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;物理磁盘的限制&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 磁盘会有一些物理限制会限制磁盘能达到的IOP级别。这个限制是磁道寻址时间(seek time)和旋转延迟(rotational latency)。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 磁道寻址时间是为了使得磁头可以移动到所要读的扇区，移动摆臂所花费的平均时间。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 旋转延迟是为了使磁头读取盘面特定位置旋转磁盘所话费的时间（通常为毫秒级）。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 单位IOP所花的时间公式如下:&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;单位IOP时间=磁道寻址时间+旋转延迟&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 所以，通过这个公式我们就可以轻松计算给定磁盘的最大IOPS。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 而每秒的IOPS数字也是我们最感兴趣的，公式如下:&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; &lt;font color="#0000ff"&gt;1秒/磁道寻址时间+旋转延迟。&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 我们来看如下例子:&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="400" colspan="2"&gt;&lt;center&gt;HP 300GB 15k SAS drive（200刀）&lt;/center&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="200"&gt;转速&lt;/td&gt;        &lt;td valign="top" width="200"&gt;15000&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="200"&gt;平均磁道寻址时间&lt;/td&gt;        &lt;td valign="top" width="200"&gt;2.9ms&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="200"&gt;平均旋转延迟&lt;/td&gt;        &lt;td valign="top" width="200"&gt;1.83ms&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 我们可以用公式计算IOPS了:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;IOPS = 1/(2.9ms + 1.83ms)&amp;#160; &lt;br /&gt;&amp;#160; = 1/(4.73ms)&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160; = 1/(0.00473)&amp;#160; &lt;br /&gt;&amp;#160; = 211 IOPS &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/em&gt;我们可以看到，这个磁盘的IOPS为211（并不是很惨)。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 假如我们想要节省更多的钱，我们再来看一个磁盘的例子以及和上面磁盘的区别:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="400" colspan="2"&gt;&lt;center&gt;HP 300GB 7200 SATA drive（100刀）&lt;/center&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="200"&gt;转速&lt;/td&gt;        &lt;td valign="top" width="200"&gt;7200&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="200"&gt;平均磁道寻址时间&lt;/td&gt;        &lt;td valign="top" width="200"&gt;10ms&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="200"&gt;平均旋转延迟&lt;/td&gt;        &lt;td valign="top" width="200"&gt;2.1ms&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 通过公式可以看到这个磁盘的最大IOPS:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;IOPS = 1/(10ms + 2.1ms)&amp;#160; &lt;br /&gt;&amp;#160; =&amp;#160; 1/(12.1ms)       &lt;br /&gt;&amp;#160; =&amp;#160; 1/(0.0121)       &lt;br /&gt;&amp;#160; = 82 IOPS &lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&lt;/em&gt;&lt;em&gt;&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;em&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/em&gt;这个7200转的磁盘的最大IOPS为82。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 通过对比可以看到上面两个磁盘的性能上的巨大差异，这也不难理解为什么同样的容量价格会差这么多。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 此外，文档显示如果你使用磁盘到其IOPS峰值，会产生请求队列而造成&lt;font style="background-color: #ffffff" color="#0000ff"&gt;延迟&lt;/font&gt;（一个在SQL Server中非常邪恶的词汇，像躲避瘟疫一样躲避它）。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 而我看过的大多数文档建议IOP保持在最大IOPS的80%左右。所以我们上面讨论的第一个磁盘的最大IOPS是211如果服务于超过168的IOPS就会开始显出延迟的征兆了。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; 现在我已经知道了单独一个磁盘可以达到的IOPS数字，那么下一件事就是要满足生产环境下的SQL Server实例需要多少IOPS?&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 我获取这些数据仅仅通过在生产环境下查看PerfMon工具的physical disk: Disk Transfers/Sec 计数器。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这个数字是:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;table border="1" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="133"&gt;&lt;strong&gt;驱动&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="133"&gt;&lt;strong&gt;平均IOPS&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top" width="133"&gt;&lt;strong&gt;最大IOPS&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="133"&gt;数据和索引&lt;/td&gt;        &lt;td valign="top" width="133"&gt;2313&lt;/td&gt;        &lt;td valign="top" width="133"&gt;16,164&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="133"&gt;日志&lt;/td&gt;        &lt;td valign="top" width="133"&gt;81.5&lt;/td&gt;        &lt;td valign="top" width="133"&gt;1,127&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="133"&gt;TempDB&lt;/td&gt;        &lt;td valign="top" width="133"&gt;141&lt;/td&gt;        &lt;td valign="top" width="133"&gt;2,838&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 通过上面的数据看到，我们的快速磁盘仅仅能处理168的IOPS,所以结论是一个磁盘无论如何也无法满足上面的IOPS要求。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 所以解决这个问题的唯一办法是使用某种机制来调整多个磁盘满足上述需求。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 如果我们有100个300GB 15k SAS驱动器，我们不仅获得了30TB的存储量，还获得了16800的IOPS。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; 如果我们使用前面例子中较慢的磁盘，为了达到16800 IOPS,我们需要205块这样的驱动器，这使得我们需要比使用快速磁盘花更多的钱($20,000 vs $20,500),听上去很讽刺，不是吗？&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;RAID的必要性&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 现在，我们需要一堆磁盘来满足我们的速度或是容量需求，所以我们需要某种机制来将工作负载加到多个磁盘，实现这个目的的主要手段就是RAID。    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; RAID代表&amp;quot;Redundant Array &amp;lt;of&amp;gt; Inexpensive Disks&amp;quot;(译者注：这是最开始的定义，后来行业标准将I改为Independant,难道这是因为Inexpensive这个词妨碍了他们收取更多的钱?)，RAID提供了将一堆磁盘连接起来使得逻辑上变为1个的方法。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 基于你如何串联你的磁盘，RAID可以提供容错性—当磁盘阵列中有一个磁盘崩溃时数据不会丢失。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 此外,因为串联了多个磁盘，我们可以消除单个磁盘的IOPS限制，更多的磁盘意味着更多的IOPS，就是这么简单。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;RAID级别&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; RAID只为了两个目的:1)通过提高IOPS提高性能&amp;#160; 2)提供容错。更高的容错性意味着更低的磁盘性能，同样，高性能方案也会降低容错性。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 根据容错性和性能的目标配置RAID就是所谓的RAID层级。RAID是对常用的RAID阵列的一种分裂，常见的RAID级别为:RAID0,RAID1,RAID5,RAID1+0,RAID0+1。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 根据你对RAID级别的选择，你需要付出所谓的”RAID代价”。某些RAID级别需要重复写入两次数据来保证容错性，但这样会牺牲性能。此外，因为重复写入数据还需要更多的磁盘空间。RAID代价会大大提高你的RAID方案的成本。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 为了明白RAID对于你的系统的影响和收益，熟悉常见的RAID级别和它们的实现原理变得非常重要。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;RAID 0&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 第一个，也是最基本的RAID级别是RAID 0.RAID 0强调为了解决IO的限制而将数据写入到磁盘阵列中。如果IO希望写100MB的数据，RAID0会将100MB数据写入到磁盘阵列的每个磁盘中。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这种方式大大减少了每个磁盘的负载，并且减少了旋转延迟(每个磁盘不再需要转和原来一样的圈数就能满足请求）。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 虽然RAID0大大提高了IO性能，但没有提供任何容错措施，这意味着如果磁盘阵列中的某一块磁盘崩溃，则整个磁盘阵列中的数据全部丢失。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 因为RAID0并没有提供任何容错措施，所以在生产环境中RAID0几乎不被使用。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 还有一点值得注意的是，由于RAID0磁盘阵列中的每个磁盘都用于存储数据，所以没有任何磁盘空间的损失，比如使用RAID0,10个300GB的磁盘就会有3TB的可用存储空间，这意味着没有损失磁盘空间的RAID代价。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;RAID 1&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; RAID1也被称为”镜像”,因为其通过一个镜像磁盘来保证容错性。在镜像集中的每个磁盘都会有一个镜像磁盘，RAID 1写入的每一笔数据都会分别在两个磁盘中各写一份。这意味着任何一个磁盘除了问题，另一个磁盘就会顶上。用户的角度来看并不知道出现了磁盘崩溃。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; RAID 1需要付出写入时的性能代价。每个写入IOP需要运行两次，但是对于读来说却会提升性能，因为RAID控制器对于大量数据请求会从两个磁盘中读取。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;RAID 5&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; RAID 5也被称为”Striping With Parity)”,这种方式既可以通过磁盘分割(Striping raid0)来提高性能，也可以通过奇偶性(Parity)来提供容错，当一个磁盘崩溃后，奇偶数据可以通过计算重建丢失的数据。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 虽然奇偶性是实现容错的一种不错的方式。但是从磁盘写入来说代价高昂。也就是说对于每一个IOP写请求，RAID5需要4个IOPS。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 为什么需要这么高写入代价的过程如下:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; 读取原始数据(1 iop) &lt;/li&gt;    &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; 读取当前奇偶数据(1 iop) &lt;/li&gt;    &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; 比较当前数据和新写入请求 &lt;/li&gt;    &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; 基于数据差异计算新的奇偶值 &lt;/li&gt;    &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; 写入新数据(1 iop) &lt;/li&gt;    &lt;li&gt;&amp;#160;&amp;#160;&amp;#160; 写入新的奇偶值(1 iop) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;RAID 1+0&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160; RAID 1+0 和其名字所示那样，融合了RAID 0(磁盘分割）和RAID1(镜像)。这种方式也被称为:分割镜像。&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; RAID 1+0 由于将数据分割到多个磁盘中使得并且不像RAID5那样有奇偶效验码，所以写入速度非常快。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 但写入速度还是会有影响因为需要重复写入镜像盘，但仍然，写入速度还是非常的快。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 而对于RAID 1+0 存储的代价等同于RAID1 (镜像)，在RAID1+0中只有一半的磁盘空间可以用于存储数据。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;RAID 0+1&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; RAID 0+1 和RAID1 +0 是很像，它们都是通过磁盘分割和镜像来实现目的。他们的区别更加学术化，这里我们假设他们一样。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; RAID 0+1和 RAID 1+0所付出的代价是一样的。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;其它RAID级别(2,3,4,6,DP等)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 还有一些其它不常见的非标准RAID层级，RAID 2,3,4,6和RAID DP都和RAID5类似，他们都是通过分割和某种奇偶校验来提供性能上和容错。这些类似RAID 5的RAID层级的区别仅仅是它们如何写入奇偶数据。它们之中有些是通过保留一个磁盘来存储奇偶数据，还有一些是将奇偶数据分布到多个磁盘当中等等。如果需要，你可以去做这些研究，但对于我来说，我都称它们为”RAID 5”&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 还有一个值得讨论的非标准的RAID级别是RAID DP,DP的是”Dual Parity”的缩写，这和RAID 5很像但其将奇偶数据写入两次，这对于写入来说代价高昂，写入代价被提高到了6（每一次IO写请求需要6 IOPS）&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;RAID 比较&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 选择合适的RAID层级并不容易，需要考虑多方面因素：成本，性能和容量。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 下表总结了每个标准RAID层级的好处和坏处。&lt;/p&gt;  &lt;table style="width: 500px" border="1" cellspacing="1" cellpadding="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;&lt;strong&gt;RAID Level&lt;/strong&gt;&lt;/td&gt;        &lt;td&gt;&lt;strong&gt;Fault Tolerance&lt;/strong&gt;&lt;/td&gt;        &lt;td&gt;&lt;strong&gt;Read Performance&lt;/strong&gt;&lt;/td&gt;        &lt;td&gt;&lt;strong&gt;Write Performance&lt;/strong&gt;&lt;/td&gt;        &lt;td&gt;&lt;strong&gt;RAID Write Penalty&lt;/strong&gt;&lt;/td&gt;        &lt;td&gt;&lt;strong&gt;Cost&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;0&lt;/td&gt;        &lt;td&gt;None&lt;/td&gt;        &lt;td&gt;Good&lt;/td&gt;        &lt;td&gt;Excellent&lt;/td&gt;        &lt;td&gt;1&lt;/td&gt;        &lt;td&gt;Excellent&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;1&lt;/td&gt;        &lt;td&gt;Good&lt;/td&gt;        &lt;td&gt;Good&lt;/td&gt;        &lt;td&gt;Good&lt;/td&gt;        &lt;td&gt;2&lt;/td&gt;        &lt;td&gt;Fair&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;5&lt;/td&gt;        &lt;td&gt;Fair&lt;/td&gt;        &lt;td&gt;Good&lt;/td&gt;        &lt;td&gt;Poor&lt;/td&gt;        &lt;td&gt;4&lt;/td&gt;        &lt;td&gt;Good&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;1+0&lt;/td&gt;        &lt;td&gt;Excellent&lt;/td&gt;        &lt;td&gt;Excellent&lt;/td&gt;        &lt;td&gt;Excellent&lt;/td&gt;        &lt;td&gt;2&lt;/td&gt;        &lt;td&gt;Poor&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;DP&lt;/td&gt;        &lt;td&gt;Good&lt;/td&gt;        &lt;td&gt;Good&lt;/td&gt;        &lt;td&gt;Terrible&lt;/td&gt;        &lt;td&gt;6&lt;/td&gt;        &lt;td&gt;Good&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;SQL存储推荐&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;table style="width: 500px" border="1" cellspacing="1" cellpadding="1"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td&gt;&lt;strong&gt;SQL Server文件&lt;/strong&gt;&lt;/td&gt;        &lt;td&gt;&lt;strong&gt;RAID级别&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;操作系统和SQL二进制文件&lt;/td&gt;        &lt;td&gt;RAID 1 &lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;数据和索引&lt;/td&gt;        &lt;td&gt;RAID 1+0 (如果预算不允许可以使用RAID 5)&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;日志&lt;/td&gt;        &lt;td&gt;RAID 1+0&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;TempDB&lt;/td&gt;        &lt;td&gt;RAID 1+0&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td&gt;备份&lt;/td&gt;        &lt;td&gt;RAID 5&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;其它考虑因素&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 当需要计划你的IO子系统和SQL文件分布以及RAID层级时，你需要多考虑其它因素。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;RAID控制器&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; RAID可以通过2种方式实现：软件实现和硬件实现。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 在软件RAID配置中，操作系统管理RAID级别以及多磁盘之间的IO负载。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 在硬件RAID配置中，物理上会有一个硬件作为RAID控制器。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 通常来说，硬盘RAID解决方案会更健壮，灵活和强大。根据你对RAID控制器的预算，你能获得对应预算的配置选项。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 比如，某些RAID控制器仅仅提供一个RAID层级（比如RAID5）,一些更昂贵的RAID控制其提供了缓存功能。缓存可以用于缓存读取操作，写入操作以及它们两者。更好的RAID控制器甚至提供了对于读取和写入分配缓存的百分比选项。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 缓存对于SQL Server来说非常重要，尤其是对于写来说。无论是何种RAID级别，都没有读取性能上的代价，所有的RAID层级都提高了读取数据的速度。而写入才是RAID的代价，你可以通过RAID缓存来缓存所有的写入操作，这极大的提高了写入性能。通常来说，有缓存的RAID控制器都带有电池，这使得即使断电，缓存的数据也不会丢失。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 记住，SQL Server本身非常善于缓存读取，所以使用昂贵的RAID控制器中的缓存来缓存读取并没有什么意义。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;虚拟化&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 还有一个值得考虑的因素是虚拟化，无论你喜欢与否，我们已经步入了虚拟化的世界。在VMWare环境下部署生产环境下的SQL Server实例变得越来越普遍。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 虚拟化也影响RAID和IO方面，根据你使用的虚拟化产品，当你选择RAID级别时就需要考虑更多的因素，比如，VM是如何和存储系统交互的。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;总结&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 很明显，我们还有一些信息没有讨论到，RAID对于SQL Server性能和容错的重要性不言而喻。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 我希望本篇文章能够帮你理解RAID是如何影响你的SQL Server的性能。作为一个DBA或是数据库构架师来说，你必须明白当前RAID配置有着怎样的性能和容错性。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;参考资料&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;MSDN&lt;/strong&gt;:     &lt;br /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms190764.aspx"&gt;http://msdn.microsoft.com/en-us/library/ms190764.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;TechNet&lt;/strong&gt;:     &lt;br /&gt;&lt;a href="http://technet.microsoft.com/en-us/library/cc966534.aspx"&gt;http://technet.microsoft.com/en-us/library/cc966534.aspx&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Ed Whalen - PerfTuning.com&lt;/strong&gt;     &lt;br /&gt;&lt;a href="http://www.perftuning.com/files/pdf/RAID1.pdf"&gt;http://www.perftuning.com/files/pdf/RAID1.pdf&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;原文链接:&lt;a href="http://www.sqlservercentral.com/articles/RAID/88945/"&gt;http://www.sqlservercentral.com/articles/RAID/88945/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Translated by &lt;a href="www.cnblogs.com/careyson"&gt;CareySon&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;译者注：关于文中可能对于细节有某些错误，已经有人在论坛指出，请看链接:&lt;a href="http://www.sqlservercentral.com/Forums/Topic1292935-143-1.aspx"&gt;查看关于本篇文章的讨论&lt;/a&gt;.但是文章对于RAID的系统性讲述还是很到位的。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/CareySon/aggbug/2490372.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/CareySon/archive/2012/05/08/HowRAIDImpactSQLServer.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/CareySon/archive/2012/05/08/2489748.html</id><title type="text">SQL Server文章目录</title><summary type="text">SQL Server的文章写了也不少了，一直没有做一个目录方便大家阅读。现在把之前写的关于SQL Server的文章做一个目录，方便大家阅读 SQL入门 SQL查询入门(上篇) SQL查询入门(中篇) SQL查询入门（下篇） SQL进阶 T-SQL查询进阶--深入理解子查询 T-SQL查询进阶--基于列的逻辑表达式 ...</summary><published>2012-05-08T03:05:00Z</published><updated>2012-05-08T03:05:00Z</updated><author><name>CareySon</name><uri>http://www.cnblogs.com/CareySon/</uri></author><link rel="alternate" href="http://www.cnblogs.com/CareySon/archive/2012/05/08/2489748.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/CareySon/archive/2012/05/08/2489748.html"/><content type="html">&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; SQL Server的文章写了也不少了，一直没有做一个目录方便大家阅读。现在把之前写的关于SQL Server的文章做一个目录，方便大家阅读 &lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-winkingsmile" alt="眨眼" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205081104525170.png" /&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;SQL入门&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2010/04/05/1704928.html"&gt;SQL查询入门(上篇)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2010/04/13/1711095.html"&gt;SQL查询入门(中篇)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/05/18/2049727.html"&gt;SQL查询入门（下篇）&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;SQL进阶&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/07/18/2109406.html"&gt;T-SQL查询进阶--深入理解子查询&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/08/11/2135214.html"&gt;T-SQL查询进阶--基于列的逻辑表达式&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/08/23/2150434.html"&gt;T-SQL查询进阶--流程控制语句&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/10/11/2207330.html"&gt;T-SQL查询进阶--变量&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/10/13/2210156.html"&gt;T-SQL查询进阶--数据集之间的运算&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/11/01/2231381.html"&gt;T-SQL查询进阶-10分钟理解游标&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/12/07/2279522.html"&gt;T-SQL查询进阶--深入浅出视图&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/12/12/2284740.html"&gt;T-SQL查询进阶--详解公用表表达式(CTE)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/12/22/2297568.html"&gt;T-SQL查询进阶--理解SQL Server中索引的概念，原理以及其他&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/12/27/2303508.html"&gt;T-SQL查询高级--理解SQL SERVER中非聚集索引的覆盖，连接，交叉和过滤&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/12/30/2307766.html"&gt;T-SQL查询进阶--理解SQL SERVER中的分区表&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/01/06/2313897.html"&gt;T-SQL查询高级—SQL Server索引中的碎片和填充因子&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/03/22/2411292.html"&gt;T-SQL查询进阶—理解SQL Server中的锁&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="background-color: #ffffff; font-weight: bold" color="#ffc000"&gt;SQL日志&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/02/13/2349751.html"&gt;浅谈SQL Server中的事务日志(一)----事务日志的物理和逻辑构架&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/02/14/2351149.html"&gt;浅谈SQL Server中的事务日志(二)----事务日志在修改数据时的角色&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/02/17/2355200.html"&gt;浅谈SQL Server中的事务日志(三)----在简单恢复模式下日志的角色&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/02/23/2364572.html"&gt;浅谈SQL Server中的事务日志(四)----在完整恢复模式下日志的角色&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;SQL的一些单篇&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/12/19/2293245.html"&gt;T-SQL中的GROUP BY GROUPING SETS&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/12/23/2299127.html"&gt;理解SQL SERVER中的逻辑读，预读和物理读&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2011/12/26/2301597.html"&gt;SQL Server中数据库文件的存放方式，文件和文件组&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/01/29/2331088.html"&gt;浅谈SQL SERVER中事务的ACID&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/02/20/2359444.html"&gt;SQL Server中生成测试数据&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/02/23/2365006.html"&gt;SQL Server中灾难时备份结尾日志(Tail of log)的两种方法&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/03/06/2381582.html"&gt;从性能的角度谈SQL Server聚集索引键的选择&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/03/07/2383690.html"&gt;SQL Server中的Merge关键字&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/03/30/2424880.html"&gt;浅谈SQL Server中的快照&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/04/01/SQL-SERVER-Encryption.html"&gt;细说SQL Server中的加密&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/04/06/Imple-BTree-With-CSharp.html"&gt;C#实现平衡多路查找树(B树)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/05/23/CoreConceptOfExcutionEngine.html"&gt;SQL Server中的执行引擎入门&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/05/14/HowStatisticImpactQuery.html"&gt;浅谈SQL Server中统计对于查询的影响&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;SQL Server 2012新特性探秘&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/03/09/2387475.html"&gt;SQL Server 2012中的ColumnStore Index尝试&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/03/09/2387825.html"&gt;SQL Server2012 T-SQL对分页的增强尝试&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/03/12/2391581.html"&gt;SQL Server2012中的SequenceNumber尝试&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/03/12/2392084.html"&gt;SQL Server 2012新增的内置函数尝试&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/03/13/2393693.html"&gt;SQL Server 2012中的Contained Database尝试&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/03/14/2395661.html"&gt;SQL Server2012中的Throw语句尝试&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/03/14/2396150.html"&gt;SQL Server2012中的Indirect CheckPoint&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/03/20/2407719.html"&gt;SQL Server 2012中的AlwaysOn尝试&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;SQL Server权限&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/04/10/MSSQL-Security-Principal.html"&gt;理解SQL Server中的权限体系(上)----主体&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/04/12/SQL-Security-SecurableAndPermission.html"&gt;理解SQL Server中的权限体系(下)----安全对象和权限&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;翻译的文章&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/02/27/2369511.html"&gt;【译】初识SSRS ----通向报表服务的阶梯系列(一)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/02/27/2370017.html"&gt;【译】SSRS基础 ----通向报表服务的阶梯系列(二)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/02/28/2371316.html"&gt;【译】无处不在的数据 ----通向报表服务的阶梯系列(三)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/02/28/2372436.html"&gt;【译】Tablix指南----通向报表服务的阶梯系列(四)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/02/29/2373532.html"&gt;【译】用图表展示未知----通向报表服务的阶梯系列(五)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/03/02/2377429.html"&gt;【译】设计仪表盘----通向报表服务的阶梯系列(六)&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/02/15/2352256.html"&gt;【译】一些优化你的SQL语句的TIPs&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://www.cnblogs.com/CareySon/archive/2012/05/08/HowRAIDImpactSQLServer.html"&gt;【译】RAID的概念和RAID对于SQL性能的影响&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/CareySon/aggbug/2489748.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/CareySon/archive/2012/05/08/2489748.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/CareySon/archive/2012/05/04/ProcessAndThread.html</id><title type="text">操作系统中的进程与线程</title><summary type="text">简介 在传统的操作系统中，进程拥有独立的内存地址空间和一个用于控制的线程。但是，现在的情况更多的情况下要求在同一地址空间下拥有多个线程并发执行。因此线程被引入操作系统。 为什么需要线程? 如果非要说是为什么需要线程，还不如说为什么需要进程中还有其它进程。这些进程中包含的其它迷你进程就是线程。 线程之所以说是迷你进程，是因为线程和进程有很多相似之处，比如线程...</summary><published>2012-05-04T01:03:00Z</published><updated>2012-05-04T01:03:00Z</updated><author><name>CareySon</name><uri>http://www.cnblogs.com/CareySon/</uri></author><link rel="alternate" href="http://www.cnblogs.com/CareySon/archive/2012/05/04/ProcessAndThread.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/CareySon/archive/2012/05/04/ProcessAndThread.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;简介&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 在传统的操作系统中，进程拥有独立的内存地址空间和一个用于控制的线程。但是，现在的情况更多的情况下要求在同一地址空间下拥有多个线程并发执行。因此线程被引入操作系统。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;font color="#ff0000"&gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ffc000"&gt;&lt;font style="font-weight: bold"&gt;为什么需要线程?&lt;/font&gt;&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 如果非要说是为什么需要线程，还不如说为什么需要进程中还有其它进程。这些进程中包含的其它迷你进程就是线程。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 线程之所以说是迷你进程，是因为线程和进程有很多相似之处，比如线程和进程的状态都有运行，就绪，阻塞状态。这几种状态理解起来非常简单，当进程所需的资源没有到位时会是阻塞状态，当进程所需的资源到位时但CPU没有到位时是就绪状态，当进程既有所需的资源，又有CPU时，就为运行状态。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 下面我们来看一个具体的例子：&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 就拿我写博客的LiveWriter来说，LiveWriter需要监听我打字输入的状态，还需要每隔5分钟对草稿进行自动保存。假设如果这个进程只有一个线程的话，那么当对草稿进行保存时，因为此时需要访问硬盘，而访问硬盘的时间线程是阻塞状态的，这时我的任何输入都会没有响应，这种用户体验是无法接受的，或许我们可以通过键盘或者鼠标的输入去中断保存草稿的过程，但这种方案也并不讨好。而使用多线程，每个线程仅仅需要处理自己那一部分应该完成的任务，而不用去关心和其它线程的冲突。因此简化了编程模型。如图1所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205040911578931.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="1" border="0" alt="1" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205040911583490.png" width="560" height="450" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图1.两条线程满足各自的功能&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 更具体的说，线程的好处如下:&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 1.在很多程序中，需要多个线程互相同步或互斥的并行完成工作，而将这些工作分解到不同的线程中去无疑简化了编程模型。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 2.因为线程相比进程来说，更加的轻量，所以线程的创建和销毁的代价变得更小。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 3.线程提高了性能，虽然线程宏观上是并行的，但微观上却是串行。从CPU角度线程并无法提升性能，但如果某些线程涉及到等待资源（比如IO，等待输入）时，多线程允许进程中的其它线程继续执行而不是整个进程被阻塞，因此提高了CPU的利用率，从这个角度会提升性能。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 4.在多CPU或多核的情况下，使用线程不仅仅在宏观上并行，在微观上也是并行的。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这里值得注意的是，上面的两个线程如果改成两个进程，那么达不到所要的效果，&lt;font color="#0000ff"&gt;因为进程有自己独立的内存地址空间，而线程共享进程的内存地址空间&lt;/font&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;经典线程模型&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 另一个看进程和线程的角度是进程模型基于两类不同的概念：资源的组织和执行。在过去没有线程的操作系统中，资源的组织和执行都是由进程完成的。但区分这两者很多时候需要加以区分，这也是为什么需要引入线程。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 进程是用于组织资源的单位，进程将相关的资源组织在一起，这些资源包括：内存地址空间，程序，数据等，将这些以进程的形式组织起来可以使得操作系统管理这些资源更为容易。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 而线程，是每一个进程中执行的一个条线。线程虽然共享进程中的大多数资源，但线程也需要自己的一些资源，比如：用于标识下一条执行指令的程序计数器，一些容纳局部变量的寄存器，以及用于表示执行的历史的栈。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 总而言之：&lt;font color="#0000ff"&gt;进程是组织资源的最小单位，而线程是安排CPU执行的最小单位&lt;/font&gt;。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 其实在一个进程中多个线程并行和在操作系统中多个进程并行非常类似，只是线程共享的是地址空间，而进程共享的是物理内存，打印机，键盘等资源……&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 每一个进程和线程所独自占有的资源如表1所示。&lt;/p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;table border="1" cellspacing="0" cellpadding="2" width="400"&gt;&lt;tbody&gt;     &lt;tr&gt;       &lt;td valign="top" width="200"&gt;进程占有的资源&lt;/td&gt;        &lt;td valign="top" width="200"&gt;线程占有的资源&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top" width="200"&gt;地址空间          &lt;br /&gt;全局变量           &lt;br /&gt;打开的文件           &lt;br /&gt;子进程           &lt;br /&gt;信号量           &lt;br /&gt;账户信息&lt;/td&gt;        &lt;td valign="top" width="200"&gt;栈          &lt;br /&gt;寄存器           &lt;br /&gt;状态           &lt;br /&gt;程序计数器&lt;/td&gt;     &lt;/tr&gt;   &lt;/tbody&gt;&lt;/table&gt;  &lt;p&gt;表1.进程和线程所独占的资源&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 其中，线程可以共享进程独占的资源。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 我们常用的术语“多线程”一般指的是在同一个进程中多个线程的并发执行。如图2所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205040911597211.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="2" border="0" alt="2" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205040912008422.png" width="566" height="444" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图2.没有多线程的系统一个进程只能由一个线程&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 在多线程的进程中，每个线程轮流使用CPU，因此实际上线程并不是并行的，但从宏观上看，是并行的。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 在多线程模型中，每一个进程初始创建时只有一个线程。这个线程可以通过调用系统的库函数去创建其它线程。线程创建的线程并必须要为其指定地址，因为新的线程自动在创建它的地址空间内工作。虽然一个线程可以创建另一个线程，但通常来讲，线程之间是并列的，并不存在层级关系。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 当一个进程完成其工作后，可以通过调用系统库函数进行销毁。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;操作系统实现线程的几种模式&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 在操作系统中，线程可以实现在用户模式下，也可以实现在内核模式下，也可以两者结合实现。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;线程实现在用户空间下&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 当线程在用户空间下实现时，操作系统对线程的存在一无所知，操作系统只能看到进程，而不能看到线程。所有的线程都是在用户空间实现。在操作系统看来，每一个进程只有一个线程。过去的操作系统大部分是这种实现方式，这种方式的好处之一就是即使操作系统不支持线程，也可以通过库函数来支持线程。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 在这种模式下，每一个进程中都维护着一个&lt;font color="#0000ff"&gt;线程表&lt;/font&gt;来追踪本进程中的线程，这个表中包含表1中每个线程独占的资源，比如栈，寄存器，状态等，如图3所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205040912031162.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="3" border="0" alt="3" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205040912048229.png" width="560" height="464" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图3.在用户空间中实现线程&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这种模式当一个线程完成了其工作或等待需要被阻塞时，其调用系统过程阻塞自身，然后将CPU交由其它线程。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这种的模式的好处，首先，是在用户空间下进行进程切换的速度要远快于在操作系统内核中实现。其次，在用户空间下实现线程使得程序员可以实现自己的线程调度算法。比如进程可以实现垃圾回收器来回收线程。还有，当线程数量过多时，由于在用户空间维护线程表，不会占用大量的操作系统空间。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 有好处就有坏处，这种模式最致命的缺点也是由于操作系统不知道线程的存在，因此当一个进程中的某一个线程进行系统调用时，比如缺页中断而导致线程阻塞，此时操作系统会阻塞整个进程，即使这个进程中其它线程还在工作。还有一个问题是假如进程中一个线程长时间不释放CPU，因为用户空间并没有时钟中断机制，会导致此进程中的其它线程得不到CPU而持续等待。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;线程实现在操作系统内核中&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 在这种模式下，操作系统知道线程的存在。此时线程表存在操作系统内核中，如图4所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/20120504091208610.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="4" border="0" alt="4" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205040912102760.png" width="513" height="438" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 图4.线程在操作系统内核中实现&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 在这种模式下，所有可能阻塞线程的调用都以系统调用(System Call)的方式实现，相比在用户空间下实现线程造成阻塞的运行时调用(System runtime call)成本会高出很多。当一个线程阻塞时，操作系统可以选择将CPU交给同一进程中的其它线程，或是其它进程中的线程，而在用户空间下实现线程时，调度只能在本进程中执行，直到操作系统剥夺了当前进程的CPU。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 因为在内核模式下实现进程的成本更高，一个比较好的做法是另线程回收利用，当一个线程需要被销毁时，仅仅是修改标记位，而不是直接销毁其内容，当一个新的线程需要被创建时，也同样修改被“销毁”的线程其标记位即可。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这种模式下同样还是有一些弊端，比如接收系统信号的单位是进程，而不是线程，那么由进程中的哪一个线程接收系统信号呢？如果使用了表来记录，那么多个线程注册则通过哪一个线程处理系统信号？&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;混合模式&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 还有一种实现方式是将上面两种模式进行混合，用户空间中进程管理自己的线程，操作系统内核中有一部分内核级别的线程，如图5所示。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205040912145698.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="5" border="0" alt="5" src="http://images.cnblogs.com/cnblogs_com/CareySon/201205/201205040912183652.png" width="487" height="393" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 图5.混合模式&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 在这种模式下，操作系统只能看到内核线程。用户空间线程基于操作系统线程运行。因此，程序员可以决定使用多少用户空间线程以及操作系统线程，这无疑具有更大的灵活性。而用户空间线程的调度和前面所说的在用户空间下执行实现线程是一样的，同样可以自定义实现。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/CareySon/aggbug/2482134.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/CareySon/archive/2012/05/04/ProcessAndThread.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/CareySon/archive/2012/04/27/HTTP-Protocol.html</id><title type="text">HTTP协议漫谈</title><summary type="text">简介 园子里已经有不少介绍HTTP的的好文章。对HTTP的一些细节介绍的比较好，所以本篇文章不会对HTTP的细节进行深究，而是从够高和更结构化的角度将HTTP协议的元素进行分类讲解。 HTTP的定义和历史 在一个网络中。传输数据需要面临三个问题: 1.客户端如何知道所求内容的位置？ 2.当客户端知道所求内容的位置后，如何获取所求内容？ 3.所求内容以何种形式组织以便被客户端所识别？ 对于WEB来说，回答上面三种问题分别采用三种不同的技术，分别为:统一资源定位符(URIs),超文本传输协议(HTTP)和超文本标记语言(H...</summary><published>2012-04-27T02:58:00Z</published><updated>2012-04-27T02:58:00Z</updated><author><name>CareySon</name><uri>http://www.cnblogs.com/CareySon/</uri></author><link rel="alternate" href="http://www.cnblogs.com/CareySon/archive/2012/04/27/HTTP-Protocol.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/CareySon/archive/2012/04/27/HTTP-Protocol.html"/><content type="html">&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;简介&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 园子里已经有不少介绍HTTP的的好文章。对HTTP的一些细节介绍的比较好，所以本篇文章不会对HTTP的细节进行深究，而是从够高和更结构化的角度将HTTP协议的元素进行分类讲解。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;HTTP的定义和历史&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 在一个网络中。传输数据需要面临三个问题:&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 1.客户端如何知道所求内容的位置？&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 2.当客户端知道所求内容的位置后，如何获取所求内容？&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 3.所求内容以何种形式组织以便被客户端所识别？&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 对于WEB来说，回答上面三种问题分别采用三种不同的技术，分别为:统一资源定位符(URIs),超文本传输协议(HTTP)和超文本标记语言(HTML)。对于大多数WEB开发人员来说URI和HTML都是非常的熟悉。而HTTP协议在很多WEB技术中都被封装的过多使得HTTP反而最不被熟悉。&lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; HTTP作为一种传输协议，也是像HTML一样随着时间不断演进的，目前流行的HTTP1.1是HTTP协议的第三个版本。&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;HTTP 0.9&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;font color="#0000ff"&gt;&lt;strong&gt;&amp;#160; &lt;/strong&gt;&lt;/font&gt;&lt;font color="#000000"&gt;&amp;#160; HTTP 0.9作为HTTP协议的第一个版本。是非常弱的。请求(Request)只有一行,比如:&lt;/font&gt;&lt;/p&gt;  &lt;div style="border-bottom: green 1px dashed; border-left: green 2px solid; padding-bottom: 1px; margin-top: 5px; padding-left: 1px; padding-right: 1px; margin-left: 15px; border-top: green 1px dashed; border-right: green 1px dashed; padding-top: 1px; margin-buttom: 5px"&gt;   GET www.cnblogs.com&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 从如此简单的请求体，没有POST方法，没有HTTP 头可以看出，那个时代的HTTP客户端只能接收一种类型：纯文本。并且，如果得不到所求的信息，也没有404 500等错误出现。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 虽然HTTP 0.9看起来如此弱，但已经能满足那个时代的需求了。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;HTTP 1.0&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 随着1996年后,WEB程序的需求，HTTP 0.9已经不能满足需求。HTTP1.0最大的改变是引入了POST方法，使得客户端通过HTML表单向服务器发送数据成为可能,这也是WEB应用程序的一个基础。另一个巨大的改变是引入了HTTP头，使得HTTP不仅能返回错误代码，并且HTTP协议所传输的内容不仅限于纯文本，还可以是图片，动画等一系列格式。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 除此之外,还允许保持连接，既一次TCP连接后，可以多次通信，虽然HTTP1.0 默认是传输一次数据后就关闭。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;HTTP 1.1&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 2000年5月，HTTP1.1确立。HTTP1.1并不像HTTP1.0对于HTTP0.9那样的革命性。但是也有很多增强。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 首先，增加了Host头，比如访问我的博客:   &lt;br /&gt;&lt;/p&gt;&lt;div style="border-bottom: green 1px dashed; border-left: green 2px solid; padding-bottom: 1px; margin-top: 5px; padding-left: 1px; padding-right: 1px; margin-left: 15px; border-top: green 1px dashed; border-right: green 1px dashed; padding-top: 1px; margin-buttom: 5px"&gt;   GET /Careyson HTTP/1.1 &lt;br/&gt; Host: &lt;a href="http://www.cnblogs.com"&gt;www.cnblogs.com&lt;/a&gt; &lt;/div&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; Get后面仅仅需要相对路径即可。这看起来虽然仅仅类似语法糖的感觉，但实际上，这个提升使得在Web上的一台主机可以存在多个域。否则多个域名指向同一个IP会产生混淆。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 此外,还引入了Range头，使得客户端通过HTTP下载时只下载内容的一部分，这使得多线程下载也成为可能。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 还有值得一提的是HTTP1.1 默认连接是一直保持的，这个概念我会在下文中具体阐述。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;HTTP的网络层次&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 在Internet中所有的传输都是通过TCP/IP进行的。HTTP协议作为TCP/IP模型中应用层的协议也不例外。HTTP在网络中的层次如图1所示。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271056507156.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="1" border="0" alt="1" src="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271056528716.png" width="356" height="361" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 图1.HTTP在TCP/IP中的层次&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 可以看出，HTTP是基于传输层的TCP协议，而TCP是一个端到端的面向连接的协议。所谓的端到端可以理解为进程到进程之间的通信。所以HTTP在开始传输之前，首先需要建立TCP连接，而TCP连接的过程需要所谓的“三次握手”。概念如图2所示。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057008113.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="22" border="0" alt="22" src="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057029740.png" width="547" height="257" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图2.TCP连接的三次握手&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160; 在TCP三次握手之后，建立了TCP连接，此时HTTP就可以进行传输了。一个重要的概念是面向连接，既HTTP在传输完成之间并不断开TCP连接。在HTTP1.1中(通过Connection头设置)这是默认行为。所谓的HTTP传输完成我们通过一个具体的例子来看。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 比如访问我的博客,使用Fiddler来截取对应的请求和响应。如图3所示。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057061249.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="3" border="0" alt="3" src="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057091023.png" width="1231" height="610" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;图3.用fiddler抓取请求和相应&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 可以看出，虽然仅仅访问了我的博客，但锁获取的不仅仅是一个HTML而已，而是浏览器对HTML解析的过程中，如果发现需要获取的内容，会再次发起HTTP请求去服务器获取，比如图2中的那个common2.css。这上面19个HTTP请求，只依靠一个TCP连接就够了，这就是所谓的&lt;font color="#0000ff"&gt;持久连接&lt;/font&gt;。也是所谓的一次HTTP请求完成。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;HTTP请求(HTTP Request)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 所谓的HTTP请求，也就是Web客户端向Web服务器发送信息，这个信息由如下三部分组成：&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 1.请求行&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 2.HTTP头&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 3.内容&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 一个典型的请求行比如:&lt;/p&gt;&lt;div style="border-bottom: green 1px dashed; border-left: green 2px solid; padding-bottom: 1px; margin-top: 5px; padding-left: 1px; padding-right: 1px; margin-left: 15px; border-top: green 1px dashed; border-right: green 1px dashed; padding-top: 1px; margin-buttom: 5px"&gt;  GET www.cnblogs.com HTTP/1.1&lt;/div&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 请求行写法是固定的，由三部分组成，第一部分是请求方法，第二部分是请求网址，第三部分是HTTP版本。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 第二部分HTTP头在HTTP请求可以是3种HTTP头：1.请求头(request header)&amp;#160; 2.普通头(general header)&amp;#160; 3.实体头(entity header)&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 通常来说，由于Get请求往往不包含内容实体，因此也不会有实体头。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 第三部分内容只在POST请求中存在，因为GET请求并不包含任何实体。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 我们截取一个具体的Post请求来看这三部分，我在一个普通的aspx页面放一个BUTTON,当提交后会产生一个Post请求，如图4所示。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057105124.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="4" border="0" alt="4" src="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057135389.png" width="668" height="290" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图4.HTTP请求由三部分组成&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;HTTP请求方法&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 虽然我们所常见的只有Get和Post方法，但实际上HTTP请求方法还有很多，比如： PUT方法，DELETE方法，HEAD方法，CONNECT方法,TRACE方法。这里我就不细说了，自行Bing。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这里重点说一下Get和Post方法，网上关于Get和Post的区别满天飞。但很多没有说到点子上。Get和Post最大的区别就是Post有上面所说的第三部分：内容。而Get不存在这个内容。因此就像Get和Post其名称所示那样，Get用于从服务器上取内容，虽然可以通过QueryString向服务器发信息，但这违背了Get的本意，QueryString中的信息在HTTP看来仅仅是获取所取得内容的一个参数而已。而Post是由客户端向服务器端发送内容的方式。因此具有请求的第三部分：内容。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;HTTP响应(HTTP Response)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 当Web服务器收到HTTP请求后，会根据请求的信息做某些处理(这些处理可能仅仅是静态的返回页，或是包含Asp.net,PHP,Jsp等语言进行处理后返回)，相应的返回一个HTTP响应。HTTP响应在结构上很类似于HTTP请求,也是由三部分组成，分别为:&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 1.状态行&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 2.HTTP头&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 3.返回内容&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 首先来看状态行，一个典型的HTTP状态如下:&lt;/p&gt;&lt;div style="border-bottom: green 1px dashed; border-left: green 2px solid; padding-bottom: 1px; margin-top: 5px; padding-left: 1px; padding-right: 1px; margin-left: 15px; border-top: green 1px dashed; border-right: green 1px dashed; padding-top: 1px; margin-buttom: 5px"&gt;  HTTP/1.1 200 OK&lt;/div&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 第一部分是HTTP版本，第二部分是响应状态码，第三部分是状态码的描述，因此也可以把第二和第三部分看成一个部分。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 对于HTTP版本没有什么好说的，而状态码值得说一下，网上对于每个具体的HTTP状态码所代表的含义都有解释，这里我说一下分类。&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;    &lt;p&gt;信息类 (100-199)&lt;/p&gt;  &lt;/li&gt;  &lt;li&gt;    &lt;p&gt;响应成功 (200-299)&lt;/p&gt;  &lt;/li&gt;  &lt;li&gt;    &lt;p&gt;重定向类 (300-399)&lt;/p&gt;  &lt;/li&gt;  &lt;li&gt;    &lt;p&gt;客户端错误类 (400-499)&lt;/p&gt;  &lt;/li&gt;  &lt;li&gt;    &lt;p&gt;服务端错误类 (500-599)&lt;/p&gt;  &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; HTTP响应中包含的头包括1.响应头(response header) 2.普通头(general header) 3.实体头(entity header)。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 第三部分HTTP响应内容就是HTTP请求所请求的信息。这个信息可以是一个HTML，也可以是一个图片。比如我访问百度，HTTP Response如图5所示。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057182852.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="5" border="0" alt="5" src="http://images.cnblogs.com/cnblogs_com/CareySon/201204/20120427105722524.png" width="573" height="235" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图5.一个典型的HTTP响应&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160; 图5中的响应是一个HTML，当然还可以是其它类型，比如图片，如图6所示。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057253329.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="6" border="0" alt="6" src="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057273560.png" width="555" height="216" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图6.HTTP响应内容是图片&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这里会有一个疑问，既然HTTP响应的内容不仅仅是HTML，还可以是其它类型，那么浏览器如何正确对接收到的信息进行处理？&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这是通过媒体类型确定的(Media Type),具体来说对应Content-Type这个HTTP头，比如图5中是text/html,图6是image/jpeg。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 媒体类型的格式为：大类/小类&amp;#160; 比如图5中的html是小类，而text是大类。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;em&gt;IANA&lt;/em&gt;(The Internet Assigned Numbers Authority，互联网数字分配机构)定义了8个大类的媒体类型，分别是:&lt;/p&gt;&lt;ul&gt;  &lt;li&gt;    &lt;p&gt;&lt;tt&gt;application&lt;/tt&gt;— &lt;a name="idd1e19290"&gt;&lt;/a&gt;(比如: &lt;tt&gt;application/vnd.ms-excel&lt;/tt&gt;.)&lt;/p&gt;  &lt;/li&gt;  &lt;li&gt;    &lt;p&gt;&lt;tt&gt;audio&lt;/tt&gt; (比如: &lt;tt&gt;audio/mpeg&lt;/tt&gt;.)&lt;/p&gt;  &lt;/li&gt;  &lt;li&gt;    &lt;p&gt;&lt;tt&gt;image&lt;/tt&gt; (比如: &lt;tt&gt;image/png&lt;/tt&gt;.)&lt;/p&gt;  &lt;/li&gt;  &lt;li&gt;    &lt;p&gt;&lt;tt&gt;message&lt;/tt&gt; (比如,:&lt;tt&gt;message/http&lt;/tt&gt;.)&lt;/p&gt;  &lt;/li&gt;  &lt;li&gt;    &lt;p&gt;&lt;tt&gt;model&lt;/tt&gt;(比如:&lt;tt&gt;model/vrml&lt;/tt&gt;.)&lt;/p&gt;  &lt;/li&gt;  &lt;li&gt;    &lt;p&gt;&lt;tt&gt;multipart&lt;/tt&gt; (比如:&lt;tt&gt;multipart/form-data&lt;/tt&gt;.)&lt;/p&gt;  &lt;/li&gt;  &lt;li&gt;    &lt;p&gt;&lt;tt&gt;text&lt;/tt&gt;(比如:&lt;tt&gt;text/html&lt;/tt&gt;.)&lt;/p&gt;  &lt;/li&gt;  &lt;li&gt;    &lt;p&gt;&lt;tt&gt;video&lt;/tt&gt;(比如:&lt;tt&gt;video/quicktime&lt;/tt&gt;.)&lt;/p&gt;  &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;HTTP头&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; HTTP头仅仅是一个标签而已，比如我在Aspx中加入代码:&lt;/p&gt;&lt;div style="border-bottom: green 1px dashed; border-left: green 2px solid; padding-bottom: 1px; margin-top: 5px; padding-left: 1px; padding-right: 1px; margin-left: 15px; border-top: green 1px dashed; border-right: green 1px dashed; padding-top: 1px; margin-buttom: 5px"&gt;  Response.AddHeader(&amp;quot;测试头&amp;quot;,&amp;quot;测试值&amp;quot;);&lt;/div&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 对应的我们可以在fiddler抓到的信息如图7所示。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057292122.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="7" border="0" alt="7" src="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057329944.png" width="344" height="112" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图7.HTTP头&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 不难看出，HTTP头并不是严格要求的，仅仅是一个标签，如果浏览器可以解析就会按照某些标准（比如浏览器自身标准，W3C的标准）去解释这个头，否则不识别的头就会被浏览器无视。对服务器也是同理。假如你编写一个浏览器，你可以将上面的头解释成任何你想要的效果&lt;img style="border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none" class="wlEmoticon wlEmoticon-smile" alt="微笑" src="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057336663.png" /&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 下面我们说的HTTP头都是W3C标准的头，我不会对每个头的作用进行详细说明，关于HTTP头作用的文章在网上已经很多了，请自行Bing。HTTP头按照其不同的作用，可以分为四大类。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;通用头(General header)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 通用头即可以包含在HTTP请求中，也可以包含在HTTP响应中。通用头的作用是描述HTTP协议本身。比如描述HTTP是否持久连接的Connection头，HTTP发送日期的Date头，描述HTTP所在TCP连接时间的Keep-Alive头,用于缓存控制的Cache-Control头等。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;实体头(Entity header)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 实体头是那些描述HTTP信息的头。既可以出现在HTTP POST方法的请求中，也可以出现在HTTP响应中。比如图5和图6中的Content-Type和Content-length都是描述实体的类型和大小的头都属于实体头。其它还有用于描述实体的Content-Language,Content-MD5,Content-Encoding以及控制实体缓存的Expires和Last-Modifies头等。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;请求头(HTTP Request Header)&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 请求头是那些由客户端发往服务端以便帮助服务端更好的满足客户端请求的头。请求头只能出现在HTTP请求中。比如告诉服务器只接收某种响应内容的Accept头，发送Cookies的Cookie头，显示请求主机域的HOST头,用于缓存的&lt;tt&gt;&lt;font face="微软雅黑"&gt;If-Match，&lt;tt&gt;&lt;font face="微软雅黑"&gt;If-Match-Since,&lt;/font&gt;&lt;tt&gt;&lt;font face="微软雅黑"&gt;If-None-Match&lt;/font&gt;头，用于只取&lt;font face="微软雅黑"&gt;HTTP响应信息中部分信息的Range头，用于附属HTML相关请求引用的Referer头等。&lt;/font&gt;&lt;/tt&gt;&lt;/tt&gt;&lt;/font&gt;&lt;/tt&gt;&lt;/p&gt;&lt;p&gt;&lt;tt&gt;&lt;tt&gt;&lt;tt&gt;&lt;/tt&gt;&lt;/tt&gt;&lt;/tt&gt;&lt;/p&gt;&lt;p&gt;&lt;tt&gt;&lt;tt&gt;&lt;tt&gt;&lt;font color="#0000ff" face="微软雅黑"&gt;&lt;strong&gt;响应头(HTTP Response Header)&lt;/strong&gt;&lt;/font&gt;&lt;/tt&gt;&lt;/tt&gt;&lt;/tt&gt;&lt;/p&gt;&lt;p&gt;&lt;tt&gt;&lt;tt&gt;&lt;tt&gt;&lt;font face="微软雅黑"&gt;&amp;#160;&amp;#160;&amp;#160; HTTP响应头是那些描述HTTP响应本身的头，这里面并不包含描述HTTP响应中第三部分也就是HTTP信息的头（这部分由实体头负责）。比如说定时刷新的Refresh头，当遇到503错误时自动重试的Retry-After头，显示服务器信息的Server头，设置COOKIE的Set-Cookie头，告诉客户端可以部分请求的Accept-Ranges头等。&lt;/font&gt;&lt;/tt&gt;&lt;/tt&gt;&lt;/tt&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;状态保持&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 还有一点值得注意的是，HTTP协议是无状态的，这意味着对于接收HTTP请求的服务器来说，并不知道每一次请求来自同一个客户端还是不同客户端，每一次请求对于服务器来说都是一样的。因此需要一些额外的手段来使得服务器在接收某个请求时知道这个请求来自于某个客户端。如图8所示。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057358289.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="8" border="0" alt="8" src="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057389982.png" width="525" height="228" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图8.服务器并不知道请求1和请求2来自同一个客户端&lt;/p&gt;&lt;p&gt;&amp;#160; &lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;通过Cookies保持状态&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 为了解决这个问题，HTTP协议通过Cookies来保持状态，对于图8中的请求，如果使用Cookies进行状态控制，则变成了如图9所示。&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057402373.png"&gt;&lt;img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="9" border="0" alt="9" src="http://images.cnblogs.com/cnblogs_com/CareySon/201204/201204271057427936.png" width="570" height="248" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 图9.通过Cookies，服务器就可以清楚的知道请求2和请求1来自同一个客户端&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;通过表单变量保持状态&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 除了Cookies之外，还可以使用表单变量来保持状态，比如Asp.net就通过一个叫ViewState的Input=“hidden”的框来保持状态,比如:&lt;/p&gt;&lt;div style="border-bottom: green 1px dashed; border-left: green 2px solid; padding-bottom: 1px; margin-top: 5px; padding-left: 1px; padding-right: 1px; margin-left: 15px; border-top: green 1px dashed; border-right: green 1px dashed; padding-top: 1px; margin-buttom: 5px"&gt;   &amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;__VIEWSTATE&amp;quot; id=&amp;quot;__VIEWSTATE&amp;quot; value=&amp;quot;/wEPDwUKMjA0OTM4MTAwNGRkXUfhlDv1Cs7/qhBlyZROCzlvf5U=&amp;quot; /&amp;gt;&lt;/div&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 这个原理和Cookies大同小异，只是每次请求和响应所附带的信息变成了表单变量。&lt;/p&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#0000ff"&gt;通过QueryString保持状态&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 这个原理和上述两种状态保持方法原理是一样的，QueryString通过将信息保存在所请求地址的末尾来向服务器传送信息，通常和表单结合使用，一个典型的QueryString比如:&lt;/p&gt;&lt;div style="border-bottom: green 1px dashed; border-left: green 2px solid; padding-bottom: 1px; margin-top: 5px; padding-left: 1px; padding-right: 1px; margin-left: 15px; border-top: green 1px dashed; border-right: green 1px dashed; padding-top: 1px; margin-buttom: 5px"&gt;   &lt;a href="http://www.xxx.com/xxx.aspx?var1=value&amp;amp;var2=value2"&gt;www.xxx.com/xxx.aspx?var1=value&amp;amp;var2=value2&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&amp;#160;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;&lt;font style="font-weight: bold" color="#ffc000"&gt;总结&lt;/font&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; 本文从一个比较高的视角来看HTTP协议，对于HTTP协议中的细节并没有深挖，但对于HTTP大框架有了比较系统的介绍，更多关于HTTP的细节信息，请去Bing或参看相关书籍:-)&lt;/p&gt;&lt;img src="http://www.cnblogs.com/CareySon/aggbug/2473154.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/CareySon/archive/2012/04/27/HTTP-Protocol.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
