1、要合理使用索引
索引是数据库一个重要的构成部分,很多人都会忽略它,其实索引的根本目的就是
为了提高查询效率。
使用原则如下: 
在经常进行连接,但是没有指定为外键的列上建立索引,而不经常连接的字段则
由优化器自动生成索引。 在频繁进行排序或分组(即进行group by或order by操作)的列上建立索引。 在条件表达式中经常用到的不同值较多的列上建立检索,在不同值少的列上不要
建立索引。比如在雇员表的“性别”列上只有“男”与“女”两个不同值,因此就
无必要建立索引。如果建立索引不但不会提高查询效率,反而会严重降低更新速度
。 
如果待排序的列有多个,可以在这些列上建立复合索引(compound index)。 在写sql语句时就必须注意有些写法是会使得数据库无法使用索引的,比如IS NULL
IS NOT NULL,IN ,NOT IN 等2.避免或简化排序 
应当简化或避免对大型表进行重复的排序。当能够利用索引自动以适当的次序产生
输出时,优化器就避免了排序的步骤。以下是一些影响因素: 
●索引中不包括一个或几个待排序的列; 
●group by或order by子句中列的次序与索引的次序不一样; 
●排序的列来自不同的表。 
为了避免不必要的排序,就要正确地增建索引,合理地合并数据库表(尽管有时可
能影响表的规范化,但相对于效率的提高是值得的)。如果排序不可避免,那么应
当试图简化它,如缩小排序的列的范围等。 3.消除对大型表行数据的顺序存取 
在嵌套查询中,对表的顺序存取对查询效率可能产生致命的影响。比如采用顺序存
取策略,一个嵌套3层的查询,如果每层都查询1000行,那么这个查询就要查询10
亿行数据。避免这种情况的主要方法就是对连接的列进行索引。例如,两个表:学
生表(学号、姓名、年龄……)和选课表(学号、课程号、成绩)。如果两个表要
做连接,就要在“学号”这个连接字段上建立索引。 
还可以使用并集来避免顺序存取。尽管在所有的检查列上都有索引,但某些形式的
where子句强迫优化器使用顺序存取。下面的查询将强迫对orders表执行顺序操作
: 
SELECT * FROM orders WHERE (customer_num=104 AND order_num>1001) OR 
order_num=1008 
虽然在customer_num和order_num上建有索引,但是在上面的语句中优化器还是使
用顺序存取路径扫描整个表。因为这个语句要检索的是分离的行的集合,所以应该
改为如下语句: 
SELECT * FROM orders WHERE customer_num=104 AND order_num>1001 
UNION 
SELECT * FROM orders WHERE order_num=1008 
这样就能利用索引路径处理查询。 4.避免相关子查询 
一个列的标签同时在主查询和where子句中的查询中出现,那么很可能当主查询中
的列值改变之后,子查询必须重新查询一次。查询嵌套层次越多,效率越低,因此
应当尽量避免子查询。如果子查询不可避免,那么要在子查询中过滤掉尽可能多的
行。 5.避免困难的正规表达式 
MATCHES和LIKE关键字支持通配符匹配,技术上叫正规表达式。但这种匹配特别耗
费时间。例如:SELECT * FROM customer WHERE zipcode LIKE “98_ _ _” 
即使在zipcode字段上建立了索引,在这种情况下也还是采用顺序扫描的方式。如
果把语句改为SELECT * FROM customer WHERE zipcode >“98000”,在执行查询
时就会利用索引来查询,显然会大大提高速度。 
另外,还要避免非开始的子串。例如语句:SELECT * FROM customer WHERE 
zipcode[2,3] >“80”,在where子句中采用了非开始子串,因而这个语句也不会
使用索引。 6.使用临时表加速查询,SQL2000中还可以使用表变量来代替临时表 
把表的一个子集进行排序并创建临时表,有时能加速查询。它有助于避免多重排序
操作,而且在其他方面还能简化优化器的工作。例如: 
SELECT cust.name,rcvbles.balance,……other columns 
FROM cust,rcvbles 
WHERE cust.customer_id = rcvlbes.customer_id 
AND rcvblls.balance>0 
AND cust.postcode>“98000” 
ORDER BY cust.name 
如果这个查询要被执行多次而不止一次,可以把所有未付款的客户找出来放在一个
临时文件中,并按客户的名字进行排序: 
SELECT cust.name,rcvbles.balance,……other columns 
FROM cust,rcvbles 
WHERE cust.customer_id = rcvlbes.customer_id 
AND rcvblls.balance>0 
ORDER BY cust.name 
INTO TEMP cust_with_balance 
然后以下面的方式在临时表中查询: 
SELECT * FROM cust_with_balance 
WHERE postcode>“98000” 
临时表中的行要比主表中的行少,而且物理顺序就是所要求的顺序,减少了磁盘
I/O,所以查询工作量可以得到大幅减少。 
注意:临时表创建后不会反映主表的修改。在主表中数据频繁修改的情况下,注意
不要丢失数据。
 
7.用排序来取代非顺序存取 
非顺序磁盘存取是最慢的操作,表现在磁盘存取臂的来回移动。SQL语句隐藏了这
一情况,使得我们在写应用程序时很容易写出要求存取大量非顺序页的查询。 
有些时候,用数据库的排序能力来替代非顺序的存取能改进查询。   
 

解决方案 »

  1.   

    1、存储
       将硬盘分成NTFS格式,NTFS比FAT32快,并看你的数据文件大小,1G以上你可以采用多数据库文件,这样可以将存取负载分散到多个物理硬盘或磁盘阵列上。2、tempdb
       tempdb也应该被单独的物理硬盘或磁盘阵列上,建议放在RAID 0上,这样它的性能最高,不要对它设置最大值让它自动增长3、日志文件
       日志文件也应该和数据文件分开在不同的理硬盘或磁盘阵列上,这样也可以提高硬盘I/O性能。4、分区视图
       就是将你的数据水平分割在集群服务器上,它适合大规模OLTP,SQL群集上,如果你数据库不是访问特别大不建议使用。5、簇索引
       你的表一定有个簇索引,在使用簇索引查询的时候,区块查询是最快的,如用between,应为他是物理连续的,你应该尽量减少对它的updaet,应为这可以使它物理不连续。6、非簇索引
       非簇索引与物理顺序无关,设计它时必须有高度的可选择性,可以提高查询速度,但对表update的时候这些非簇索引会影响速度,且占用空间大,如果你愿意用空间和修改时间换取速度可以考虑。7、索引视图
       如果在视图上建立索引,那视图的结果集就会被存储起来,对与特定的查询性能可以提高很多,但同样对update语句时它也会严重减低性能,一般用在数据相对稳定的数据仓库中。8、维护索引
       你在将索引建好后,定期维护是很重要的,用dbcc showcontig来观察页密度、扫描密度等等,及时用dbcc indexdefrag来整理表或视图的索引,在必要的时候用dbcc dbreindex来重建索引可以受到良好的效果。不论你是用几个表1、2、3点都可以提高一定的性能,5、6、8点你是必须做的,至于4、7点看你的需求,不建议的。
      

  2.   

    范式
    构造数据库必须遵循一定的规则在关系数据库中这种规则就是范式范式是符合
    某一种级别的关系模式的集合关系数据库中的关系必须满足一定的要求即满足不同的
    范式目前关系数据库有六种范式第一范式1NF 第二范式2NF 第三范式3NF
    第四范式4NF 第五范式5NF 和第六范式6NF 满足最低要求的范式是第一
    范式1NF 在第一范式的基础上进一步满足更多要求的称为第二范式2NF 其余
    范式以次类推一般说来数据库只需满足第三范式3NF 就行了下面我们举例介绍
    第一范式1NF 第二范式2NF 和第三范式3NF
    第一范式1NF
    在任何一个关系数据库中第一范式1NF 是对关系模式的基本要求不满足第一
    范式1NF 的数据库就不是关系数据库
    所谓第一范式1NF 是指数据库表的每一列都是不可分割的基本数据项同一列中
    不能有多个值即实体中的某个属性不能有多个值或者不能有重复的属性如果出现重复
    的属性就可能需要定义一个新的实体新的实体由重复的属性构成新实体与原实体之
    间为一对多关系在第一范式1NF 中表的每一行只包含一个实例的信息例如对
    于图3-2 中的员工信息表不能将员工信息都放在一列中显示也不能将其中的两列或多
    列在一列中显示员工信息表的每一行只表示一个员工的信息一个员工的信息在表中只
    出现一次简而言之第一范式就是无重复的列
    第二范式2NF
    第二范式2NF 是在第一范式1NF 的基础上建立起来的即满足第二范式2NF
    必须先满足第一范式1NF 第二范式2NF 要求数据库表中的每个实例或行必须可
    以被惟一地区分为实现区分通常需要为表加上一个列以存储各个实例的惟一标识如
    图3-2 员工信息表中加上了员工编号emp_id 列因为每个员工的员工编号是惟一的
    因此每个员工可以被惟一区分这个惟一属性列被称为主关键字或主键主码
    第二范式2NF 要求实体的属性完全依赖于主关键字所谓完全依赖是指不能存在
    仅依赖主关键字一部分的属性如果存在那么这个属性和主关键字的这一部分应该分离
    出来形成一个新的实体新实体与原实体之间是一对多的关系为实现区分通常需要为表
    加上一个列以存储各个实例的惟一标识简而言之第二范式就是非主属性非部分依赖
    于主关键字
    第三范式3NF
    满足第三范式3NF 必须先满足第二范式2NF 简而言之第三范式3NF
    要求一个数据库表中不包含已在其它表中已包含的非主关键字信息例如存在一个部门
    信息表其中每个部门有部门编号dept_id 部门名称部门简介等信息那么在图3-2
    的员工信息表中列出部门编号后就不能再将部门名称部门简介等与部门有关的信息再加
    入员工信息表中如果不存在部门信息表则根据第三范式3NF 也应该构建它否则
    就会有大量的数据冗余简而言之第三范式就是属性不依赖于其它非主属性