索引
Microsoft SQL Server提供了分簇和未分簇的索引结构。这些索引是由来自于一个叫做B-tree的树型结构中
的页构成的(同Oracle中的B-tree索引结构相似)。起始页(“根”级)说明了表中值的范围。“根”级页
中的每一个范围指向其他页(判断节点),该节点包含了表中值的更小的范围。以此类推,该节点又可以指
向其他的判断节点,这样就缩小了搜索的范围。树型结构的最后一级叫做“叶”级。
分簇的索引
分簇的索引在Oracle中是以索引组织表的形式实现的。一个分簇的索引是一个物理的包含在一个表中的索引。
表和索引分享同一块存储空间。分簇的索引按索引顺序物理的重排数据行,建立起中间判断节点。索引的
“叶”页包含了真实的表数据。这个结构允许每个表只有一个分簇的索引。Microsoft SQL Server为表自动
的创建一个分簇的索引,无论该表设置了PRIMARY KEY还是UNIQUE约束。分簇的索引对下面这些是有用的:
主键(Primary keys)
不能被更新的列。
返回一个值的范围的查询,使用诸如BETWEEN、、=、
SELECT * FROM STUDENT WHERE GRAD_DATE
BETWEEN '1/1/97' AND '12/31/97'
返回一个大的结果集合的查询:
SELECT * FROM STUDENT WHERE LNAME = 'SMITH'
被用做排序操作的列(ORDER BY、GROUP BY)
例如,在STUDENT表上,在ssn的主键上包含一个未分簇的索引是很有用的,而分簇的索引可以在lname、
fname(last name、first name)上创建,因为这是一种常用的区分学生的方法。
分布表上的更新行为可以防止出现“热点”。热点通常是由于多个用户向一个有上升键的表中填充而引起
的。这样的情景经常导致行级别的锁定。
删除和重建一个分簇的索引在SQL Server中是一种很普通的重新组织表的技术。这是一种确保数据页在磁
盘上是连续的以及重建表中的一些可用空间的简单的方法。这同Oracle中导出、删除以及导入一个表是很
相似的。
一个SQL Server分簇的索引与Oracle的簇在根本上是不一样的。一个Oracle的簇。一个Oracle的簇是两个
或者更多的表的物理集合,它们分享同一个数据块,使用一个公共的列来作为簇键。SQL Server没有与
Oracle簇相似的结构。
作为一个普遍的原则,在表上定义一个分簇的索引将提高SQL Server的性能并且加强空间管理。如果你
不知道对于给定表的查询和更新模式,你可以在主键上创建一个分簇的索引。
下表摘录自示例应用程序的源代码。请注意SQL Server“簇”化索引的使用。
Oracle Microsoft SQL
CREATE TABLE STUDENT_ADMIN.GRADE (
SSNCHAR(9) NOT NULL,
CCODEVARCHAR2(4) NOT NULL,
GRADEVARCHAR2(2) NULL,
CONSTRAINT
GRADE_SSN_CCODE_PK
PRIMARY KEY (SSN, CCODE)
CONSTRAINT GRADE_SSN_FK
FOREIGN KEY (SSN) REFERENCES
STUDENT_ADMIN.STUDENT (SSN),
CONSTRAINT GRADE_CCODE_FK
FOREIGN KEY (CCODE) REFERENCES
DEPT_ADMIN.CLASS (CCODE)
) CREATE TABLE STUDENT_ADMIN.GRADE (
SSNCHAR(9) NOT NULL,
CCODEVARCHAR(4) NOT NULL,
GRADEVARCHAR(2) NULL,
CONSTRAINT
GRADE_SSN_CCODE_PK
PRIMARY KEY CLUSTERED (SSN,
CCODE),
CONSTRAINT GRADE_SSN_FK
FOREIGN KEY (SSN) REFERENCES
STUDENT_ADMIN.STUDENT (SSN),
CONSTRAINT GRADE_CCODE_FK
FOREIGN KEY (CCODE) REFERENCES
DEPT_ADMIN.CLASS (CCODE)
)
未分簇的索引
在未分簇的索引中,索引数据和表数据在物理上是分开的,并且表中的行并不是按顺序存储在索引中的。
你可以把Oracle索引定义移植到Microsoft SQL Server未分簇的索引定义上(就像在下表中显示的一样)。
可是,考虑到性能的缘故,你可能希望选择表的其中一个索引把它创建为分簇的索引。
Oracle Microsoft SQL
CREATE INDEX
STUDENT_ADMIN.STUDENT_
MAJOR_IDX
ON STUDENT_ADMIN.STUDENT
(MAJOR)
TABLESPACE USER_DATA
PCTFREE 0
STORAGE (INITIAL 10K NEXT 10K
MINEXTENTS 1 MAXEXTENTS
UNLIMITED) CREATE NONCLUSTERED INDEX
STUDENT_MAJOR_IDX
ON USER_DB.STUDENT_
ADMIN.STUDENT (MAJOR)
索引语法和命名
在Oracle中,一个索引的名字在一个用户账号中是唯一的。在In Microsoft SQL Server,一个索引的名
字在一个表名中必须是唯一的,但是不必在用户名和数据库名中唯一。因此,在SQL Server中创建或者删
除索引时,你必须说明表名和索引名。另外,SQL Server的DROP INDEX语句可以一次删除多个索引。
Oracle Microsoft SQL
CREATE [UNIQUE] INDEX [schema].index_name
ON [schema.]table_name (column_name
[, column_name]...)
[INITRANS n]
[MAXTRANS n]
[TABLESPACE tablespace_name]
[STORAGE storage_parameters]
[PCTFREE n]
[NOSORT]
DROP INDEX ABC;
CREATE [UNIQUE] [CLUSTERED | NONCLUSTERED]
INDEX index_name ON table (column
[,…n])
[WITH
[PAD_INDEX]
[[,] FILLFACTOR = fillfactor]
[[,] IGNORE_DUP_KEY]
[[,] DROP_EXISTING]
[[,] STATISTICS_NORECOMPUTE]
]
[ON filegroup]
DROP INDEX
USER_DB.STUDENT.DEMO_IDX,
USER_DB.GRADE.DEMO_IDX
索引数据存储参数
Microsoft SQL Server功能选项中的FILLFACTOR选项在很多方面与Oracle中的PCTFREE变量相似。当表的
尺寸增加的时候,索引页也相应改变以容纳新的数据。索引必须自己进行重新组合以容纳新的数据。只有
在创建索引的时候,才使用填充参数百分比,而且在这之后也不加以维护。
FILLFACTOR选项(0~100)控制着在创建索引时应该留下多少空间。如果没有表明参数,就使用缺省
参数,该参数是0,表示将完全填充索引的“叶”页,并且在每个判断节点为至少一个条目留下空间(如
果有两个条目,则表示是一个不唯一的“簇”化索引)。
一个较低的填充因数将会减少索引页的分裂,但是会增加B-tree结构的层数。较高的填充因数能更有效的
使用索引页空间,只需要较少的磁盘I/O来访问索引数据,并且将会减少B-tree结构的层数。
PAD_INDEX选项表示,填充因数也将应用到判断节点页上,就象要用在索引的数据页上一样。
虽然在
Oracle中可能需要调整PCTFREE参数以优化性能。但是在CREATE INDEX语句中很少使用FILLFACTOR
参数。填充因数是为性能优化而提供的。但是它仅仅在一个表上为已有数据创建索引时才有用,并且只有在
你能精确的预测数据在未来的变化时才有用。
如果你将Oracle中的PCTFREE参数设为0,可以考虑将它设为100。这在表中不会发生数据输入和修改(
只读表)时是很有用的。如果填充因数设为100,服务器将创建这样一个索引,它的每一页都是完全填满
的。
忽略重复的关键字
无论在Oracle还是在Microsoft SQL Server中,用户都不能在一个或者一些唯一索引的列中输入重复的值。
这样做将会产生一个错误消息。然而,SQL Server允许开发人员选择INSERT或者UPDATE语句将如何处理这个
错误。
如果在CREATE INDEX语句中使用了IGNORE_DUP_KEY,并且执行了一个创建重复的关键字的INSERT或者UPDATE
语句,SQL Server将给出一个警告信息,并且忽略重复行。如果没有使用IGNORE_DUP_KEY,SQL Server将给
出一个错误信息,并且后滚整个INSERT语句。如果需要了解关于这个选项的更多信息,请参看SQL Server联
机手册。
使用临时表
一个Oracle应用程序也许必须创建一个暂时存在的表。应用程序必须确保在某个时候删除所有为此目的创建
的表。如果应用程序不这样做,那么表空间将很快变得混乱,难以管理。
Microsoft SQL Server提供了临时表数据库对象,这个表就是为上面提到的目的创建的。这样的表总是在
tempdb数据库中创建的。表的名字决定了该表在tempdb数据库中要存在多长时间。
表名 描述
#table_name 这个本地临时表只在用户会话或者创建它的过程的生命期内存在。在用户退出登录或者创建
它的过程完成以后,该表自动删除。该表不能在多个用户之间共享。其它数据库用户不能访问该表。在该
表上不能赋予或者撤消许可。
##table_name 该表也典型的存在于用户会话或者创建它的过程的生命期内。但该表可以被多个用户共享。
在最后一个引用它的