关于SqlServer中索引的学习
1.数据库中为什么要使用索引?
与书中的索引一样,数据库中的索引使您可以快速找到表或索引视图中的特定信息。索引包含从表或视图中一个或多个列生成的键,以及映射到指定数据的存储位置的指针。通过创建设计良好的索引以支持查询,可以显著提高数据库查询和应用程序的性能。索引可以减少为返回查询结果集而必须读取的数据量。索引还可以强制表中的行具有唯一性,从而确保表数据的数据完整性。
2.索引的类型
SqlServer2005所支持的索引类型有聚集索引、非聚集索引、唯一索引、包含性列索引、索引视图、全文索引以及XML共7种。
1).聚集索引
对于聚集索引,表中行的物理顺序与键值的逻辑(索引)顺序相同。由于聚集索引规定数据在表中的物理存储顺序,所以一个表只能包含一个聚集索引。聚集索引类似于电话簿,后者按姓氏排列数据。
--创建一个新表 t1
CREATE TABLE t1 (a int, b int, c int);
--在表t1的c列上创建一个唯一的聚集索引
CREATE CLUSTERED INDEX Idx1 ON t1(c);
聚集索引适用的情况:
包含大量非重复值的列。
使用下列运算符返回一个范围值的查询:BETWEEN、>、>=、< 和 <=。
被连续访问的列。
返回大型结果集的查询。
经常被使用联接或 GROUP BY 子句的查询访问的列;一般来说,这些是外键列。对 ORDER BY 或 GROUP BY 子句中指定的列进行索引,可以使 SQL Server 不必对数据进行排序,因为这些行已经排序。这样可以提高查询性能。
OLTP 类型的应用程序,这些程序要求进行非常快速的单行查找(一般通过主键)。应在主键上创建聚集索引。
聚集索引不适用于:
频繁更改的列
这将导致整行移动(因为 SQL Server 必须按物理顺序保留行中的数据值)。这一点要特别注意,因为在大数据量事务处理系统中数据是易失的。
宽键
来自聚集索引的键值由所有非聚集索引作为查找键使用,因此存储在每个非聚集索引的叶条目内。
2).非聚集索引
对于非聚集索引,表中行的物理顺序与键值的逻辑(索引)顺序不相同, 两者是独立的。非聚集索引与课本中的索引类似。数据存储在一个地方,索引存储在另一个地方,索引带有指针指向数据的存储位置。索引中的项目按索引键值的顺序存储,而表中的信息按另一种顺序存储(这可以由聚集索引规定)。如果在表中未创建聚集索引,则无法保证这些行具有任何特定的顺序。
--Purchasing.ProductVendor 表的 VendorID
列创建非聚集索引
USE AdventureWorks;
GO
IF EXISTS (SELECT name FROM sys.indexes
WHERE name = N'IX_ProductVendor_VendorID')
DROP INDEX IX_ProductVendor_VendorID ON Purchasing.ProductVendor;
GO
CREATE INDEX IX_ProductVendor_VendorID
ON Purchasing.ProductVendor (VendorID);
GO
非聚集索引适应的情况:
包含大量非重复值的列,如姓氏和名字的组合(如果聚集索引用于其它列)。如果只有很少的非重复值,如只有 1 和 0,则大多数查询将不使用索引,因为此时表扫描通常更有效。
不返回大型结果集的查询。
返回精确匹配的查询的搜索条件(WHERE 子句)中经常使用的列。
经常需要联接和分组的决策支持系统应用程序。应在联接和分组操作中使用的列上创建多个非聚集索引,在任何外键列上创建一个聚集索引。
在特定的查询中覆盖一个表中的所有列。这将完全消除对表或聚集索引的访问。
3).唯一索引
唯一索引可以确保索引列不包含重复的值。在多列唯一索引的情况下,该索引可以确保索引列中每个值组合都是唯一的。例如,如果在 last_name、first_name 和 middle_initial 列的组合上创建了唯一索引 full_name,则该表中任何两个人都不可以具有相同的全名。
聚集索引和非聚集索引都可以是唯一的。因此,只要列中的数据是唯一的,就可以在同一个表上创建一个唯一的聚集索引和多个唯一的非聚集索引。
唯一索引适用情况:
只有当唯一性是数据本身的特征时,指定唯一索引才有意义。如果必须实施唯一性以确保数据的完整性,则应在列上创建 UNIQUE 或 PRIMARY KEY 约束,而不要创建唯一索引。尽管唯一索引有助于定位信息,但为获得最佳性能结果,建议改用主键或唯一约束。例如,如果打算经常查询雇员表(主键为 emp_id)中的社会安全号码 (ssn) 列,并希望确保社会安全号码的唯一性,则在 ssn 列上创建 UNIQUE 约束。如果用户为一个以上的雇员输入了同一个社会安全号码,则会显示错误。
另外在创建 PRIMARY KEY 或 UNIQUE 约束会在表中指定的列上自动创建唯一索引。
--为Production.UnitMeasure
表的 Name
列创建唯一的非聚集索引
USE AdventureWorks;
GO
IF EXISTS (SELECT name from sys.indexes
WHERE name = N'AK_UnitMeasure_Name')
DROP INDEX AK_UnitMeasure_Name ON Production.UnitMeasure;
GO
CREATE UNIQUE INDEX AK_UnitMeasure_Name
ON Production.UnitMeasure(Name);
GO
以下查询通过尝试插入与现有行包含相同值的一行来测试唯一性约束。
--Verify the existing value.
SELECT Name FROM Production.UnitMeasure WHERE Name = N'Ounces';
GO
INSERT INTO Production.UnitMeasure (UnitMeasureCode, Name, ModifiedDate)
VALUES ('OC', 'Ounces', GetDate());
生成如下错误消息:
(1 行受影响)
消息 2601,级别 14,状态 1,第 1 行
不能在具有唯一索引 'AK_UnitMeasure_Name' 的对象 'Production.UnitMeasure' 中插入重复键的行。
语句已终止。
4).主键索引
数据库表经常有一列或列组合,其值唯一标识表中的每一行。该列称为表的主键。
在数据库关系图中为表定义主键将自动创建主键索引,主键索引是唯一索引的特定类型。如果不存在该表的聚集索引且未指定唯一非聚集索引,则将自动对一列或多列创建唯一聚集索引。
该索引要求主键中的每个值都唯一,且不能为空。当在查询中使用主键索引时,它还允许对数据的快速访问。