初学C#的时候,用控制台实现过学生信息管理系统。那个时候所有的数据都是保存在泛型集合中,然后创建各种工厂类,各种继承多态……虽然最后做出来后感觉挺不错,但是数据的冗余大的不得了。在编码的时候还得写一个模块测试一个模块,一旦其中一个模块出现一点小小的BUG那么就会造成数据的不准确。
后来学到了数据库,发现用SELECT [字段1,字段2,……] from 表名 就能查到我需要的所有的数据。感觉挺不错,查询效率又高,有简便。不需要自己手动建什么工厂类啊,继承多态了。用的久了,会开始想探索下数据库的查询是怎么实现的。个人感觉,如果在一个表中执行查询,那么数据库会遍历所有行查找到符合条件的行,然后返回出来。实现思路和用C#实现学生信息管理系统差不多。这个时候就出现了这样一个问题,如果这个表里面的数据有上亿条,甚至是几亿亿条呢?难道说为了查找那么一行记录还要遍历所有行去找到符合条件的行?这样未免太浪费资源了吧!现在才知道,原来数据库还有一个叫索引的东西,就像是字典中的目录。比如说你要查找一个“城”字,只需要在目录中找到拼音ch的所在页区间,然后翻到指定的页区间中找,很快就能找到“城”字。因为有了索引,所以数据库的查找效率不会因为数据量的庞大而造成大幅度下降(当然是会下降一点点)。如果没有索引这个东西,就好比字典没有了目录,那么这个查找数据的效率就可想而知了。
一个数据库一般来说会有很多的表,为了实现数据的各种完整性,那么就要设置主键,外键,约束……。在我们实现数据的各种完整性的时候,我们就已经创建了索引。数据库默认会为主键列和有唯一约束的列创建索引。主键列为“主键索引”,默认为“聚集索引”;有唯一约束的列为“唯一索引”,默认为“非聚集索引”。
上面说到为列创建索引可以大大增加查询的效率,但是这个世界上的物质是守恒的,也就是人们常说的“物极必反”。如果为表中的所有列都创建索引,那么无论用这个表中的哪个列作为查询条件,这个查询的速度都是飞一般的快。但是,如果要向表中插入数据的时候,那么可就悲剧了。插入了一条新的记录,那么相对应的也要为这条新的记录创建索引。当然,你只是插入一条当然感觉不到插入数据的速度慢了。但是如果一秒钟写入几千条,几万条数据呢?估计系统会直接崩溃吧……所以,一般只需要为主键列,外键列,和有唯一约束的列创建索引。
创建索引的时候还有一个东西很重要,那就是“填充因子”。创建索引时,可以指定一个填充因子,以便在索引的每个叶级页上留出额外的间隙和保留一定百分比的空间,供将来表的数据存储容量进行扩充和减少页拆分的可能性。填充因子的值是从 0 到 100 的百分比数值,指定在创建索引后对数据页的填充比例。值为 100 时表示页将填满,所留出的存储空间量最小。只有当不会对数据进行更改时(例如,在只读表中)才会使用此设置。值越小则数据页上的空闲空间越大,这样可以减少在索引增长过程中对数据页进行拆分的需要,但需要更多的存储空间。当表中数据会发生更改时,这种设置更为适当。
说的通俗易懂点吧。打个比方,为了给一个班的100个同学排一下顺序,我们可以给每一位同学一个编号,如:a. 从1,2,3,4,5,6,7,.....100。这时,我们说填充因子是100。此时,如果又来了新同学,而其排名要在中间某位置的话,我们就要改变许多个同学的号码,如新同学排5号,就需要将5号以后的同学号码都加1才行。b.我们又可以给同学这样编号:10,20,30,40,50,60,70.......1000也同样完成了顺序的排列.我们说这时填充因子是0,此时如果来了新同学,又是排在第七位的话,那么我们只许将其号码编为65就行了.其它同学都不用变。可以看出,填充因子大的时候,点用的号码空间小,耗费资源少,小的时候呢,占用资源加大,但操作方便,迅速。所以,在SQL2000O中索引的填充因子就是这个道理,填充因子大的时候,插入或修改记录后重新索引的工作会很大,磁盘IO操作增加,性能必然降,但其占用空间小.填充因子小的时候呢,索引文件占用磁盘及内存空间相对要大,但是,系统身重新索引所需IO操作减少,性能提高,只是多占用一些存储空间。如果设置填充因子为100的话,那么除非你不会再对表进行INSERT和UPDATE操作。因此,孰重孰轻自已决定就行了.....
最后提下,想查询你创建的索引的话,可以用系统存储过程 exec sp_helpindex 表名 ,也可以用视图sys.indexes查看 select * from sys.indexes