VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > 数据库 > sql数据库 >
  • sql语句大全之创建索引

创建索引
既然知道了什么是索引,也了解了索引的各种类型,现在我们开始在SQL Server中创建一些索引。正如你所预料的,在SQL Server中,可以使用多种不同的方法来创建索引,这些方法将是本章的这一节的主要内容,我们先从如何使用SSMS的表设计器开始介绍。
放置到数据库中的第一个索引,是放在CustomerDetails.Customers表的CustomerId列上。
6.5.1  用表设计器创建索引
回忆前面有关创建CustomerId列的那一章,SQL Server自动在该列中生成数据,而不管是不是在表中插入了新的记录。这个数据永远无法改变,因为它在列上使用了IDENTITY标识。因此,只要有客户记录被添加,该CustomerId列就会自动更新。可以写(如用C#)一个应用程序,以之作为用户前端来更新客户数据的保留区域,它也可能会显示特定客户的细节,但是它不知道CustomerId对于每个新记录来说要求递增,也不知道值是从哪里开始的。
被创建的第一个索引,用于找到客户记录,并对客户信息进行更新。通过使用姓名和地址的组合,应用程序会找到客户,但是在返回的结果中,仍然可能包含了多条记录。例如,可能有一对父子都叫John J.Doe,而他们拥有相同的地址。一旦在屏幕上显示了相关的记录细节,计算机怎么才能知道要对哪个John J.Doe来进行更新呢?
同观察到的客户姓名和地址不同的是,应用程序知道CustomerId,并通过它在SQL Server中查找记录。在完成对名称的搜索的时候,CustomerId也作为返回值的一部分被返回,这样当用户选择正确的John J.Doe时,应用程序也就知道了相应的CustomerId。SQL Server会使用这个值来找到要更新的记录。在下面的练习中,我们为CustomerDetails.Customers表添加这一索引。
练习:以图形化的方式创建索引
(1) 确保SSMS正在运行,并且已经展开了树状视图,能看到ApressFinancial数据库的"表"节点。
(2) 找到要添加索引的第一个表(在本例
。在"说明"中添加某些描述可能会更好。然而,因为索引的名称已经能解释中是Customer- Details.Customers表)。右击并选择"设计"。这会打开表设计器。点击"管理索引和键"按钮(参看图6-1)。
(3) 这时会显示创建索引界面,该界面类似于图6-2。注意,这里已经定义了一个主键。该主键是在第5章中创建的,在图5-24中,当我们创建关系时看到过"保存"对话框。我们将CustomerDetaills.Customers表定义为主键表,而该表尚无主键,于是SQL Server为我们创建了主键。单击"添加"按钮,以创建新的索引并设置索引的属性。
http://images.51cto.com/files/uploadimg/20090515/125637519.jpg
(点击查看大图)图6-2  "索引/键"对话框
 
这个对话框中显示的列是预设的,但是你可以根据需要改变你希望使用的列和选项。然而,不管已经创建了什么索引,为索引所选择的初始列总会是表中定义的第一个列。
(4) 要改变的第一个区域是索引的名称。注意,在"(名称)"文本框中,SQL Server已经创建了一个可能的名称。名称的前缀为IX_,这使用了一种好的命名系统。它还很好地保留了表的名称以及一个有用的后缀,例如列的名称。在本例中,索引被命名为IX_Customers_CustomerId其内容,实际上不再需要什么描述信息了。
(5) 在本例中,SQL Server已经正确地选择CustomerId列作为组成索引的列。同时,它设置索引按照升序排序。对于这个例子,默认的排序方式是合适的。如果存在多个不同排序的列,而一个列在查询的ORDER BY子句中被使用,那么为该列设置索引时采用相应的排序是比较有用的。如果在索引中为某列所设置的排序顺序,同该列在查询的ORDER BY子句中所使用的排序顺序一致,则SQL Server就可以避免执行额外的排序工作,从而提高查询的性能。
提示 如果在索引中只有一列,SQL Server向前读取该索引的速度会同向后读取索引的速度一样快。
(6) 正如以前定义表时所提到的,在添加记录时,SQL Server会自动为CustomerId列的值按顺序生成下一个数字,因为该列具有IDENTITY特性。该值不能在表中被修改,因为允许创建你自己的标识值的选项开关没有打开,所以通过将信息的这两项组合起来,就可以确认值是唯一的。因此,将"是唯一的"选项设置为"是"。
(7) 创建索引的最后一部分是将"创建为聚集的"选项设置为"否"(如图6-3所示)。虽然,从许多标准来看,该索引都是成为聚集索引的理想候选,例如,该索引有很高程度的唯一性,能在查询的一个范围内使用,但是,极少有人会首先通过客户ID来访问该表。更可能的情况是,通过表中的客户支票账户AccountNumber访问该表。最后,这样插入到SQL Server中的记录的顺序将不会被改变。如果你向下滚动屏幕,还应该将"重新计算统计数据"选项设置为"否"。
注解 如果当前是在生产环境中,或者,在开发环境中创建的系统将会迁移至生产环境中,则需要做一些其他方面的考虑。正如我们在前面讨论过的,你可能需要修改文件组或分区方案,以便把索引放置在不同的文件组上。另一个需要注意的区域是"填充因子"。我们将在本练习的最后讨论与之相关的内容。
http://images.51cto.com/files/uploadimg/20090515/125708155.jpg
(点击查看大图)图6-3  "索引/键"对话框中的"聚集"选项
 
(8) 点击"关闭"按钮,关闭对表的修改对话框。在提示是否要保存改变时,回答"是"。这就将索引添加到了数据库中。
在SSMS中构建索引是一个很直观的过程,正如你所看到的。尽管在创建第一个索引的时候,只花费了很少的时间,但是这里面还是有很多地方需要你做一些决策。我们现在就对此进行说明。
为索引选择名称和包含的列是很容易的,不值得在其上耗费过多的笔墨。通过本章开始处介绍构建索引的基础时的讨论,你应该知道在构建索引的时候,需要包含哪些列。
你需要做的第一个主要决策是,确认一个列中是否包含唯一的值。回忆前文,你就会记得,我们构建的第一个索引就是一个标识列,不能通过任何SQL命令往该列中输入数据,因为该列中的数据是由SQL Server自动生成的。同样,在一个标识列中,默认时不可能出现两行包含相同值的情形。然而,这里并没有一种自动的方法来阻止创建重复键。因此,还需要告知SQL Server该索引是唯一的。
移动到"创建为聚集的"设置上,表中的数据最好保持CustomerId的顺序。这是因为当往表中插入数据的时候,新插入的数据对应的CustomerId值,总是比以前的记录对应的CustomerId值要大。因此,每当添加记录的时候,记录都会被添加到表的末尾,也就不再需要使用聚集索引了。因为为索引设置了"是唯一的"选项,所以也就不必再选择"创建为聚集的"选项了。
接着来到了"填充因子"选项,通过该选项告知SQL Server,在SQL Server接续索引开始一个新数据页之前,要用索引数据把页填充到什么程度。对于眼下这一索引,由于数据将是静态的,不会出现太多必须把索引项移来移去的情况,因此最好是把填充因子设置成较高的百分比,如95。
最后,"重新计算统计数据"选项用于定义当数据被修改时,SQL Server是否重新计算关于索引的统计数据。

6.5.2  索引和统计信息
在提取数据的时候,SQL Server显然会考虑采用最好的方法来获取数据,并将其返回给请求它的查询。即使已经在一系列的列上创建了索引,SQL Server也可能会决定使用另外一种方法--也许通过表扫描提取数据的方法会更好更快。在提取相同的数据时,也许有多个索引可供选择。无论出现什么情况,SQL Server都会获取相关的信息,以做出更明智且更正确的选择。这就是统计信息的作用。
SQL Server会为索引中包含的每个列保存其统计信息。这些统计信息在经过了一定的时间或进行了一定数量的数据插入和修改之后被更新。在后台所有这些工作是如何进行的细节,以及SQL Server是如何使统计信息保持最新,都属于高级主题。你只需要知道的是,如果对包含数据的表中的索引进行了修改或构建,不让SQL Server更新表上的统计信息,那么SQL Server在决定如何提取数据的时候,就可能会得到不正确的信息。这甚至意味着,通过改变索引,原意本来是想提高性能,但实际上却导致性能降低。
这并不是要谨慎到总是让SQL Server自动对统计信息进行更新,SQL Server只有在它觉得需要的时候,才会对统计信息进行更新。这种更新可能会发生在一个很忙的处理过程中,而你对要发生的事情却无法控制。当然,如果SQL Server确实(在这个很忙的处理过程中)去更新统计信息,那么,因为若打开了AUTO_UPDATE_STATISTICS_ASYNC选项,统计信息的更新是异步的,所以导致启动更新的查询不会因为系统很忙而受到影响。
通过计划任务来手动更新统计信息,让所有的统计信息都在闲时创建,这样可能会更有效率。在一个有大量对数据的插入或修改的生产环境中,常会看到这种手动更新统计信息的情形。

 

6.5.3  CREATE INDEX语法
通过T-SQL创建索引,就像创建表一样容易。在本节中,我们只看看如何给表创建索引,尽管在SQL Server中,还可以给另一种被称作视图的对象创建索引。
创建索引的完整语法没有在这里列出,不过你可以在SQL Server的联机丛书中找到对它的详细描述。在学习SQL Server 2008的时候,使用其简化版本就已经足够了。大多数情况下,创建索引可以采用下面的版本:
 
 
让我们对该删节版本语句中的选项进行逐一的介绍。
CREATE。必填。该关键字通知SQL Server要构建一个新的对象。
UNIQUE。可选。该选项用于通知SQL Server索引中列出的列的值是每行唯一的。如果试图插入重复的行,则该选项会强制SQL Server返回一个错误信息。
CLUSTERED或NONCLUSTERED。可选。如果这两个选项都没有被明确列出,则默认将索引创建为NONCLUSTERED(非聚集索引)。
INDEX。必填。该选项用于通知SQL Server要创建的新对象是一个索引。
Index_name。必填。这是要创建的索引的名称。该名称在表中必须是唯一的,也建议在整个数据库中保持该名称的唯一性,在前面的相关讨论中,我们使用了"IX_表名_列名"的这种命名方法。
ON table。必填。这是同索引相关联的表的名称。只能是一个表的名称。
column。必填。这是在索引中所包含的列的名称。可以是一个列,也可以是多个列。如果是多个列,列的名称之间需要用逗号进行分隔。
ASC。可选(默认)。如果既没有声明ASC,也没有声明DESC,则默认设置为ASC。ASC选项用于通知SQL Server将列按升序保存。
DESC。可选。它通知SQL Server将列以降序保存。
WITH。可选。不过如果必须使用下面的任何选项,则该WITH选项都是必填的。
IGNORE_DUP_KEY。这个选项只在索引中定义了UNIQUE的时候才有效。如果在前面没有使用UNIQUE选项,则无效。我们一会再对此进行解释。
DROP_EXISTING。如果在数据库中存在相同名称的索引,则可以使用该选项。它会在重建索引之前先删除原先的索引。如果你实际上并不改变索引中的任何列,那么这个选项很有用。我们一会再进行说明。
SORT_IN_TEMPDB。在一个已经有数据的表中构建索引的时候,建议使用这个选项,如果表是一个很大的表,会在临时数据库tempdb中对数据按索引排序,正如我们在第3章所介绍的。如果你有一张大表,或者tempdb数据库位于另一个磁盘上,则可以使用这个选项。这个选项会加速索引的构建,因为SQL Server会对保存表的磁盘设备进行读取,同时对tempdb表所在的另一磁盘设备进行写入。这种读取和写入是并发进行的,从而提高了性能。
ON。可选。如果要指定将索引创建在特定的文件组中的时候,这个选项则是必填的。如果希望将索引构建在PRIMARY文件组,则这个选项不必填。
filegroup。这是要保存索引的文件组的名称。在当前,我们只有一个文件组,即PRIMARY。PRIMARY是一个保留字,如果要使用它,需要用方括号([])将之括住。
有两个选项需要更进一步讨论:IGNORE_DUP_KEY和DROP_EXISTING。这将在下面的两节中予以介绍。
1. IGNORE_DUP_KEY
如果将索引定义为UNIQUE,那么不管怎样尝试,你都无法添加一个在该列中包含重复值的新行。然而,根据在索引上所进行的这一设置,可以执行两种操作。
在进行多行插入的时候,如果指定了IGNORE_DUP_KEY选项,那么即使在插入的行中存在与唯一索引相冲突的内容,SQL Server也不会生成错误信息,而只是生成一个警告信息。那条与现有唯一索引相冲突的行不会被插入,而其他的行则能够成功插入。
在执行多行插入的时候,如果省略了IGNORE_DUP_KEY选项,那么只要有某些行违背了唯一索引,在SQLServer中都将产生错误信息,整个批操作都会被回滚,所有的行都不会被插入到表中。
注意 每次SQL Server进行了一项操作之后,可以通过名为@@ERROR的系统变量来测试是否出现了错误,或者也可以通过Try/Catch这样的错误处理机制来判断是否存在错误。如果出现了错误,通常需要在批操作中进行某些类型的错误处理。如果使用了IGNORE_DUP_KEY选项,则在试图插入重复的行时,不会生成错误,这样在记录被插入的时候,批操作就能正常运行。当然,要小心,在这种情况下,表面上每件事都工作得很好,但实际上可能有某些行没有被插入。
2. DROP_EXISTING
在数据被插入和修改时,索引会被膨胀多次,比理想状态要大很多。就像Access数据库需要被压缩一样,有时SQL Server中的索引也需要被压缩。通过消除索引中的碎片对索引进行压缩可以加快性能,也可以减少对磁盘空间的占用。要压缩索引,可以重建索引,而无需实际修改列中的数据,或者,实际上,可以从无到有,构建整个索引,并访问表中的每一行。
在重建聚集索引时,相比在DROP INDEX命令后再使用CREATE INDEX命令来说,DROP_EXISTING子句提供更强的性能。如果列包含在聚集索引中,每当表的聚集索引被重建时,非聚集索引也会被重建。聚集索引的必须用原来的名字,同样,排序顺序以及创建索引的分区也必须保持一致。最后,唯一性属性也不能改变。因此,如果删除聚集索引再重建它,现有的非聚集索引会被重建两次(如果要重建的话):一次是在删除索引之后,一次是在创建索引之后。当你在时间很关键的批处理窗口中工作时,这一点十分重要,必须谨记。考虑到表和要创建的索引的大小,或许重建聚集索引的工作只能放在周末进行。
DROP_EXISTING可以允许通过显式地删除再重建索引,对现存的索引进行重建。这在重建主键索引的时候特别有用。在采用传统的方法重建主键索引的时候,因为其他的表可能引用了主键,所以需要先在这些表中删除指向该主键上的外键。而通过指定DROP_EXISTING子句,SQL Server会重建索引,而不会对主键约束性产生影响。


相关教程