1 Oracle数据库性能优化方案
1.1 ORACLE SQL执行流程图
1.2 SQL语句优化技术分析
1.2.1 操作符优化
IN 操作符
用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格。
但是用IN的SQL性能总是比较低的,从ORACLE执行的步骤来分析用IN的SQL与不用IN的SQL有以下区别:
ORACLE试图将其转换成多个表的连接,如果转换不成功则先执行IN里面的子查询,再查询外层的表记录,如果转换成功则直接采用多个表的连接方式查询。由此可见用IN的SQL至少多了一个转换的过程。一般的SQL都可以转换成功,但对于含有分组统计等方面的SQL就不能转换了。
推荐方案:在业务密集的SQL当中尽量不采用IN操作符。
NOT IN操作符
此操作是强列推荐不使用的,因为它不能应用表的索引。
推荐方案:用NOT EXISTS 或(外连接+判断为空)方案代替
<> 操作符(不等于)
不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。
推荐方案:用其它相同功能的操作运算代替,如
a<>0 改为 a>0 or a<0
a<>’’ 改为 a>’’
IS NULL 或IS NOT NULL操作(判断字段是否为空)
判断字段是否为空一般是不会应用索引的,因为B树索引是不索引空值的。
推荐方案:
用其它相同功能的操作运算代替,如
ais not null 改为 a>0 或a>’’等。
不允许字段为空,而用一个缺省值代替空值,如业扩申请中状态字段不允许为空,缺省为申请。
建立位图索引(有分区的表不能建,位图索引比较难控制,如字段值太多索引会使性能下降,多人更新操作会增加数据块锁的现象)
> 及 < 操作符(大于或小于操作符)
大于或小于操作符一般情况下是不用调整的,因为它有索引就会采用索引查找,但有的情况下可以对它进行优化,如一个表有100万记录,一个数值型字段A,30万记录的A=0,30万记录的A=1,39万记录的A=2,1万记录的A=3。那么执行A>2与A>=3的效果就有很大的区别了,因为A>2时ORACLE会先找出为2的记录索引再进行比较,而A>=3时ORACLE则直接找到=3的记录索引。
LIKE操作符
LIKE操作符可以应用通配符查询,里面的通配符组合可能达到几乎是任意的查询,但是如果用得不好则会产生性能上的问题,如LIKE ‘%5400%’ 这种查询不会引用索引,而LIKE ‘X5400%’则会引用范围索引。一个实际例子:用YW_YHJBQK表中营业编号后面的户标识号可来查询营业编号 YY_BH LIKE ‘%5400%’ 这个条件会产生全表扫描,如果改成YY_BH LIKE ’X5400%’ OR YY_BH LIKE ’B5400%’ 则会利用YY_BH的索引进行两个范围的查询,性能肯定大大提高。
UNION操作符
UNION在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复的记录再返回结果。实际大部分应用中是不会产生重复的记录,最常见的是过程表与历史表UNION。如:
select * from gc_dfys
union
select * from ls_jg_dfys
这个SQL在运行时先取出两个表的结果,再用排序空间进行排序删除重复的记录,最后返回结果集,如果表数据量大的话可能会导致用磁盘进行排序。
推荐方案:采用UNIONALL操作符替代UNION,因为UNION ALL操作只是简单的将两个结果合并后就返回。
select * from gc_dfys
union all
select * from ls_jg_dfys
1.2.2 SQL书写的影响
同一功能同一性能不同写法SQL的影响
如一个SQL在A程序员写的为
Select* from zl_yhjbqk
B程序员写的为
Select* from dlyx.zl_yhjbqk(带表所有者的前缀)
C程序员写的为
Select* from DLYX.ZLYHJBQK(大写表名)
D程序员写的为
Select* from DLYX.ZLYHJBQK(中间多了空格)
以上四个SQL在ORACLE分析整理之后产生的结果及执行的时间是一样的,但是从ORACLE共享内存SGA的原理,可以得出ORACLE对每个SQL 都会对其进行一次分析,并且占用共享内存,如果将SQL的字符串及格式写得完全相同则ORACLE只会分析一次,共享内存也只会留下一次的分析结果,这不仅可以减少分析SQL的时间,而且可以减少共享内存重复的信息,ORACLE也可以准确统计SQL的执行频率。
WHERE后面的条件顺序影响
WHERE子句后面的条件顺序对大数据量表的查询会产生直接的影响,如
Select * from zl_yhjbqk where dy_dj ='1KV以下' and xh_bz=1
Select * from zl_yhjbqk wherexh_bz=1 and dy_dj = '1KV以下'
以上两个SQL中dy_dj(电压等级)及xh_bz(销户标志)两个字段都没进行索引,所以执行的时候都是全表扫描,第一条SQL的dy_dj = '1KV以下'条件在记录集内比率为99%,而xh_bz=1的比率只为0.5%,在进行第一条SQL的时候99%条记录都进行dy_dj及xh_bz的比较,而在进行第二条SQL的时候0.5%条记录都进行dy_dj及xh_bz的比较,以此可以得出第二条SQL的CPU占用率明显比第一条低。
查询表顺序的影响
在FROM后面的表中的列表顺序会对SQL执行性能影响,在没有索引及ORACLE没有对表进行统计分析的情况下ORACLE会按表出现的顺序进行链接,由此因为表的顺序不对会产生十分耗服务器资源的数据交叉。(注:如果对表进行了统计分析,ORACLE会自动先进小表的链接,再进行大表的链接)
SQL语句索引的利用
对操作符的优化(见上节)
对条件字段的一些优化
采用函数处理的字段不能利用索引,如:
substr(hbs_bh,1,4)=’5400’,优化处理:hbs_bh like ‘5400%’
trunc(sk_rq)=trunc(sysdate), 优化处理:
sk_rq>=trunc(sysdate)and sk_rq<trunc(sysdate+1)
进行了显式或隐式的运算的字段不能进行索引,如:
ss_df+20>50,优化处理:ss_df>30
‘X’||hbs_bh>’X5400021452’,优化处理:hbs_bh>’5400021542’
sk_rq+5=sysdate,优化处理:sk_rq=sysdate-5
hbs_bh=5401002554,优化处理:hbs_bh=’ 5401002554’,注:此条件对hbs_bh 进行隐式的to_number转换,因为hbs_bh字段是字符型。
条件内包括了多个本表的字段运算时不能进行索引,如:
ys_df>cx_df,无法进行优化
qc_bh||kh_bh=’5400250000’,优化处理:qc_bh=’5400’ and kh_bh=’250000’
应用ORACLE的HINT(提示)处理
提示处理是在ORACLE产生的SQL分析执行路径不满意的情况下要用到的。它可以对SQL进行以下方面的提示
目标方面的提示:
COST(按成本优化)
RULE(按规则优化)
CHOOSE(缺省)(ORACLE自动选择成本或规则进行优化)
ALL_ROWS(所有的行尽快返回)
FIRST_ROWS(第一行数据尽快返回)
执行方法的提示:
USE_NL(使用NESTEDLOOPS方式联合)
USE_MERGE(使用MERGE JOIN方式联合)
USE_HASH(使用HASH JOIN方式联合)
索引提示:
INDEX(TABLE INDEX)(使用提示的表索引进行查询)
其它高级提示(如并行处理等等)
ORACLE的提示功能是比较强的功能,也是比较复杂的应用,并且提示只是给ORACLE执行的一个建议,有时如果出于成本方面的考虑ORACLE也可能不会按提示进行。根据实践应用,一般不建议开发人员应用ORACLE提示,因为各个数据库及服务器性能情况不一样,很可能一个地方性能提升了,但另一个地方却下降了,ORACLE在SQL执行分析方面已经比较成熟,如果分析执行的路径不对首先应在数据库结构(主要是索引)、服务器当前性能(共享内存、磁盘文件碎片)、数据库对象(表、索引)统计信息是否正确这几方面分析。
1.3 视图在数据库中的应用分析
视图技术现在几乎所有的关系型数据库都支持,其应用也十分广泛。
采用视图的优点
1、 让数据库结构实现逻辑上的可扩充性:当数据库系统的物理信息(主要指表结构、表数据)已经完成后,如果由于新的业务要求导致表数据的不够,这时就可以采用视图技术进行扩充,通过视图中强大的SQL来完成功能。
2、 软件开发及数据查询处理方便:采用视图可以简化数据库系统的内部结构及其关系图,因为物理表很多时候是以数据库范式原则分析建立的,尤其在数据冗余处理方面与实际业务会产生较大的分歧,采用视图可以将多个表通过SQL联合起来,产生与实际业务相适应的数据结果,这极大方便了软件开发及数据查询,利用视图的SQL写起来也比较简单。
视图按功能的分类分析
1、 业务视图
业务视图在数据库应用中比较多,往往是实现返回一个具体的业务结果功能,里面的复杂程度随着业务的复杂而提高,这种视图往往只用在软件中的某个固定模块,所以在建立这种视图应考虑产生的业务数据信息是否有用和完整,不用的数据尽量不返回,如果须从其它表产生的数据应考虑在视图中产生,而不要在实现软件开发时的SQL中通过表链接产生。
2、 基本视图
基本视图是指一般是指在软件开发中多个模块都可能用到的视图,这种视图一般比较简单,不会超过四个表的链接,处理基本视图时应做详细的分析,使它的重用性达到最大,切不能因为当前的SQL处理就随便建立一个基本视图。应用了基本视图内的表不应该在外面的SQL中重复出现,否则可能导致ORACLE重复处理的现象。
视图建立备注:
视图中如果出现UNION操作的话在数据不重复的情况下应改为UNION ALL以提高速度。
功能大致相同的视图应在不影响性能及数据的前提下分析是否可以合并成一个视图,这有助于软件模块化开发及调试。
非软件用和不常用的视图应使用完后可以保存SQL成文件再进行删除,以免给其它人员产生影响。
1.4 数据库对象统计分析技术应用
ORACLE在执行SQL时如果使用成本方式分析则所有的成本分析信息来源依靠于系统的统计分析表(DBA_TABLES、DBA_INDEXES、DBA_TAB_COLUMNS)数据,如果说统计分析的数据是不准确的,那可能会使ORACLE分析出来的路径执行性能极差,所以统计分析数据是影响ORACLE性能极重要的信息。
统计分析主要包括产生表及索引的统计信息
表的统计信息主要包括表的行数,每行的平均长度(字节),空闲块,统计时间等信息
索引的统计信息主要包括行数、层数、叶块数、统计时间等信息。
另外ORACLE还可以统计列及数据不对称信息,9i还可以统计系统信息(CPU,I/O)
ORACLE执行成本分析时首先取出所应用表及索引的统计数据进行分析,其中数据行数是一个重要的参数,因为ORACLE在分析表大小时行数为主要参数,如果进行两个表联合时,ORACLE会通过分析表的大小,决定应用小表进行全表查询,而大表执行联合查询,这种性能明显高于先大表进行全表扫描。索引的统计信息对分析也产生比较大的影响,如ORACLE通过统计可以分析产生多个索引的优先级及索引的实用性来确定最优的索引策略。ORACLE还可以统计列及数据对称信息以产生更精确的分析。如一个表有A字段的索引,其中A共有两种值1和0,共10000条记录,为0的记录有10条,为1的记录有9990条,这时如果没有进行列数据不对称的统计信息,那么ORACLE对A=0及A=1条件查询都会进行索引,但实际应用对A=0的索引性能得到了很大的提高,而A=1的索引反而使性能下降。所以说索引特征值分析信息对应用索引产生重大影响,精确的信息使ORACLE不会使用不应该用的索引。
实际分析
zl_cbqc和zl_yhjbqk都没有建立统计信息,执行如下两个SQL ORACLE将产生不同的执行计划。
1 select * from dlyx.zl_cbqc b, dlyx.zl_yhjbqk a where a.qc_bh=b.qc_bh
执行计划:
SELECT STATEMENT, GOAL = CHOOSE
NESTEDLOOPS
TABLEACCESS FULL DLYX ZL_YHJBQK
TABLE ACCESS BY INDEX ROWID DLYX ZL_CBQC
INDEX UNIQUE SCAN DLYX 抄表区册主键
2 select * from dlyx.zl_yhjbqk a,dlyx.zl_cbqc b where a.qc_bh=b.qc_bh
执行计划:
SELECT STATEMENT, GOAL = CHOOSE
NESTED LOOPS
TABLEACCESS FULL DLYX ZL_CBQC
TABLEACCESS BY INDEX ROWID DLYX ZL_YHJBQK
INDEX RANGE SCAN DLYX 区册索引
在对两个表进行了统计分析后
3 select * fromdlyx.zl_yhjbqk a,dlyx.zl_cbqc b where a.qc_bh=b.qc_bh
执行计划:
SELECT STATEMENT, GOAL = CHOOSE 159 72853 9689449
HASHJOIN 159 72853 9689449
TABLE ACCESS FULL DLYX ZL_CBQC 1 426 19596
TABLE ACCESS FULL DLYX ZL_YHJBQK 157 72853 6338211
4 select * from dlyx.zl_cbqcb,dlyx.zl_yhjbqk a where a.qc_bh=b.qc_bh
执行计划:
SELECT STATEMENT, GOAL = CHOOSE 159 72853 9689449
HASHJOIN 159 72853 9689449
TABLEACCESS FULL DLYX ZL_CBQC 1 426 19596
TABLE ACCESS FULL DLYX ZL_YHJBQK 157 72853 6338211
从以上测试可以明显看出ORACLE的分析结果
第1条SQL与第2条SQL在没有统计分析的信息下进行,ORACLE无法进行判断,只能以规则方法进行分析,根据表的出现先后顺序有明显关系。
第3条SQL与第4条SQL在有统计分析的信息下进行,ORACLE分析与表的出现先后顺序无关,因为它已经知道了表的数据量并且已经确定返回的数据量基本上是两个表所有的数据,所以对表两个表进行了HASH JOIN (同时取出两个表的数据然后在内存中进行联合产生返回结果)。
相关技术
用analyze语句产生分析数据
分析表:analyze table zl_yhjbqk estimatestatistics sample 20 percent
分析索引:analyze index用户资料表主键compute statistics
分析列:analyze table zl_yhjbqk compute statistics forcolumns hbs_bh
分析索引列:analyze table zl_yhjbqk compute statistics forall indexed columns
用sys.dbms_utility包分析数据
分析数据库(包括所有的用户对象和系统对象):analyze_database
分析用户所有的对象(包括用户方案内的表、索引、簇):analyze_schema
用sys.dbms_stats包处理分析数据
分析数据库(包括所有的用户对象和系统对象):gather_database_stats
分析用户所有的对象(包括表、索引、簇):gather_schema_stats
分析表:gather_table_stats
分析索引:gather_index_stats
删除数据库统计信息:delete_database_stats
删除用户方案统计信息:delete_schema_stats
删除表统计信息:delete_table_stats
删除索引统计信息:delete_index_stats
删除列统计信息:delete_column_stats
设置表统计信息:set_table_stats
设置索引统计信息:set_index_stats
设置列统计信息:set_column_stats
ORACLE推荐用户采用sys.dbms_stats包体进行分析,因为在ORACLE9i及其以上的版本全面扩充的此包体的功能。sys.dbms_utility包体进行分析时会对所有的信息全部分析一遍,时间比较长,而在9i中sys.dbms_stats可以利用表修改监控技术来判断需统计分析的表进行,节省了用户的分析资源。
备注:
ORACLE在得到了表的统计分析数据后才会进行成本分析,否则采用规则分析。
并不是所有的统计数据都会对ORACLE分析产生影响,有些统计数据ORACLE并不处理,只是提供给用户一个参考信息,也可能在ORACLE以后的版本中利用这些信息进行分析。
分析表的登录用户必须对表拥有访问权限或具有DBA或Analyze any权限
1.5 索引在数据库中的应用分析
索引是提高数据查询最有效的方法,也是最难全面掌握的技术,因为正确的索引可能使效率提高10000倍,而无效的索引可能是浪费了数据库空间,甚至大大降低查询性能。
索引的管理成本
1、 存储索引的磁盘空间
2、 执行数据修改操作(INSERT、UPDATE、DELETE)产生的索引维护
3、 在数据处理时回需额外的回退空间。
实际数据修改测试:
一个表有字段A、B、C,同时进行插入10000行记录测试
在没有建索引时平均完成时间是2.9秒
在对A字段建索引后平均完成时间是6.7秒
在对A字段和B字段建索引后平均完成时间是10.3秒
在对A字段、B字段和C字段都建索引后平均完成时间是11.7秒
从以上测试结果可以明显看出索引对数据修改产生的影响
索引按存储方法分类
B*树索引
B*树索引是最常用的索引,其存储结构类似书的索引结构,有分支和叶两种类型的存储数据块,分支块相当于书的大目录,叶块相当于索引到的具体的书页。一般索引及唯一约束索引都使用B*树索引。
位图索引
位图索引储存主要用来节省空间,减少ORACLE对数据块的访问,它采用位图偏移方式来与表的行ID号对应,采用位图索引一般是重复值太多的表字段。位图索引在实际密集型OLTP(数据事务处理)中用得比较少,因为OLTP会对表进行大量的删除、修改、新建操作,ORACLE每次进行操作都会对要操作的数据块加锁,所以多人操作很容易产生数据块锁等待甚至死锁现象。在OLAP(数据分析处理)中应用位图有优势,因为OLAP中大部分是对数据库的查询操作,而且一般采用数据仓库技术,所以大量数据采用位图索引节省空间比较明显。
索引按功能分类
唯一索引
唯一索引有两个作用,一个是数据约束,一个是数据索引,其中数据约束主要用来保证数据的完整性,唯一索引产生的索引记录中每一条记录都对应一个唯一的ROWID。
主关键字索引
主关键字索引产生的索引同唯一索引,只不过它是在数据库建立主关键字时系统自动建立的。
一般索引
一般索引不产生数据约束作用,其功能主要是对字段建立索引表,以提高数据查询速度。
索引按索引对象分类
单列索引(表单个字段的索引)
多列索引(表多个字段的索引)
函数索引(对字段进行函数运算的索引)
建立函数索引的方法:
createindex 收费日期索引 onGC_DFSS(trunc(sk_rq))
createindex 完全客户编号索引 onyhzl(qc_bh||kh_bh)
在对函数进行了索引后,如果当前会话要引用应设置当前会话的query_rewrite_enabled为TRUE。
altersession set query_rewrite_enabled=true
注:如果对用户函数进行索引的话,那用户函数应加上 deterministic参数,意思是函数在输入值固定的情况下返回值也固定。例:
create or replacefunction trunc_add(input_datedate)return date deterministic
as
begin
return trunc(input_date+1);
end trunc_add;
应用索引的扫描分类
INDEX UNIQUE SCAN(按索引唯一值扫描)
select * from zl_yhjbqk where hbs_bh='5420016000'
INDEX RANGE SCAN(按索引值范围扫描)
select * from zl_yhjbqk where hbs_bh>'5420016000'
select * from zl_yhjbqk where qc_bh>'7001'
INDEX FAST FULL SCAN(按索引值快速全部扫描)
select hbs_bh from zl_yhjbqkorder by hbs_bh
select count(*) from zl_yhjbqk
select qc_bh from zl_yhjbqkgroup by qc_bh
什么情况下应该建立索引
表的主关键字
自动建立唯一索引
如zl_yhjbqk(用户基本情况)中的hbs_bh(户标识编号)
表的字段唯一约束
ORACLE利用索引来保证数据的完整性
如lc_hj(流程环节)中的lc_bh+hj_sx(流程编号+环节顺序)
直接条件查询的字段
在SQL中用于条件约束的字段
如zl_yhjbqk(用户基本情况)中的qc_bh(区册编号)
select * from zl_yhjbqk where qc_bh=’7001’
查询中与其它表关联的字段
字段常常建立了外键关系
如zl_ydcf(用电成份)中的jldb_bh(计量点表编号)
select * fromzl_ydcf a,zl_yhdb b where a.jldb_bh=b.jldb_bh and b.jldb_bh=’540100214511’
查询中排序的字段
排序的字段如果通过索引去访问那将大大提高排序速度
select * from zl_yhjbqk order by qc_bh(建立qc_bh索引)
select * from zl_yhjbqk where qc_bh='7001' order by cb_sx(建立qc_bh+cb_sx索引,注:只是一个索引,其中包括qc_bh和cb_sx字段)
查询中统计或分组统计的字段
select max(hbs_bh) from zl_yhjbqk
select qc_bh,count(*) from zl_yhjbqkgroup by qc_bh
什么情况下应不建或少建索引
表记录太少
如果一个表只有5条记录,采用索引去访问记录的话,那首先需访问索引表,再通过索引表访问数据表,一般索引表与数据表不在同一个数据块,这种情况下ORACLE至少要往返读取数据块两次。而不用索引的情况下ORACLE会将所有的数据一次读出,处理速度显然会比用索引快。
如表zl_sybm(使用部门)一般只有几条记录,除了主关键字外对任何一个字段建索引都不会产生性能优化,实际上如果对这个表进行了统计分析后ORACLE也不会用你建的索引,而是自动执行全表访问。如:
select* from zl_sybm where sydw_bh='5401'(对sydw_bh建立索引不会产生性能优化)
经常插入、删除、修改的表
对一些经常处理的业务表应在查询允许的情况下尽量减少索引,如zl_yhbm,gc_dfss,gc_dfys,gc_fpdy等业务表。
数据重复且分布平均的表字段
假如一个表有10万行记录,有一个字段A只有T和F两种值,且每个值的分布概率大约为50%,那么对这种表A字段建索引一般不会提高数据库的查询速度。
经常和主字段一块查询但主字段索引值比较多的表字段
如gc_dfss(电费实收)表经常按收费序号、户标识编号、抄表日期、电费发生年月、操作标志来具体查询某一笔收款的情况,如果将所有的字段都建在一个索引里那将会增加数据的修改、插入、删除时间,从实际上分析一笔收款如果按收费序号索引就已经将记录减少到只有几条,如果再按后面的几个字段索引查询将对性能不产生太大的影响。
如何只通过索引返回结果
一个索引一般包括单个或多个字段,如果能不访问表直接应用索引就返回结果那将大大提高数据库查询的性能。对比以下三个SQL,其中对表zl_yhjbqk的hbs_bh和qc_bh字段建立了索引:
1 selecthbs_bh,qc_bh,xh_bz from zl_yhjbqk where qc_bh=’7001’
执行路径:
SELECT STATEMENT,GOAL = CHOOSE 11 265 5565
TABLE ACCESS BY INDEX ROWID DLYX ZL_YHJBQK 11 265 5565
INDEX RANGE SCAN DLYX 区册索引 1 265
平均执行时间(0.078秒)
2 select hbs_bh,qc_bh from zl_yhjbqk whereqc_bh=’7001’
执行路径:
SELECT STATEMENT,GOAL = CHOOSE 11 265 3710
TABLE ACCESS BY INDEX ROWID DLYX ZL_YHJBQK 11 265 3710
INDEX RANGE SCAN DLYX 区册索引 1 265
平均执行时间(0.078秒)
3 select qc_bh from zl_yhjbqk where qc_bh=’7001’
执行路径:
SELECT STATEMENT,GOAL = CHOOSE 1 265 1060
INDEX RANGE SCAN DLYX 区册索引 1 265 1060
平均执行时间(0.062秒)
从执行结果可以看出第三条SQL的效率最高。执行路径可以看出第1、2条SQL都多执行了TABLE ACCESS BY INDEX ROWID(通过ROWID访问表) 这个步骤,因为返回的结果列中包括当前使用索引(qc_bh)中未索引的列(hbs_bh,xh_bz),而第3条SQL直接通过QC_BH返回了结果,这就是通过索引直接返回结果的方法。
如何重建索引
alter index 表电量结果表主键 rebuild
如何快速新建大数据量表的索引
如果一个表的记录达到100万以上的话,要对其中一个字段建索引可能要花很长的时间,甚至导致服务器数据库死机,因为在建索引的时候ORACLE要将索引字段所有的内容取出并进行全面排序,数据量大的话可能导致服务器排序内存不足而引用磁盘交换空间进行,这将严重影响服务器数据库的工作。解决方法是增大数据库启动初始化中的排序内存参数,如果要进行大量的索引修改可以设置10M以上的排序内存(ORACLE缺省大小为64K),在索引建立完成后应将参数修改回来,因为在实际OLTP数据库应用中一般不会用到这么大的排序内存。
1.6 主关键字建立分析
简单原则
有一个字段可以作关键字则应尽可能不用多个字段
主关键字段应尽量采用数值型或长度小的字符型,不宜采取日期型或长度大的字符型
如果要采用多个字段做主关键字,那将给软件开发中数据处理增加一定的工作量,如查询修改或删除的时候就要求确定的字段条件有两个以上,特别是在修改或删除表的时候会增加软件的BUG。
一般情况下多个字段的占用空间肯定比单个字段大,在进行主关键查询时包括CPU处理及磁盘I/O操作都会增加服务器的负荷,在百万级以上的数据量时表现尤为明显。
有一个这样的测试
一个表100万行记录,三个字段,A(数值型),B(字符型10位),C日期型
检索1000行记录
以A字段做条件,最大时间为1.344秒,最小时间为1.156秒
以B字段做条件,最大时间为1.391秒,最小时间为1.172秒
以C字段做条件,最大时间为1.843秒,最小时间为1.532秒
采用日期型数据做主关键字不会对性能上带来太大的影响,但是日期型的主关键字在软件开发上会带来很大的不便,如:
对日期不能直接字符查询,需将字符转换为日期型数据再查询,日期型数据可以存时间也可以不存时间,如果某字段不要求存时间则在开发中还要在时间数据处理上下功夫,因为有时间的数据可能会对查询产生不正确的结果。
另外有时采用日期时间作为主关键字是一种现实理想上的推论,随着业务数据量的增加业务功能的扩充及操作人员增加会对此关键字提出挑战,并且时间会因为数据库服务器的时间而影响,很可能在服务器时间出错或因为与实际时间相差太大时修改的时候导致数据库数据紊乱。
持久性原则
一个主关键字应是持久有效的,具体的说就是主关键字能确定当前及将来一段时间内的业务需求(可以预见的或可能出现的)的业务最小原子,如果因为以后的业务功能扩充导致主关键字失效或者是要强制约定记录数据内容才能维持的话,那将带来非常严重的后果。最容易出现这种错误的表就是有多个字段的主关键字并且与业务相当紧密,设计分析时只考虑了当前分析的业务情况,认为这几个字段做主关键字足够了。
可充当其它表外键关联原则
主关键字应该是经常查询的字段,并且是当前表与其它表关联最多的字段
经常查询的字段按数据库性能设计来分析应该在条件字段上建立索引,主关键产生的索引是所有索引类型最快的一种,因此应在查询的时候尽可能的用到主关键字索引。
有意义原则
在实际的简单业务表中,主关键字应尽量有实际意义,而在系统的基础核心表及数据量大的业务表中主关键字应在速度性能方面考虑多一些。主关键字有意义主要是为了在软件开发及数据库查询调试时更方面,业务更容易理解,数据库与实际业务更清晰。