您好,欢迎访问一九零五行业门户网

数据库设计及优化

数据库设计 ,可以使数据库通过健壮的数据库结构高效并且健康的进行工作。 数据库设计原则: 1、熟悉需求。2、开发符合规范的数据库。3、审核数据库设计。 数据库规范 1、命名规范: 1、表名的单数和复数形式要统一。2、对于字段,如果主键是数字类型的,可
数据库设计,可以使数据库通过健壮的数据库结构高效并且健康的进行工作。
数据库设计原则:1、熟悉需求。2、开发符合规范的数据库。3、审核数据库设计。
数据库规范
1、命名规范:1、表名的单数和复数形式要统一。2、对于字段,如果主键是数字类型的,可以考虑使用_n结尾,例如userid_n;如果是字符类型_c结尾username_c;3、如果一个单词经常出现,比如user,则可以考虑以_u结尾,例如,userid可以表示成id_u,username表示为name_u。4、如果某一列是日期类型,则使用d_开头,起到强调的作用,例如:d_createdatetime。
2、明确现实中实体与数据表的关系。3、一张数据表不能既没有主键也没有外键。4、表要符合基本表的特征。
5、必须满足第一第二范式,尽量满足第三范式。6、比较简洁的e-r图。7、符合完整性约束。
基本表的特征:1、原子性,就是基本表中的字段是不可在分解的。2、原始性,基本表中的记录是袁术数据的记录。3、演绎性,由基本表和关系表中的数据可以派生出任何想要的数据。4、稳定性、基本表中的结构是相对稳定的,表中的记录需要长期保存。
第一范式:是对属性的原子性约束,要求属性具有原子性,不可再分。第二范式:记录的唯一性约束,要求记录有唯一标识,即实体的唯一性。第三范式:对字段冗余的约束,即任何字段不能由其他字段派生出来,要求字段没有冗余,一个表中的字段除了和主键有关外,这些字段他们之间不能有关系,也就是说这个表中的字段只能和主键相关,他们之间没有关系。
数据库设计技巧:1、在符合系统需求的前提下,表的个数越少越好,一张表中组合主键字段数越少越好,一个表中的字段越少越好。2、检查各种变化字段。3、避免使用保留字。4、数据库设计的时候多使用删除标记字段。5、避免使用触发器。6、如果发现在重复输入数据,就需要创建新的表和新的关系。7、熟练使用数据库设计工具。8、创建e-r图和数据字典。9、每个表都应该有三个有用的字段:修改记录时间、修改人、修改后的版本。10、对于地址和电话采用多个字段。
sql查询优化
劣质sql判断条件:1、运行时间超长。2、引发严重的等待事件。3、不能满足压力测试。4、消耗大量系统资源。
索引是对数据库表中一列或者多列的值进行排序的一种结构。使用索引可以快速访问数据库表中的特定信息。
索引存在的问题:1、索引占用表空间,创建太多索引可能会造成索引冗余。2、索引影响dml性能。
索引使用的条件:1、一个字段里包含大量的值。2、一个字段包含多个空值。3、多个字段经常出现在where查询中。4、表非常大并且查询返回数据量低于总数据的20%。
创建索引的语法:
create index 索引名 on 表名(列名)tablespace 表空间名
例如:
select identity_l from depositor where identity_l between109000 and 110000 --未使用索引,查询值在109000到110000之间的值create index dptor_index on depositor(identity_l)tablespace demo --使用索引查询。
索引类型,按列值是否唯一分为:非唯一索引和唯一索引。按索引列的个数分为单列索引和复合索引。按照索引的物理组织方式分为:b树索引、反向键索引、基于函数的索引、位图索引。
创建复合索引时,表指定的第一个列为主导列。
select *from depositor t where identity_l>100000 and act>=500 --未使用索引create index op_idact_index on depositor(identity_l,act) tablespace demo --使用复合索引
使用复合索引的情况:1、当sql语句的where自居中用到复合索引的主导列时。2、当某几个列在sql语句的where子句中经常通过and操作符联合在一起使用,并且这些列合在一起是选择性比各自单个列的选择性要好时。
3、当有几个查询语句都是查询相同的几个列值时。
反向键索引就是将当前列中的值反转后生成的索引。
创建反向键索引的语法:create index索引名 on表名(列名) reverse tablespace表空间;
基于函数的索引,基于一个或者多个列上的函数或表达式创建的索引。
注意:表达式中不能包含聚合函数(sum、count、avg、min、max)。
基于函数索引的语法:create index索引名 on表名(函数(列名)) tablespace表空间;
select lower(firstname) from depositor t; --没有使用基于函数索引的情况。create index firstname_lower on depositor(lower(firstname)) tablespace prd;
使用基于函数的索引的情况:1、一个表中的字段经常被函数所调用,那么这个字段就可以使用基于函数的索引。
位图索引:
值\行
1
2
3
4
张三
1
0
0
1
李四
0
0
0
1
王五
0
1
0
1
小明
1
0
1
1
整个表就是针对一个列建立出来的位图索引,这个表中的列(1,2,3,4)表示的是对应的索引列的第几行。行代表的是当前行,当前被索引列的值。比如图中第一列1,张三第一列的值是1,表示在当前被索引的第一行的位置中张三这个值时存在的,并且是1。
使用位图索引的情况:主要是处理数据的聚合关系的,用于一个重复数据很多的情况。
位图索引的语法:
create bitmap index 索引名 on 表名(列名) tablespace 表空间; select count(*) from depositor t where firstname=’luke’;create bitmap index fn_bitmap on depositor(firstname) tablespace prd;
表分区:有利于管理非常大的表和索引。当表里面的内容或者整个表的结构非常庞大的时候,就考虑表分区。
表分区的优点:1、提高数据的可用性,当某个分区损坏不会影响整个表结构。2、减少管理负担。3、改善语句性能。
表分区的分区方式:1、区间分区。2、散列分区。3、列表分区。4、组合分区。
区间分区:往往根据一个列值的范围来划分,开发中常常使用日期字段来划分。
语法:
partitionby range(列名) --range表示分区的方式( partition 分区表名 values less than (值) tablespace 表空间)
示例:part_1这个分区保存早于(不包括)2008年12月31日的数据
create table drawlist( dt_draw date not null)partitionby range(dt_draw)( partition part_1 values lessthan(to_date(‘1/1/2009’,’dd/mm/yyyy’)) tablespace demo, partition part_1 values lessthan(to_date(‘1/1/2011’,’dd/mm/yyyy’)) tablespace demo, partition part_1 values lessthan(to_date(maxvalue) tablespace demo)insert into drawlist values(to_date(‘31/12/2008’,’dd/mm/yyyy’));insert into drawlist values(to_date(‘01/01/2009’,’dd/mm/yyyy’));insert into drawlist values(to_date(‘06/06/2009’,’dd/mm/yyyy’));insert into drawlist values(to_date(‘31/12/2010’,’dd/mm/yyyy’));insert into drawlist values(to_date(‘01/01/2011’,’dd/mm/yyyy’));insert into drawlist values(to_date(‘04/05/2011’,’dd/mm/yyyy’)); select *from drawlist partition(part_2); 显示结果:2009-1-1;2009-6-6;2010-12-31;
散列分区:会对分区键应用一个散列函数,以此确定数据应当放在n个分区中的哪个分区中。直到散列算法是将数据随机均匀的分布。为了使数据分布的更均匀,分区表的数目建议为2的幂,也就是1、4、8、16……
散列分区语法:
partition by hash(列)(partition 分区表名 tablespace表空间)createtable hash_table (hash_no integer not null )partitionby hash(hash_no)( partition part_1 tablespace demo, partition part_2 tablespace demo, partition part_3 tablespace demo, partition part_4 tablespace demo,)
对其随机插入500条测试语句
selectcount(*) from hash_table partition(part_1)selectcount(*) from hash_table partition(part_2)selectcount(*) from hash_table partition(part_3)selectcount(*) from hash_table partition(part_4)
输出结果基本均匀分布,分别为:123、116、121、140。
列表分区:可以将数据按照列的值分类。列表分区语法如下:
partitionby list(列)( partition 分区表名values(指定值1,指定值2……))
示例:根据用户所在地区将用户存储在不同分区中
create table area( code integernot null )partition by list(code)( partitionpart_1 values(102200,102202,102203), partitionpart_2 values(164300,164302,164303))tablespace demo;insert into area values(102200);insert into area values(102203);insert into area values(164300);insert into area values(164303);select * from area partition(part_1)select * from area partition(part_2)
查询结果:在part_1分区中数据为102200、102202;part_2分区中数据位164300、164303;
组合分区:就是区间分区与散列分区或者区间分区与列表分区的组合。
区间-散列组合分区表语法:首先按照列1的值进行区间分区,然后按照列2散列分区。
partition by range(列1) subpartition by hash(列2)( partition分区名 values less than (值) tablespace表空间,)
区间-列表组合分区表语法:先按照列1的值进行区间分区,然后按照列2指定值进行列表分区
partition by range(列1) subpartition by list(列2)( partition 分区名 values less than (值) tablespace 表空间 ( subpartition 子分区名 values(列表指定值1……) tablespace 表空间 ))
组合分区示例:
select *from range_list partition(part_2);
返回值为:dt_date 2009-1-1,2010-12-31,2010-11-21;code 102200,164300,164300;
select *from range_list subpartition(part2_list);
结果为:dt_date 2009-1-1;code102200;
分区维护:增加分区、删除分区、截断分区、合并分区。
增加分区的语法:
alter table 表名 add partition 分区表名 values less than(值)
例如:
altertable drawlist add partition part_4 values lessthan(to_date(‘1/1/2012’,’dd/mm/yyyy’)) tablespace demo;
删除分区语法:
alter table 表名 drop partition 分区表名
例如:
alter table drawlist droppartition part_3;
截断分区是删除当前分区中的数据,但不删除当前分区,也不影响其他分区。
语法:
alter table 表名 truncate partition 已存在的分区表
如:
alter table drawli st truncatepartition part_1;
合并分区是将两个分区的数据合并成一个分区里,注意:高界限的分区不能合并到低界限的分区中。
合并分区的语法:
alter table 表名 merge partitions 分区表1,分区表2 into partition 分区表2
例如:
alter table drawlist merge partitions part_2,part_4 into partition part_4;
sql优化途径:选择合适的oracle优化器、选择恰当的扫描方式、善于利用共享的sql语句。
1、选择合适的优化器。cbo优化器:基于成本的优化器,这个成本是指cpu和内存占用率。
在编写sql时,可以使用cbo对sql进行优化从而获得更快的响应速度。
优化器使用的模式根据目标而定,cbo的优化模式有四种分别为:1、rule:基于规则。2、choose:默认,表或者索引有统计信息,走cbo模式,否则,走rbo模式。3、firstrow:表中有统计信息时,以最快方式返回查询的前几行,总体减少响应时间,4、allrows:表中有统计信息时,以最快的方式返回表的所有行,总体提高查询吞吐量。
1、 选择合适的扫描方式。oracle中,查询数据可以分为:全表扫描、使用rowid、索引全扫描、快速索引扫描。
全表扫描:就是oracle读取表中所有的行,并检查每一行是否满足where语句的限制。在数据量大的表中不建议使用全表扫描,效率低下。
使用rowid:rowid指出该行所在的数据文件、数据块以及行在该块的位置。是oracle存取单行数据最快的方式。
索引全扫描:只在cbo模式下有效,这种方式查询的数据必须可以从索引中直接得到。
快速索引扫描:它会扫描索引中所有的数据块,与全索引扫描类似,但这种方式不会对查询出的数据进行排序,这种方式会获得最大吞吐量,并且缩短执行时间。
3、学会利用共享的sql语句。它存在oracle的系统全局区中,也就是sga,可以通过设置sga的大小,来提高sql的执行效率。
其它类似信息

推荐信息