数据库设计规范(五)

1.数据库命名规范

1.1.命名规范

  • 命名对象包括文件、类、过程、函数、模块、变量。
  • 尽可能使用英文。在英文很差表达其含义时,可以使用汉语拼音。
  • 名称应能反映所表明对象的实际内容和做用。可以使用多个词组合,但不要使用人名、项目组名。
  • 只可以使用字母、数字和连字符‘_’,但第一个字符必须是字母。
  • 多个词组合较长时可以使用缩写,但尽量使用标准的缩写。在一个系统中要创建缩语表以规范缩写的使用。
  • 命名时请考虑名字的惟一性和含义的准确性,不得使用很是相近的名字表示几个不一样含义的对象。
  • 名称中字母的大小写在实施细则中规定,在同一个项目中必须统一。

1.2.相关对象标识

与特定内容相关的一组数据库对象,赋予一个指定的3字符的英文标识,便于识别和查找。如与客户信息CustomerInfo相关的数据库对象,则用mci标识;如与帐户费用AccountExpense相关数据库对象,则用eae标识。
 程序员

1.3.内容标识

与对象表示的内容相关的名称。尽可能使用描述性的、完整的、可以描述每一个对象的用途的名字;若是单词很长,可以使用缩写。
用英文单词或多个单词组合(尽可能避免使用汉语拼音,拒绝使用汉字)命名,每单词首字母大写。
用缩写时要使用标准的或通用的写法,同时要创建缩写词典以便标准化。
对于专业词汇,要创建词汇词典,以便统一和识别。
 算法

1.4.命名规则

数据库对象 前缀 相关对象标识 内容标识 后缀
数据库     <内容标识>  
数据表 t_ <相关对象标识>_ <内容标识> _[<后缀>]
字段     <内容标识>  
视图 v_ <相关对象标识>_ <内容标识>  
函数 f[t]_ <相关对象标识>_ <内容标识>  
存储过程 p_ <相关对象标识>_ <内容标识>  
触发器 tr[i][d][u]_ <表名> <内容标识>  
索引 Ix_ <表名> <内容标识>  
主键 pk_ <表名> <内容标识>  
外键 fk_ <表名> <内容标识>  
注:
① 只在须要时使用,用以表示同名表间的差异。如主表_m,明细表_d,年度_2000/_2010。
②f:返回值的函数;ft:返回列表的函数。
③i:插入触发;d:删除触发;u:更新触发
④ 不要使用数据库系统的保留词。对于可能在多个表中出现的,或经常使用的名称,要创建字段名词典,统一数据类型和长度,以便标准化。
 

2.数据库编码规范

2.1.编码规范总则

经过创建软件编码规范,造成代码约定,提升程序的可读性、一致性、可维护性,共享性和继承性,保证程序质量和可靠性,延长程序的生命周期。
 sql

2.1.1.文件结构

(1).每一个程序文件由标题、主体内容和附加说明三部分组成。
(2).标题:文件最前面的注释说明,其内容主要包括:程序名、做者、程序目的/功能、版本信息、版本号、生成日期、修改日志、依赖性等。必要时应有更详尽的说明。
(3).主体内容:为文件源代码部分基本上由预处理语句、类型定义、变量定义、实现等部分组成。
(4).附加说明:文件末尾的补充说明,如参考资料等,若内容很少也可放在标题部分的最后。
 数据库

2.1.2.排版

(1). 要采用缩进风格编写,缩进使用半角空格键,每级缩进的空格数为4个。
(2).  每一个程序块或语句块的起止符(如C/C++语言的大括号“{”和“}”,SQL子查询的“(”和“)”)应各独占一行而且与包含的语句有相同的缩进。
(3).  函数或过程的开始、结构的定义及循环、判断等语句中的代码都要采用缩进风格。
(4).  较长的语句要分红多行书写,通常每行为120字符。长语句要在低优先级操做符处划分新行,操做符放在新行之首。划分出的新行相对首行要缩进。不得在单词或词组中间分行。
(5).  独立的程序块之间、变量说明以后、或是程序说明跟主体之间必须加空行。
(6).   一行只写一条语句,不容许把多个短语句写在一行中。
 编程

2.1.3.注释

为何要使用注释:
 数据结构

  • 方便代码的阅读和维护(修改),但不会增长可执行文件的大小和处理时间;
  • 咱们在维护代码时,多数时间不是编写或修改代码,而是在理解原有代码(有至关部分是本身编写的)。而好的注释能够大大减小理解代码的时间。

 
(1)注释的原则是有助于对程序的阅读理解,注释不宜太多也不能太少,注释语言必须易懂、简洁、含义准确,防止注释二义性。
(2).  函数或程序的头部应进行注释,列出:函数或程序名、功能说明、参数说明、做者、建立时间、修改人、修改日期。
(3).   边写代码边注释,修改代码同时修改相应的注释,以保证注释与代码的一致性。没有用的注释要及时删除。
(4).  避免在注释中使用缩写,特别是很是用缩写。若是使用缩写,应对缩写进行必要的说明。
(5).  注释应与其描述的代码邻近,可放在多行代码的上方或单行代码的行尾,不可放在下方;与被解释的代码之间不得有空行;如放于上方则需与其上面的代码用空行隔开。
(6).  注释与所描述内容使用相同的缩进。
(7).  避免在一行代码或表达式的中间插入注释。
(8).  当代码段较长,特别是多重嵌套时,可在程序块的结束行右方加注释标记,以代表某程序块的结束。
(9).  使用中文注释。
 并发

2.2.SQL开发规范

规范sql的编写格式,提升SQL语句的可读性,共享性和执行效率。
大部分业务系统须要与数据库进行交互,与数据库交互的主要方式就是SQL语句,编写规范的SQL语句不但利于阅读,并且被数据库重复使用的概率也较大,执行效率相对较高,编写的好的SQL与编写的差的SQL在执行性能上可能会差几倍甚至几千几万倍,所以养成好的SQL编写规范对于提升项目质量及提升开发人员自身素质有着潜在的极大的影响。
 数据库设计

2.2.1.书写

SQL书写遵照以下规范:
 ide

  • 在同一个项目中,为了最大限度实现SQL的共享,要求书写sql语句时大小写要一致,为了阅读方便和统一块儿见,全部SQL语句所有小写(如SQL谓词,字段名,表名等),常量除外,常量能够按须要书写。

举例:下面两个相同的语句除常量外都要统一块儿来。
1)selectnamefromemp;
2)select'NAME' fromempwhereemp_no='QD001'?    
 函数

  • SQL语句尽量放在一行,若SQL太长放在一行中影响阅读时可分多行,但要保持缩进一致,缩进可用TAB或者空格,但TAB数和空格数最好一致。

 
 

  • SQL语句中,各谓词之间以空格分割的,尽可能保持空格数量一致,即若用一个空格分割,则所有都用一个空格分割,便于数据库可以共享。

       
 

  • 能使用绑定变量的,尽可能使用绑定变量,尤为是在前台程序中.

 
 

  • 对下面列出的状况,慎重使用绑定变量:

1)  列值倾斜严重,如:某一状态列大部分值是‘1’,只有极少数值为’2’,这种状况不宜用绑定变量,而应该用常量,便于数据库使用柱状图统计信息。
2)  日期时间列。
 
总之:书写SQL的目标是若sql的用途是同样的,则sql应该彻底一致,包括空格,大小写。下面的语句因为写法不彻底相同,数据库会理解为4条不一样的语句从而致使重复编译,下降了性能。
1)selectnamefromempwhereemp_no='111'
2)SelectnameFromempWhereemp_no='111'
3)selectNamefromEMPwhereemp_no='111'
4)selectnamefromempwhereEMP_NO='111'
 
下面的语句,因为语句规范,能够只编译一次。
1)selectnamefromempwhereemp_no='111'
2)selectnamefromempwhereemp_no='222'
3)selectnamefromempwhereemp_no='333'
4)selectnamefromempwhereemp_no=:b1
 

2.2.2.     注释

(1).开头注释
全部的过程、函数、触发器、包都应该在开头有注释,
注释中要列出对象名称;完成功能简述;调用模块,调用时机;
建立日期;做者信息;历次修改日期;历次修改人;历次修改缘由和其它做者认为重要的内容,在每次修改的注释之间建一空行。
 
举例以下:
/*************************************************************
名称:PRO_WO_MULTI_REPAIR_JOB
功能:屡次维修断定程序
调用:自动统计月结前,后台调用
做者:xxx
时间:2009-02-20
 
修改人:xxx
修改时间:2009-03-08
修改内容:重写部分SQL优化性能
 
修改人:xxx
修改日期:2010-03-23
修改内容:增长判断条件
 
*************************************************************/
 
(2).块注释
对于复杂的语句块,必须提供块注释,清晰描述该语句块的功能逻辑、数据结构以及算法;块注释应该和它们所描述的代码具备同样的缩进格式;块注释之首应该有一个空行,用于把块注释和代码分割开来;块注释结构以下所示:
/*
    计算配送能力系数:
    派工系数=a*b+c*d+e*f
    a:考评成绩,取xx的考评成绩
    c:承担度度,根据当前遗留量和总服务能力计算所得,
    c=当前遗留配送量/总配送能力
     ...
*/
 
(3).行注释
对于复杂的SQL语句,必须提供行注释,清晰描述该SQL语句功能以及目的;行注释结构以下所示:
--计算动态能力得分,当负荷率超高时,可能出现负值,注意处理。
 
添加注释时要注意:注释中包含GO 命令时会生成一个错误消息。
 

2.2.3.     存储过程和函数

(1).命名规范
存储过程/函数的命名(代码)使用如下方式:
存储过程名=  p_ + 模块代码+ 存储过程代码
函数名=  f_ + 模块代码+ 函数代码
存储过程以表现其功能的简洁语言进行命名,定义好后,放置于每个Diagram的特定区域(通常置于右边部分的上边)。
 
(2).存储过程/函数头定义规范
包括过程/函数名称定义、参数定义、注释说明、变量定义四部分。
 

  • 参数定义

全部的参数必须显示指出变量类型,对于返回参数,必须指出其方向;
参数变量定义格式为:“a“+参数类型简写+“_”+参数名称,其中a是单词argument(参数)的第一个字母,参数类型以下:
文本型:s
日期时间型:d
数字型:n
×××:i
布尔型:b
举例:as_name 表示文本型
      ad_birthdate 表示日期时间型
      an_age   表示数字型
 
 

  • 注释说明

见前面描述。
 
(3).变量定义规范
1).变量的命名
除游标变量之外,全部的变量命名采用此方式:
变量名= “v_”+ 变量名称
游标变量采用:
变量名= “cur”+ 变量名(第一个字母大写)。
其中变量名称由表明变量确切含意的单词代码组合而成,每个单词的首字母根据阅读的方便性决定是否须要大写。
举例:
变量名:v_EmpName
游标名:curNetlist
 
2).变量类型
定义变量的类型时,尽可能采用显示定义的方式。尽可能将变量的定义分开来,并进行格式化,以便程序代码的阅读。例如:
v_UserName   CHAR(10)
v_SEX        CHAR(1)
 
(4).变量注释
原则上要求对于通常变量定义时必须加上注释,如变量有特定的值范围,则必须显示描述各确切值及其含意说明;
 
(5).存储过程/函数体定义规范
在过程/函数的定义中,最重要的是过程代码的严谨性和可读性,主要包括如下的注意事项:
1).如无特殊须要,SQL中涉及的全部内容都要小写。
2).原则上要求全部的SQL语句必须在其前面加上注释,对于IF/CASE等流程控制语句,必须在语句前/后说明控制处理和可能的流程方向;
3).全部的赋值语句要求变量与运算符之间要有空格。如:v_Count := v_Count + 1,并保持适当的对齐;
4).尽可能避免复杂SQL,尤为是关联多个大表的SQL,对于须要关联多个大表的SQL最好分解成小的SQL分步处理,避免出现性能问题,对于复杂的语句块之间,要求中间加入空行;
5).全部可能的返回结果,必须在过程体中显示定义和说明,并在注释中说明。在其它的过程、代码中调用本过程/函数时,必须在其代码中处理全部的各类可能的返回结果;
6).锁定数据时,尽量只锁定要操做的数据行,避免锁定整个表,限制使用local table等DDL语句,若要对数据表、数据行加锁时,须要考虑由此致使的并发操做失败的处理;
7).全部的过程/函数代码在编写以前,必需要有设计原型及其说明;
 
(6).  存储过程/函数错误定义
 
1).全部的DML语句必须考虑死锁、并发、主关键字不惟一等的出错异常处理,应该对全部可能出现的异常进行捕获、编码处理,并注明异常的内容;
2).异常处理有两种须要考虑的问题,一是事务的完整性;二是错误的出错日志及返回处理。全部异常的根据其类型和等级进行如下的处理:

类型 内容 处理  
系统级 数据库级发出的底层的异常,如主关键字不惟一冲突等; 返回定义错误代码为其它错误,彻底回退事务,登陆异常日志;  
应用级 应用系统定义并发出的异常,如指定记录不存在; 定义应用级错误代码,根据实际状况处理事务;  
 
(7).  存储过程/函数使用原则
1).存储过程功能尽可能保持独立、复用,但尽可能避免嵌套调用,充分考虑其性能体现;
2).使用前台代码调用存储过程时,必须考虑返回传入参数的有效性、代码的处理及展现、事务完整性处理;
3).直接使用参数做为变量处理,不要在存储过程当中定义参数一样含义的变量使用,避免因为值的不一样致使性能问题。
 

2.2.4.触发器

(1).命名规范
触发器不一样类型的命名结构以下

操做 时机 命名结构
Insert After ai_表名
Update After au_表名
Delete After ad_表名
 
(2).触发器编写规范
请参见存储过程/函数编写规范。
 
(3).异常
全部过程和函数处理必须考虑可能出现的错误,一是数据库或操做系统底层错误;二是因为业务逻辑形成的错误;三是无反应或超时;四是输入参数不在指定范围内。
设计全部的过程时,必须考虑出错后的恢复。
 

2.3.优化

2.3.1.SQL语句原则

  • Where子句尽可能避免使用函数;
  • 避免在ORDER BY子句中使用表达式;
  • 限制在GROUP BY子句中使用表达式;
  • 慎用游标;
  • 大小写规范统一,变量绑定统一,避免重复编译;
  • 尽量少的返回结果集行的数量
  • 避免使用select * 语句;
  • 减小结果集中的列的数量;
  • 视图嵌套使用不能超过3层;
  • 不要使用没有意义的列做为汇集索引列,例如,加1自增列;
  • 避免隐式类型转换,例如字符型必定要用’’,数字型必定不要使用’’;
  • 查询语句必定要有范围的限定,避免全表扫描操做;
  • 合理对大表进行分区;
  • 慎用DISTINCT关键字;
  • 慎用UNION关键字,能够用OR替代;
  • 使用top 1替count(*)来判断是否存在记录;

2.3.2.索引建立原则

  • 同一索引中的组成列最好不要超过3列。
  • 把常常一块儿出现的字段组合在一块儿,组成组合索引,组合索引的字段顺序与主键同样,也须要把最经常使用的字段放在前面,把重复率低的字段放在前面。
  • 根据使用频率决定哪些字段须要创建索引,选择常常做为链接条件、筛选条件、聚合查询、排序的字段做为索引的候选字段。
  • 根据数据量决定哪些表须要增长索引,数据量小的能够只有主键。
  • 若某列中有大量的值是空值,能够创建索引。
  • 要对值分布较宽的列创建索引。
  • 若表主要用来查询,则可按须要创建索引,若对表操做主要是UPDATE,则尽量少建索引。
  • 不要对值较窄的列创建索引,如性别
  • 不要索引较小的表(如表不足1000行)
  • 若某列的值大部分是a,少数是别的值(如b,c,d…),且常常以该列的其它值(如b,c,d…)为查询条件,则能够将值a设为空值,并在此列上建立索引。

2.3.3.充分利用索引

(1).函数、表达式使用
在where语句中,尽可能避免在运算符左边对列进行函数或者表达式操做,容易引发全表扫描,要尽量将操做移至运算符右边。
 
(2).IN/OR子句使用
IN、OR、NOT IN Sql Server2005数据库能够分析出应该根据索引查找。属于2005版本的新特性。
 
(3). !=或<>操做符子句使用
!=或<>操做符能够用INDEXSEEK查找的,能够正常使用。
 
(4). 不要对索引字段进行运算
例如:
SELECTIDFROMTWHERENUM/2=100
应改成:
SELECTIDFROMTWHERENUM=100*2
 
SELECTIDFROMTWHERENUM/2=NUM1
若是NUM有索引应改成:
SELECTIDFROMTWHERENUM=NUM1*2
若是NUM1有索引则不该该改。
 
 
 
(5). 不要对索引字段进行格式转换
日期字段的例子:
WHERECONVERT(VARCHAR(10),日期字段,120)='2008-08-15'
应该改成
WHERE日期字段〉='2008-08-15'  AND日期字段<'2008-08-16'
 
ISNULL转换的例子:
WHEREISNULL(字段,'')<>''应改成:WHERE字段<>''
WHEREISNULL(字段,'')=''不该修改
WHEREISNULL(字段,'F')='T'应改成:WHERE字段='T'
WHEREISNULL(字段,'F')<>'T'不该修改
 
(6).不要对索引字段使用函数
WHERELEFT(NAME,3)='ABC'或者WHERESUBSTRING(NAME,1,3)='ABC'
应改成:
WHERENAMELIKE'ABC%'
 
日期查询的例子:
WHEREDATEDIFF(DAY,日期,'2005-11-30')=0
应改成:WHERE日期>='2005-11-30'AND日期<'2005-12-1'
 
WHEREDATEDIFF(DAY,日期,'2005-11-30')>0
应改成:WHERE日期<'2005-11-30'
 
WHEREDATEDIFF(DAY,日期,'2005-11-30')>=0
应改成:WHERE日期<'2005-12-01'
 
WHEREDATEDIFF(DAY,日期,'2005-11-30')<0
应改成:WHERE日期>='2005-12-01'
 
WHEREDATEDIFF(DAY,日期,'2005-11-30')<=0
应改成:WHERE日期>='2005-11-30'
 
(7).不要对索引字段进行多字段链接
例如:
WHEREFAME+'.'+LNAME='H.Y'
应改成:
WHEREFNAME='H'ANDLNAME='Y'
 

2.3.4.Like的使用

对索引列避免使用like ‘%xx’, 应该使用like ‘xx%’。设计数据结构时就应该考虑这个问题,不要出现必需要采用like ‘%xx’才能知足业务须要的情形。
 

2.4.编码阶段

2.4.1.尽量少的范围数据

A、 横向来看,不要写SELECT *的语句,而是选择你须要的字段。
B、 纵向来看,合理写WHERE子句,不要写没有WHERE的SQL语句。
C、 注意SELECT INTO后的WHERE子句,由于SELECT INTO把数据插入到临时表,这个过程会锁定一些系统表,若是这个WHERE子句返回的数据过多或者速度太慢,会形成系统表长期锁定,诸塞其余进程。
D、对于聚合查询,能够用HAVING子句进一步限定返回的行。
 

2.4.2.尽量少的重复操做

A、控制同一语句的屡次执行,特别是一些基础数据的屡次执行是不少程序员不多注意的。
B、减小屡次的数据转换,也许须要数据转换是设计的问题,可是减小次数是程序员能够作到的。
C、杜毫不必要的子查询和链接表,子查询在执行计划通常解释成外链接,多余的链接表带来额外的开销。
D、合并对同一表同一条件的屡次UPDATE,好比
UPDATEEMPLOYEESETFNAME='H'WHEREEMP_ID=' F'
UPDATEEMPLOYEESETLNAME='Y'WHEREEMP_ID=' F'
这两个语句应该合并成如下一个语句
UPDATEEMPLOYEESETFNAME='H',LNAME='Y'WHEREEMP_ID=' F'
 
E、UPDATE操做不要拆成DELETE操做+INSERT操做的形式,虽然功能相同,可是性能差异是很大的。
F、不要写一些没有意义的查询,好比
SELECT*FROMEMPLOYEEWHERE1=2
 

2.4.3.注意事务和锁

事务是数据库应用中和重要的工具,它有原子性、一致性、隔离性、持久性这四个属性,不少操做咱们都须要利用事务来保证数据的正确性。在使用事务中咱们须要作到尽可能避免死锁、尽可能减小阻塞。具体如下方面须要特别注意:
A、事务操做过程要尽可能小,能拆分的事务要拆分开来。
B、 事务操做过程不该该有交互,由于交互等待的时候,事务并未结束,可能锁定了不少资源。
C、 事务操做过程要按同一顺序访问对象。
D、提升事务中每一个语句的效率,利用索引和其余方法提升每一个语句的效率能够有效地减小整个事务的执行时间。
E、 尽可能不要指定锁类型和索引,SQL SERVER容许咱们本身指定语句使用的锁类型和索引,可是通常状况下,SQL SERVER优化器选择的锁类型和索引是在当前数据量和查询条件下是最优的,咱们指定的可能只是在目前状况下更有,可是数据量和数据分布在未来是会变化的。
 

2.4.4.注意临时表和表变量的用法

在复杂系统中,临时表和表变量很难避免,关于临时表和表变量的用法,须要注意:
A、若是语句很复杂,链接太多,能够考虑用临时表和表变量分步完成。
B、若是须要屡次用到一个大表的同一部分数据,考虑用临时表和表变量暂存这部分数据。
C、若是须要综合多个表的数据,造成一个结果,能够考虑用临时表和表变量分步汇总这多个表的数据。
D、其余状况下,应该控制临时表和表变量的使用。
E、关于临时表和表变量的选择,不少说法是表变量在内存,速度快,应该首选表变量,可是在实际使用中发现,这个选择主要考虑须要放在临时表的数据量,在数据量较多的状况下,临时表的速度反而更快。
F、关于临时表产生使用SELECTINTO和CREATETABLE+INSERTINTO的选择,咱们作过测试,通常状况下,SELECTINTO会比CREATETABLE+INSERTINTO的方法快不少,可是SELECTINTO会锁定TEMPDB的系统表SYSOBJECTS、SYSINDEXES、SYSCOLUMNS,在多用户并发环境下,容易阻塞其余进程,因此个人建议是,在并发系统中,尽可能使用CREATETABLE+INSERTINTO,而大数据量的单个语句使用中,使用SELECTINTO。
G、注意排序规则,用CREATETABLE创建的临时表,若是不指定字段的排序规则,会选择TEMPDB的默认排序规则,而不是当前数据库的排序规则。若是当前数据库的排序规则和TEMPDB的排序规则不一样,链接的时候就会出现排序规则的冲突错误。通常能够在CREATETABLE创建临时表时指定字段的排序规则为DATABASE_DEFAULT来避免上述问题。
 

2.4.5.注意子查询的用法

子查询是一个 SELECT查询,它嵌套在 SELECT、INSERT、UPDATE、DELETE语句或其它子查询中。任何容许使用表达式的地方均可以使用子查询。
子查询可使咱们的编程灵活多样,能够用来实现一些特殊的功能。可是在性能上,每每一个不合适的子查询用法会造成一个性能瓶颈。
若是子查询的条件中使用了其外层的表的字段,这种子查询就叫做相关子查询。相关子查询能够用IN、NOTIN、EXISTS、NOTEXISTS引入。
 
关于相关子查询,应该注意:
A、NOTIN、NOTEXISTS的相关子查询能够改用LEFTJOIN代替写法。好比:
 SELECTPUB_NAME  FROM  PUBLISHERS WHEREPUB_IDNOTIN
   (SELECTPUB_IDFROMTITLES  WHERETYPE='BUSINESS')
 能够改写成:
SELECTA.PUB_NAME  FROMPUBLISHERSA
LEFTJOINTITLESBON  B.TYPE='BUSINESS'AND  A.PUB_ID=B.PUB_ID
 
SELECTTITLEFROMTITLES
WHERENOTEXISTS(SELECTTITLE_IDFROMSALESWHERETITLE_ID=TITLES.TITLE_ID)
能够改写成:
SELECTTITLE 
FROMTITLESLEFTJOINSALESNSALES.TITLE_ID=TITLES.TITLE_ID
WHERESALES.TITLE_IDISNULL
 
B、若是保证子查询没有重复,IN、EXISTS的相关子查询能够用INNERJOIN代替。好比:
SELECTPUB_NAMEFROMPUBLISHERS  WHEREPUB_IDIN(SELECTPUB_IDFROMTITLESWHERETYPE='BUSINESS')
能够改写成:
SELECTDISTINCTA.PUB_NAME  
FROMPUBLISHERSA
INNERJOINTITLESBON  B.TYPE='BUSINESS'ANDA.PUB_ID=B.PUB_ID
 
C、不要用COUNT(*)的子查询判断是否存在记录,最好用LEFTJOIN或者EXISTS,好比有人写这样的语句:
SELECTJOB_DESCFROMJOBS
WHERE (SELECTCOUNT(*)FROMEMPLOYEEWHEREJOB_ID=JOBS.JOB_ID)=0
应该改为:
SELECTJOBS.JOB_DESCFROMJOBS
LEFTJOINEMPLOYEEONEMPLOYEE.JOB_ID=JOBS.JOB_ID
WHEREEMPLOYEE.EMP_IDISNULL
 
SELECTJOB_DESCFROMJOBS
WHERE (SELECTCOUNT(*)FROMEMPLOYEEWHEREJOB_ID=JOBS.JOB_ID)<>0
应该改为:
SELECTJOB_DESCFROMJOBS
WHEREEXISTS(SELECT1 FROMEMPLOYEEWHEREJOB_ID=JOBS.JOB_ID)
 

2.4.6.注意链接条件的用法

多表链接的链接条件对索引的选择有着重要的意义,因此咱们在写链接条件的时候须要特别的注意。
A、多表链接的时候,链接条件必须写全,宁肯重复,不要缺漏。
B、 链接条件尽可能使用汇集索引
C、 注意ON部分条件和WHERE部分条件的区别
 

2.4.7.查看执行计划及成本

养成良好的编码习惯,每写完一个sql语句,就查看执行计划及成本分析。在大表上尽量避免全表扫描及汇集索引扫描。
 

2.4.8.索引的使用及维护

在良好的数据库设计基础上,能有效地使用索引是SQL Server取得高性能的基础,SQL Server采用基于代价的优化模型,它对每个提交的有关表的查询,决定是否使用索引或用哪个索引。由于查询执行的大部分开销是磁盘I/O,使用索引提升性能的一个主要目标是避免全表扫描,由于全表扫描须要从磁盘上读表的每个数据页,若是有索引指向数据值,则查询只需读几回磁盘就能够了。因此若是创建了合理的索引,优化器就能利用索引加速数据的查询过程。可是,索引并不老是提升系统的性能,在增、删、改操做中索引的存在会增长必定的工做量,所以,在适当的地方增长适当的索引并从不合理的地方删除次优的索引,将有助于优化那些性能较差的SQL Server应用。
 
(1). 聚簇索引(clustered indexes)的使用
聚簇索引是一种对磁盘上实际数据从新组织以按指定的一个或多个列的值排序。因为聚簇索引的索引页面指针指向数据页面,因此使用聚簇索引查找数据几乎老是比使用非聚簇索引快。每张表只能建一个聚簇索引,而且建聚簇索引须要至少至关该表120%的附加空间,以存放该表的副本和索引中间页。创建聚簇索引的思想是:
一、大多数表都应该有聚簇索引或使用分区来下降对表尾页的竞争,在一个高事务的环境中,对最后一页的封锁严重影响系统的吞吐量。
二、在聚簇索引下,数据在物理上按顺序排在数据页上,重复值也排在一块儿,于是在那些包含范围检查(between、<、<=、>、>=)或使用group by或order by的查询时,一旦找到具备范围中第一个键值的行,具备后续索引值的行保证物理上毗连在一块儿而没必要进一步搜索,避免了大范围扫描,能够大大提升查询速度。
三、在一个频繁发生插入操做的表上创建聚簇索引时,不要建在具备单调上升值的列(如IDENTITY)上,不然会常常引发封锁冲突。
四、在聚簇索引中不要包含常常修改的列,由于码值修改后,数据行必须移动到新的位置。
五、选择聚簇索引应基于where子句和链接操做的类型。
 
聚簇索引的侯选列是:
一、主键列,该列在where子句中使用而且插入是随机的。
二、按范围存取的列,如pri_order > 100 and pri_order < 200。
三、在groupby或orderby中使用的列。
四、不常常修改的列。
五、在链接操做中使用的列
 
(2). 非聚簇索引(nonclustered indexes)的使用
SQL Server缺省状况下创建的索引是非聚簇索引,因为非聚簇索引不从新组织表中的数据,而是对每一行存储索引列值并用一个指针指向数据所在的页面。换句话说非聚簇索引具备在索引结构和数据自己之间的一个额外级。一个表若是没有聚簇索引时,可有250个非聚簇索引。每一个非聚簇索引提供访问数据的不一样排序顺序。在创建非聚簇索引时,要权衡索引对查询速度的加快与下降修改速度之间的利弊。另外,还要考虑这些问题:
一、索引须要使用多少空间。
二、合适的列是否稳定。
三、索引键是如何选择的,扫描效果是否更佳。
四、是否有许多重复值。
对更新频繁的表来讲,表上的非聚簇索引比聚簇索引和根本没有索引须要更多的额外开销。对移到新页的每一行而言,指向该数据的每一个非聚簇索引的页级行也必须更新,有时可能还须要索引页的分理。从一个页面删除数据的进程也会有相似的开销,另外,删除进程还必须把数据移到页面上部,以保证数据的连续性。因此,创建非聚簇索引要很是慎重。非聚簇索引常被用在如下状况:
一、某列经常使用于集合函数(如Sum,....)。
二、某列经常使用于join,order by,group by。
三、查寻出的数据不超过表中数据量的20%。
 
(3).  覆盖索引(covering indexes)的使用
覆盖索引是指那些索引项中包含查寻所须要的所有信息的非聚簇索引,这种索引之因此比较快也正是由于索引页中包含了查寻所必须的数据,不需去访问数据页。若是非聚簇索引中包含结果数据,那么它的查询速度将快于聚簇索引。 可是因为覆盖索引的索引项比较多,要占用比较大的空间。并且update操做会引发索引值改变。因此若是潜在的覆盖查询并不经常使用或不太关键,则覆盖索引的增长反而会下降性能。
 

2.4.9.索引的选择技术

索引的有无,创建方式的不一样将会致使不一样的查询效果,选择什么样的索引基于用户对数据的查询条件,这些条件体现于where从句和join表达式中。通常来讲创建索引的思路是:
 (1)、主键时常做为where子句的条件,应在表的主键列上创建聚簇索引,尤为当常常用它做为链接的时候。
 (2)、有大量重复值且常常有范围查询和排序、分组发生的列,或者很是频繁地被访问的列,可考虑创建聚簇索引。
 (3)、常常同时存取多列,且每列都含有重复值可考虑创建复合索引来覆盖一个或一组查询,并把查询引用最频繁的列做为前导列,若是可能尽可能使关键查询造成覆盖查询。
 (4)、若是知道索引键的全部值都是惟一的,那么确保把索引定义成惟一索引。
 (5)、在一个常常作插入操做的表上建索引时,使用fillfactor(填充因子)来减小页分裂,同时提升并发度下降死锁的发生。若是在只读表上建索引,则能够把fillfactor置为100。
 (6)、在选择索引键时,设法选择那些采用小数据类型的列做为键以使每一个索引页可以容纳尽量多的索引键和指针,经过这种方式,可以使一个查询必须遍历的索引页面降到最小。此外,尽量地使用整数为键值,由于它可以提供比任何数据类型都快的访问速度。
 

2.4.10.索引的维护

某些不合适的索引影响到SQL Server的性能,随着应用系统的运行,数据不断地发生变化,当数据变化达到某一个程度时将会影响到索引的使用。这时须要用户本身来维护索引。索引的维护包括:
一、重建索引
随着数据行的插入、删除和数据页的分裂,有些索引页可能只包含几页数据,另外应用在执行大块I/O的时候,重建非聚簇索引能够下降分片,维护大块I/O的效率。重建索引其实是从新组织B-树空间。在下面状况下须要重建索引:
 (1)、数据和使用模式大幅度变化。
 (2)、排序的顺序发生改变。
 (3)、要进行大量插入操做或已经完成。
 (4)、使用大块I/O的查询的磁盘读次数比预料的要多。
 (5)、因为大量数据修改,使得数据页和索引页没有充分使用而致使空间的使用超出估算。
 (6)、dbcc检查出索引有问题。
当重建聚簇索引时,这张表的全部非聚簇索引将被重建。
二、索引统计信息的更新
当在一个包含数据的表上建立索引的时候,SQL Server会建立分布数据页来存放有关索引的两种统计信息:分布表和密度表。优化器利用这个页来判断该索引对某个特定查询是否有用。但这个统计信息并不动态地从新计算。这意味着,当表的数据改变以后,统计信息有多是过期的,从而影响优化器追求最有工做的目标。所以,在下面状况下应该运行update statistics命令:
 (1)、数据行的插入和删除修改了数据的分布。
 (2)、对用truncate table删除数据的表上增长数据行。
 (3)、修改索引列的值。
 

相关文章
相关标签/搜索