Home >Database >Mysql Tutorial >SQLSERVER是怎麽通过索引和统计信息来找到目标数据的(第一篇)

SQLSERVER是怎麽通过索引和统计信息来找到目标数据的(第一篇)

WBOY
WBOYOriginal
2016-06-07 15:45:191046browse

SQLSERVER是怎麽通过索引和统计信息来找到目标数据的(第一篇) 在第一篇里大家先搭建好测试环境,了解SQL Server中的执行引擎,了解一下表的信息,在第二篇再跟大家详细地说清楚索引 在第三篇里跟大家说一下统计信息。 因为篇幅比较长,所以暂时分成第一篇、

SQLSERVER是怎麽通过索引和统计信息来找到目标数据的(第一篇)

在第一篇里大家先搭建好测试环境,了解SQL Server中的执行引擎,了解一下表的信息,在第二篇再跟大家详细地说清楚索引

在第三篇里跟大家说一下统计信息。

因为篇幅比较长,所以暂时分成第一篇、第二篇、第三篇,不然大家看得很痛苦

 

---------------------------------------------------------------开始-----------------------------------------------------

先给出一篇文章的地址,都是博客园里的文章:

http://www.cnblogs.com/CareySon/archive/2012/05/23/CoreConceptOfExcutionEngine.html

《SQL Server中的执行引擎入门》,这篇文章主要讲了:执行引擎、执行计划、查询优化器

对执行引擎 、执行计划的了解或者掌握对SQLSERVER的索引查找数据方法是很有必要的,因为是环环相扣

如果阁下不对执行引擎 、执行计划先进行一下了解,下面的内容阁下会看得一头雾水

 

再看一下SQLSERVER为每个表记录了哪些信息 因为博客园的图片上传功能出了一些问题

我先给出图片链接

SQLSERVER是怎麽通过索引和统计信息来找到目标数据的(第一篇)

打开SSMS,点击表的+号,可以看到SQLSERVER一般记录了表的列信息、主键、约束、触发器、索引和统计信息

列信息、主键、约束、触发器就不说了,一般SQLSERVER查找目标数据都要使用到索引统计信息

 

 --------------------------------------------搭建测试环境-----------------------------------------------

请确保阁下的计算机里有范例数据库AdventureWorks,并在数据库里建立两张新的规范表格

<span> 1</span> <span>USE [AdventureWorks]
</span><span> 2</span> 
<span> 3</span> <span>DROP TABLE [dbo].SalesOrderHeader_test
</span><span> 4</span> <span>GO
</span><span> 5</span> <span>DROP TABLE [dbo].SalesOrderDetail_test
</span><span> 6</span> <span>GO
</span><span> 7</span> 
<span> 8</span> SELECT *<span> INTO dbo.SalesOrderHeader_test
</span><span> 9</span> <span>FROM sales.[SalesOrderHeader]
</span><span>10</span> <span>GO
</span><span>11</span> 
<span>12</span> SELECT *<span> INTO [dbo].SalesOrderDetail_test
</span><span>13</span> <span>FROM sales.[SalesOrderDetail]
</span><span>14</span> <span>GO
</span><span>15</span> 
<span>16</span> <span>CREATE CLUSTERED INDEX SalesOrderHeader_test_CL
</span><span>17</span> <span>ON [dbo].SalesOrderHeader_test([SalesOrderID])
</span><span>18</span> 
<span>19</span> <span>GO
</span><span>20</span> 
<span>21</span> <span>CREATE INDEX SalesOrderDetail_test_NCL
</span><span>22</span> <span>ON [dbo].SalesOrderDetail_test([SalesOrderID])
</span><span>23</span> GO

dbo.SalesOrderHeader_test:存放的是每一张订单的头信息,包括订单创建日期、客户编号、

合同编号、销售员编号等,每个订单都有一个单独的订单号在订单号这个字段上,有一个聚集索引

 

dbo.SalesOrderDetail_test:存放的是订单的详细内容。一张订单可以销售多个产品给同一个客户,

所以SalesOrderHeader_test和SalesOrderDetail_test是一对多的关系。每条详细内容包括他所属的订单编号,

他自己在表格里的唯一编号(SalesOrderDetailID)、产品编号、单价、销售数量等,在这里,先只在[SalesOrderID]

上建立一个非聚集索引

 

按照AdventureWorks里原先的数据,dbo.SalesOrderHeader_test里有3W多条订单信息,

dbo.SalesOrderDetail_test里有12W多条订单详细记录,基本上一条订单有3~5条详细记录,

这是一个正常的分布

 

下面再在dbo.SalesOrderHeader_test里加入9条订单记录,他们的编号是从75124到75132

这是9张特殊的订单,每张有12W多条详细记录。也就是说:dbo.SalesOrderDetail_test里会有

90%的数据属于这9张订单。请用下面这段代码来得到模拟数据:

<span> 1</span> <span>USE [AdventureWorks]
</span><span> 2</span> <span>GO
</span><span> 3</span> <span>DECLARE @i INT
</span><span> 4</span> SET @i=<span>1</span>
<span> 5</span> WHILE @i9
<span> 6</span> <span>BEGIN
</span><span> 7</span> <span>INSERT INTO dbo.[SalesOrderHeader_test]
</span><span> 8</span> <span>        ( [RevisionNumber] ,
</span><span> 9</span> <span>          [OrderDate] ,
</span><span>10</span> <span>          [DueDate] ,
</span><span>11</span> <span>          [ShipDate] ,
</span><span>12</span> <span>          [Status] ,
</span><span>13</span> <span>          [OnlineOrderFlag] ,
</span><span>14</span> <span>          [SalesOrderNumber] ,
</span><span>15</span> <span>          [PurchaseOrderNumber] ,
</span><span>16</span> <span>          [AccountNumber] ,
</span><span>17</span> <span>          [CustomerID] ,
</span><span>18</span> <span>          [ContactID] ,
</span><span>19</span> <span>          [SalesPersonID] ,
</span><span>20</span> <span>          [TerritoryID] ,
</span><span>21</span> <span>          [BillToAddressID] ,
</span><span>22</span> <span>          [ShipToAddressID] ,
</span><span>23</span> <span>          [ShipMethodID] ,
</span><span>24</span> <span>          [CreditCardID] ,
</span><span>25</span> <span>          [CreditCardApprovalCode] ,
</span><span>26</span> <span>          [CurrencyRateID] ,
</span><span>27</span> <span>          [SubTotal] ,
</span><span>28</span> <span>          [TaxAmt] ,
</span><span>29</span> <span>          [Freight] ,
</span><span>30</span> <span>          [TotalDue] ,
</span><span>31</span> <span>          [Comment] ,
</span><span>32</span> <span>          [rowguid] ,
</span><span>33</span> <span>          [ModifiedDate]
</span><span>34</span> <span>        )
</span><span>35</span> <span>SELECT 
</span><span>36</span> <span>[RevisionNumber],[OrderDate],[DueDate],
</span><span>37</span> <span>[ShipDate],[Status],[OnlineOrderFlag],[SalesOrderNumber],
</span><span>38</span> <span>[PurchaseOrderNumber],[AccountNumber],[CustomerID],
</span><span>39</span> <span>[ContactID],[SalesPersonID],[TerritoryID],
</span><span>40</span> <span>[BillToAddressID],[ShipToAddressID],[ShipMethodID],
</span><span>41</span> <span>[CreditCardID],[CreditCardApprovalCode],[CurrencyRateID],
</span><span>42</span> <span>[SubTotal],[TaxAmt],
</span><span>43</span> <span>[Freight],[TotalDue],[Comment],[rowguid],[ModifiedDate]
</span><span>44</span> <span>FROM [dbo].[SalesOrderHeader_test]
</span><span>45</span> WHERE [SalesOrderID]=<span>75123</span>
<span>46</span> 
<span>47</span> <span>INSERT INTO [dbo].[SalesOrderDetail_test]
</span><span>48</span> <span>        ( [SalesOrderID] ,
</span><span>49</span> <span>          [CarrierTrackingNumber] ,
</span><span>50</span> <span>          [OrderQty] ,
</span><span>51</span> <span>          [ProductID] ,
</span><span>52</span> <span>          [SpecialOfferID] ,
</span><span>53</span> <span>          [UnitPrice] ,
</span><span>54</span> <span>          [UnitPriceDiscount] ,
</span><span>55</span> <span>          [LineTotal] ,
</span><span>56</span> <span>          [rowguid] ,
</span><span>57</span> <span>          [ModifiedDate]
</span><span>58</span> <span>        )
</span><span>59</span> <span>SELECT 
</span><span>60</span> <span>75123</span>+<span>@i,[CarrierTrackingNumber],[OrderQty],
</span><span>61</span> <span>[ProductID],[SpecialOfferID],[UnitPrice],
</span><span>62</span> <span>[UnitPriceDiscount],[LineTotal],
</span><span>63</span> <span>[rowguid],GETDATE()
</span><span>64</span> <span>FROM sales.[SalesOrderDetail]
</span><span>65</span> SET @i=@i+<span>1</span>
<span>66</span> <span>END
</span><span>67</span> GO

在后面的内容中,将用这两张表做例子。

测试数据建立完毕了!

 

--------------------------------------------------索引与统计信息的介绍--------------------------------------------------------------

SQLSERVER有两类索引,聚集索引和非聚集索引。建立索引的主要目的,是按照预期的顺序排列数据,并且存储一部分冗余数据,

用来加快SQL找到数据的速度。一张几百万条甚至更大数据量的表,怎样从里面找到用户想要的数据呢?从头到尾找一遍肯定是最慢的办法

索引的功能类似于字典里的检字表。有了好的索引,表格再大,也能像查字典一样很快地找到用户需要的数据

除了需要索引的帮助,SQLSERVER在运行指令的时候,也要知道所涉及的表格每个有多大,预期每张表能够返回多少数据,

每一步的结果集会多大。知道了这些信息,才能够选择比较好的执行计划。可是SQLSERVER是一个计算机程序,他是怎麽知道这些信息的呢?

这要靠统计信息(statistics)来帮忙(上面已经给出了截图)。SQLSERVER会在每个索引上自动建立统计信息,也会根据运行指令的需要,

动态地创建一些统计信息。统计信息的准确度,会直接影响SQLSERVER完成指令的速度

 

 

 

第一篇完毕了,第二篇就是讲索引的内容了,敬请期待o(∩_∩)o

第二篇地址:SQLSERVER是怎麽通过索引和统计信息来找到目标数据的(第二篇)

第三篇地址:SQLSERVER是怎麽通过索引和统计信息来找到目标数据的(第三篇)

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn