【IT168 评论】在前面说过了索引能极大的提高数据的检索速度,那为什么不在每一个列上建索引呢?初学者可能会困惑这个问题,而且通常不知道哪些列该建索引,哪些不该建, 甚至于会把like模糊查询的列也作为索引列,其实绝大多数情况下,like是不使用索引的,只有等于,大于,IN等操作符会使用索引。SQLSERVER对于数据的插入,更新和删除,都要更新相应的索引。这无疑会大大增加更新时间。另外,如果某个数据页已满,这时如果要在该页插入数据时,就会造成页分裂产生碎片(后面还会说到),而影响性能。所以仅当查询的性能比更新的性能更重要时才建索引。
考虑建索引的列
1. 主键
2. 外键
3. 频繁检索的列和按排序顺序频繁检索的列
通常where 后面的条件引用的列都是考虑建索引的列,模糊查询除外(如like查询)
不考虑建索引的列
1.很少或从来不在查询中引用的列
2.只有两个或若干个值的列(比如只有男和女两个值的列)
3.小表(行数很少的表,这时候SQL SERVER花费在索引上的时间比直接扫描表的时间还更长)
SQL SERVER对于建立索引的列,都要付出一定的代价来维护这个索引。另外SQLSERVER会自动分析是否使用该列的索引,比如对于只有男和女两个值的列,如果给它建立索引,SQLSERVER自行分析后,会认为改列使用索引查找的效率不大,因为返回结果集的百分比比较大,于是SQLSERVER会将统计数据记录下来,当下次查找该列时,就会根据该统计数据来决定是否要使用改列的索引。
对于返回结果集百分比比较大的列(比如有100万的数据,而查找的结果将返回50万),SQLSERVER就可能不会使用该列上的索引,而采用全表扫描的方法。可自行测试,插入2000条数据,有1999条数据是一样的,比如ForumID为2的有1999条,ForumID为3的只有一条,这时使用
SET SHOWPLAN_TEXT ON –显示执行计划,可查看查询语句使用了哪些索引
GO
SELECT * FROM Posts WHERE ForumID=2
会发现没有使用ForumID列的索引。
SELECT * FROM Posts WHERE ForumID=3
则使用了ForumID列的索引
进行大批量插入或更新应先删除索引最后再重建索引,避免每插入或更新一条数据时都要更新相应的索引,而影响更新速度。
复合索引(指两列或多列组成的索引,通常where后面由多个列组成的条件时,可以把这些列建成一个复合索引)
1) 只有当WHERE子句中指定索引键的第一列时才使用该索引。
例子:
CREATE INDEX Posts_INDEX
ON Posts(ThreadID,ForumID)
如果SELECT * FROM Posts WHERE ForumID=2 则查询不会使用Posts_INDEX索引
而 SELECT * FROM Posts WHERE ThreadID=10 则会使用Posts_INDEX索引
2) 索引不应过大(<= 8个字节为最好,int型相当于4个字节,SmallInt相当于2个字节)。
3) 首先定义最具唯一性的列(顺序不一样,索引是不一样的)
比如:A列有30%的数据是重复的,B列有10%的列是重复的,C列有25%的数据是重复的,这时候建立索引的列的顺序应当是 B C A