码迷,mamicode.com
首页 > 数据库 > 详细

sqlserver 索引

时间:2017-03-30 19:39:54      阅读:247      评论:0      收藏:0      [点我收藏+]

标签:group   影响   dex   sts   html   tail   文件   没有   microsoft   

参考原文:http://www.cnblogs.com/tjy9999/p/4494662.html

 

1. 非聚集索引

SET STATISTICS io ON 
SET STATISTICS time ON 

-- 1. 没有索引(logical reads 568)
SELECT FirstName, LastName FROM dbo.Contact WHERE LastName LIKE S%  

-- 创建非聚集索引
IF EXISTS (SELECT * FROM sys.indexes WHERE OBJECT_ID = OBJECT_ID(Person.Contact) AND name = FullName) 
DROP INDEX Person.Contact.FullName; 
CREATE NONCLUSTERED INDEX FullName ON Person.Contact( LastName, FirstName ); 
GO 

-- 2. 完全覆盖的查询(logical reads 14)
SELECT FirstName, LastName FROM dbo.Contact WHERE LastName LIKE S%   

-- 3. 非完全覆盖的查询(logical reads 568) SQL Server觉得使用索引查找,比直接扫描还要做更多的工作,因此没有使用索引.
SELECT * FROM dbo.Contact WHERE LastName LIKE S%   

-- 4. 非完全覆盖的查询(logical reads 111) 改变where条件,从而减少查询结果的范围,增加使用索引的好处,SQL Server使用索引查找来缩短查询时间.
SELECT * FROM dbo.Contacts WHERE LastName LIKE Ste%

 

2. 聚集索引

非聚集索引是独立的对象,有自己的存储空间,而聚集索引和表是同一个对象。创建一个聚集索引的时候,SQL Server用key对表进行排序,并且在修改数据的时候维护排序。因此当聚集索引的键是订单号,那么同一个订单的信息在表中的顺序是连续的。每张表只能有一个聚集索引,因为表只能按照一个顺序来排列。如果一张表上没有聚集索引,表也被叫做堆,因此表分为两种类型:聚集索引表和堆表。

CREATE CLUSTERED INDEX IX_SalesOrderDetail ON dbo.SalesOrderDetail (SalesOrderID, SalesOrderDetailID) 
GO 

-- 1. 堆表查询(logical reads 1495) & 聚集索引表查询(logical reads 3)
SELECT * FROM SalesOrderDetailWHERE SalesOrderID = 43671 AND SalesOrderDetailID = 120

-- 2. 堆表查询(logical reads 1495) & 聚集索引表查询(logical reads 1513)
--    ProductID列不是聚集索引的键。两种表都进行了表扫描。因为包含了聚集索引,聚集索引表更大,所以扫描了更多的次数。
SELECT * FROM SalesOrderDetail WHERE ProductID = 755

3. 页和区

SQL Server在创建数据库的时候,即指定数据文件的存放位置。SQL Server读取的不是行,读取的单位是一页或者更多页。页是最小的IO单元,每页的大小是8K。一个分区包含8个连续的页。每一行的大小=所有列的大小+行的头部信息。

 

4. 包含列

  • 表中的每一行在索引中总是有一个入口(这条规则有一个意外,在后面的级别中我们会讲到)。这些入口总是用索引键排序。
  • 在聚集索引中,索引的入口就是表的实际行。
  • 在非聚集索引中,入口和数据行是分开的,索引由索引键列和标签组成,标签是索引键列到表数据行的映射。

那些经常出现在select中的,而不是where子句中的列,最好放在包含列中。索引列不会影响索引入口的排序,只会更新索引的入口,但是不需要移动。

CREATE NONCLUSTERED INDEX FK_ProductID_ ModifiedDate 
       ON Sales.SalesOrderDetail (ProductID, ModifiedDate) 
       INCLUDE (OrderQty, UnitPrice, LineTotal) 

-- 该查询在包含列的非聚集索引下速度更快
SELECT ProductID , 
    ModifiedDate , 
    SUM(OrderQty) AS No of Items , 
    AVG(UnitPrice) Avg Price , 
    SUM(LineTotal) Total Value 
FROM Sales.SalesOrderDetail 
WHERE ProductID = 888 
GROUP BY ProductID ,ModifiedDate ;

 

5. 标签

据库中的每一行,在任何时间,都可以用三个数字来标识:文件号-页号-行号。这三个数字的复合标识叫做rowid,通常叫做RID。因此文件1的77页的12行,RID会显示成1:77:12。

一个堆表的非聚集索引:RID为基础的标签

  通常来讲,一个堆表的行是不会移动的,一旦他们被插入一页,他们会保持在这页中。更加精准的说法是:在堆表中的行很少移动,当他们移动的时候,在旧的位置上会留下新的地址。因为堆表的行不会移动,在堆表中RID永久的标识每一行。不仅值是永久的,而且物理位置也是永久的。索引中每一行的标签都是很有效的,直接指向对应的数据行。

聚集索引的非聚集索引:键为基础的标签

  聚集索引表的行是可以移动的,在修改数据或者是维护索引的时候可能会分配到另外一页。当聚集索引的一行被移动到新页的时候,它只是被移动,而聚集索引的键值没有改变。因此可以用索引键值作为行的标签。聚集索引的键应该满足三个条件:短小、静态,并且唯一。聚集索引键值的改变,会导致每一个非聚集索引中对应行的入口发生更新操作。因此,如果一张表有n个非聚集索引,一次索引键的更新,会变成n+1次的更新。

  非聚集索引的入口由查询键列、包含列、标签组成。标签的值既可以是RID,也可以是聚集索引的键,这依赖于表是堆表还是聚集索引表。为表选择最好的聚集索引需要你依据三条规则,确保索引键是一个好的标签。

sqlserver 索引

标签:group   影响   dex   sts   html   tail   文件   没有   microsoft   

原文地址:http://www.cnblogs.com/anxiao/p/6647213.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!