范式设计简单介绍(二)0+

11,482 views / 2009.09.08 / 1:01 下午

1.3] Third Normal Form(3NF)

3NF 要求所有的属性都直接依赖于 primary key。3NF 和 2NF 最大的不同之处是,2NF 有依赖传递性,而 3NF 不准许。

例如,有一个符合 2NF 的表:

错误方式:

+———————+———–+—————-+———–+———-+——————

..some属性s | 用户号 | 用户发表文章数 | 用户登录数| 用户积分 | other 列 …

+———————+———–+—————-+———–+—————————–

…… | ID_001 | 4 | 20 | 13 | ……

+———————+———–+—————-+———–+———-+——————

用户积分规则:用户发表文章数 x 2 + 用户登录数 /4

在 3NF 中是不符合的。因为‘用户积分’是通过‘用户发表文章数’和‘用户登录数’,用公式计算得来的。也就是说,‘用户积分’依赖于‘用户发表文章数’和‘用户登录数’。

3NF 符合的划分方式是:

正确方式:

+———————+———–+—————-+———–+——————-

..some属性s | 用户号 | 用户发表文章数 | 用户登录数| other 列 …

+———————+———–+—————-+———–+——————-

…… | ID_001 | 4 | 20 | ……

+———————+———–+—————-+———–+——————-

正确方式:

+———————+———–+———–+——————–

..some属性s | 用户号 | 用户积分 | other 列 …

+———————+———–+———–+——————–

…… | ID_001 | 13 | ……

+———————+———–+———–+——————–

用户积分规则不变

需要注意的是,虽然 3NF 更加清楚地将用户资料和用户积分这两个关系表示了出来。但是在需要联合查询用户资料和积分的情况下,在大多数 RDBMS 如 MySQL 中,会造成性能消耗严重的情况。进一步讨论在 1.4 中进行。

1.3.1] Joining 关系

关系之间相互关联的方式有两种:INNER JOIN 和 OUTER JOIN

INNER JOIN 查询会返回两个关系完全匹配的情况,MYSQL 默认的匹配方式为 INNER JOIN 。

如果你希望查询的结果即使没有匹配也会被查询出来,那么就要使用 OUTER JOIN 的连接方式。OUTER JOIN 又细分为三种:LEFT OUTER JOIN, RIGHT OUTER JOIN 和 FULL OUTER JOIN 。

LEFT OUTER JOIN 是将左边的查询关系作为主关系,如果右面的关系有相匹配的 tuple , 那么处理方式和 INNER JOIN 一样;如果右面的关系没有与左边的关系相匹配,那么属性就会列出一个 NULL 的值。

RIGHT OUTER JOIN 的处理方式与 LEFT OUTER JOIN 类似,只不过是以右面的关系为主 关系。

FULL OUTER JOIN 与 INNER JOIN 的显示结果相同。

1.3.2] BCNF

修正的第三范式(BCNF) 全称 Boyce-Codd normal form 。是 3NF 的一个拓展,所以 BCNF 的前提和 3NF 是一样的:关系 必须符合 2NF ,并且有 KEY 可以用来相互关联。并不是所有符合 2NF 的关系都可以划分为 BCNF。

BCNF 简单来说,就是所有的 tuple 都依赖于 candidate key 或者这个 tuple 是 superkey 。因此所有的 tuple 都依赖于 key,从而避免了传递依赖问题。

1.4] NF 设计与性能消耗

NF 理论在设计之初,主要是为了应付数据冗余与存储重复而出的。当越来越庞大的数据库应用出现时,高度设计的 NF 带来的好处与性能所带来的坏处相互抵消了。因为通常,越高层次的 NF 会划分越多的 关系,从而查询出所需要的数据就需要更多的 join 操作。虽然 view 在一定程度上可以解决这个问题,但是视图本身也是一个不小的性能消耗。

如果一个 MySQL 执行的多是 SQL-Transaction 的话,那么使用高层次的 NF 设计就显得尤为必要,因为书写 transaction 的 SQL 语言通常都不适于做复杂的过程处理,而高层次的 NF 设计可以在逻辑上更清楚的划分关系,从而较少的操作关系之间的关系处理,较多的操作关系之间的数据。

而如果一个 MySQL 在应用中 ,更多的是扮演数据存储与统计的操作,那么高层次的 NF 设计就没有必要。因为此类应用中,通常都搭配使用高级编程语言,而高级编程语言灵活多样,在逻辑、过程与数据的处理过程中,都要比 SQL 更加的强壮。

1.5] NF 与 SQL 的关系

SQL 语言是为了结构化的查询数据而发明的一种机器查询语言。主要的功能是查询,兼顾数据定义与控制的功能。

SQL 大致可以分为三类:

1.5.1] Data Manipulation Language (DML)

DML 主要用来 查/删/改/插关系的 tuple 。他们共同的特点是都需要指定作用的关系和关系之间的关系。

1.5.1.1] Select

Select 用来查询关系中的 tuple 包括:

Select : 后面跟属性,作用是控制查询的输出。

From : 后面跟关系与 joins ,作用是控制与关联关系之间的关系。

Where : 后面跟属性的限制语句,主要是用来划分查询的区域。

Group By : 后面跟属性,主要用来将相似的属性分成单一的结果集。

Having : 与 Where 作用相同,作用域为 Group By 控制的结果集。

Order By: 用来将最后筛选出来的结果集,通过某一 tuple 来进行排序。

具体作用详见:1.2.1]

1.5.1.2] Insert

Insert 用来插入 tuple。具体作用详见:1.2.2]

1.5.1.3] Update

Update 用来更新 tuple 。具体作用详见:1.2.3]

1.5.1.4] Delete

Delete 用来删除 tuple 。作用域与 Select 类似,但是不返回查询的 tuple。

1.5.2] Data Definition Language (DDL)

DDL 的作用是创建关系与定义关系中的属性。主要包括三大部分:

1.5.2.1] CREATE

创建语句,可以用来创建 Database、关系、transaction(祥见 1.2.4) 等。根据需要创建的类型不同,语句稍有差别。

1.5.2.2] DROP

删除语句,与 CREATE 语句相反。

1.5.2.3] ALTER

修改关系和 Transaction 。

1.5.3] Data Control Language (DCL)

DCL 的作用是用来控制关系和属性的权限。主要有两部分:

1.5.3.1] GRANT

用来创建访问关系与属性的权限

1.5.3.2] REVOKE

用来删除访问关系与属性的权限

原文作者:韩述 杜工稍作修改。

Categories: 分享 Tags: ,

范式设计简单介绍(一)1+

15,149 views / 2009.09.08 / 1:01 下午

范式设计是关系数据库的一个延伸理论。目的是在关系数据库的基础上,减少重叠数据的冗余,并且在将列(属性) 逐渐拆分成表(关系) 的过程中,从理论上减少了异常数据产生的几率。增强了数据的关系性能,在一定程度上,增强了关系查询效率。

术语:通常在具体的 RDBMS 如 MySQL 的应用开发中,将一个关系叫做表,一条元组(tuple) 称为行,一个属性叫做列。 因为范式(NF) 设计主要是讲理论,所以在本文中,一律将表称为关系,将行称为tuple,将列称为属性。

如图:

范式设计

1.1] First Normal Form(1NF)

1NF(第一范式) 的目的是将数据拆分成原子状态。例如 一个大型文章发布系统的文章序列号的组成是 8 位用户名 + 该用户所属的文章号,如某用户的用户名是 ID_001 ,他发表的某一篇文章,在他的文章列表中的序列号是 15 ,这篇文章在该系统中唯一序列号是 ID_00115 。

将文章序列号存储到关系中去,通常的做法是这样的:

错误的方式

+———————-+—————–+—————+

some属性…… | 文章序列号 | other 列……

———————-+—————–+—————-

……| ID_00115 |

这么做是不符合 1NF 规范的。因为文章序列号是两部分组成的,如果存成一个属性那么就违反了 1NF 的原子性原则。

符合 1NF 的属性划分方法如下:

正确方式:

+———————-+————–+——–+—————+

some属性…… | 用户号 | 文章号 | other 列……

———————-+—————+——–+—————-

……| ID_001 | 15 |

+———————-+————-+——–+—————+

1.2] Second Normal Form(2NF)

2NF 划分关系的原则是:一个关系中的所有非 Key属性s 必须完全的依赖于 Key。如果是多主键的话,那么非主键属性s 必须完全依赖所有的主键.

1NF 的范围是同一关系的不同属性之间的划分。而 2NF(第二范式) 的范围是将一个大的,数据相互重叠与冗余的关系拆分成众多小的,关系 ,他们之间相互的联系就是 Key ,Key 是一个关系中唯一标示一个tuple 的标识。而且在 2NF 中,所有有效的单一的 Key 默认都是 Primary key。(多个 Key 唯一定位一个tuple ,那么这些Key 称为复合主键) 。

另外一点需要特别注意的是,范式是属性递增的,因此,只有在完成了 1NF 之后,才能进行 2NF 的划分。

例如某文章系统中,一个存储某一篇文章的关系,有如下字段

错误方式:

+————————–+————+———-+———–+———–+————–+—————-+———–+——————

..some属性s | 用户号 | 文章号 | 文章标题 | 文章内容 | 文章创建时间 | 用户发表文章数 | 用户登录数| other 列 …

+————————–+————+———-+———–+———–+————–+—————-+———–+——————

……| ID_001 | 15 | Article | Cnt … | 1223372589 | 4 | 20 | ……

其中,‘用户号’和‘文章号’对于 ‘文章标题’、‘文章内容’、‘文章创建时间’来说,可以算是复合主键,因为要查出这些属性,必须完全依赖 ‘文章号’和 ‘用户号’这两个属性,缺一不可。

而 ‘用户发表文章数’和 ‘用户登录数’这两个属性仅依靠 ‘用户号’就可以出来,所以 ‘用户号’是 ‘用户发表文章数’和 ‘用户登录数’的主键,而 ‘文章号’则和这两个属性没有关系。也可以说 ‘用户发表文章数’和 ‘用户登录数’没有完全依赖于复合主键,所以这个表不符合 2NF 标准(但是所有属性都是原子不可分状态,因此这个表符合 1NF 标准)。

如果要符合 2NF 标准,就需要将这个关系拆分成两个关系

正确方式:

+————————–+————+———-+———–+———–+————–+————————–

..some属性s | 用户号 | 文章号 | 文章标题 | 文章内容 | 文章创建时间 | other 列 …

+————————–+————+———-+———–+———–+————–+————————–

……| ID_001 | 15 | Article | Cnt … | 1223372589 | ……

+————————–+————+———-+———–+———–+————–+—————————

正确方式:

+————————–+————+—————–+———–+——————-

..some属性s | 用户号 | 用户发表文章数 | 用户登录数| other 列 …

+————————–+————+—————–+———–+——————-

……| ID_001 | 4 | 20 | ……

+————————–+————+—————–+———–+——————-

这样,Right way one . 中剔出了不符合完全依赖的两个属性s ,所有的属性s 都完全依赖 composite primary key ,可以认为 Right way one. 符合 2NF 标准。

另外,将 Wrong way. 中剔出的两个属性s 划分到了 Right way two. 里面,primary key 是 ‘用户号’。因此 Right way two. 仅就一个 primary key ,并且所有内容都依赖于 primary key 查询,所以可以说 Right way two. 符合 2NF 的要求。

1.2.1] 关系模式

经过 2NF 的拆分,现在关系的数量在增加,但是属性之间的关系趋向于更加的简单明了。

关系之间根据对应联系的不同,有三种不同的关系模式:

· 一对一

· 一对多

· 多对多

·一对一 , 既一个属性仅可以对应一个其他的属性

例如:一个用户号和用户之间就是一对一的关系,一个用户只能有一个用户号,一个用户号只能指定某一个用户。

·一对多 , 既一个属性可以对应多个其他的属性

例如: 一个用户号可以对应多个文章号,因为用户可以发表多篇的文章.

·多对多 , 既多个属性可以对应多个其他的属性

完全多对多就是 Cartesian product(笛卡尔积或直积)。

例如: 一个用户可以发相同标题的不同文章。而拥有相同标题的文章,可以由不同的用户发。

Categories: 分享 Tags: ,

JS数据压缩算法3+

19,020 views / 2009.09.04 / 12:12 下午

研究Google chart API的时候发现它提供的数据压缩算法不错,可以把纯数字的数组压缩成很短的一个字符串,分享如下:

var simpleEncoding = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
 
function simpleEncode(values,maxValue) {
 
var chartData = ['s:'];
for (var i = 0; i < values.length; i++) { var currentValue = values[i]; if (!isNaN(currentValue) && currentValue >= 0) {
chartData.push(simpleEncoding.charAt(Math.round((simpleEncoding.length-1) * currentValue / maxValue)));
} else {
chartData.push('_');
}
}
return chartData.join('');
}

测试例子:

var valueArray = new Array(20,100,40,50,60,81,74);
var maxValue = 100;
document.write(simpleEncode(valueArray,maxValue));
Categories: 分享 Tags: , , ,

用js计算时间差,得到比较人性化的结果0+

10,580 views / 2009.09.03 / 5:05 下午

我们经常看到一些文章或者评论的发表时间不是直接显示出死板的Y-m-d格式,而是算了一个时间差,如:发表于2分钟前,这样显得比较人性化,多用于一些非正式网站。下面提供JavaScript的实现方法:

var minute = 1000 * 60;
var hour = minute * 60;
var day = hour * 24;
var halfamonth = day * 15;
var month = day * 30;
 
function getDateDiff(dateTimeStamp){
var now = new Date().getTime();
var diffValue = now - dateTimeStamp;
 
if(diffValue < 0){
 //非法操作
 //alert("结束日期不能小于开始日期!");
 }
 
var monthC =diffValue/month;
var weekC =diffValue/(7*day);
var dayC =diffValue/day;
var hourC =diffValue/hour;
var minC =diffValue/minute;
 
if(monthC>=1){
 result="发表于" + parseInt(monthC) + "个月前";
 }
 else if(weekC>=1){
 result="发表于" + parseInt(weekC) + "个星期前";
 }
 else if(dayC>=1){
 result="发表于"+ parseInt(dayC) +"天前";
 }
 else if(hourC>=1){
 result="发表于"+ parseInt(hourC) +"个小时前";
 }
 else if(minC>=1){
 result="发表于"+ parseInt(minC) +"分钟前";
 }else
 result="刚刚发表";
? return result;
}

如果你得到的原始数据不是时间戳,可以采用下面的函数把字符串转换为标准时间戳, 它相当于JS版的strtotime,只不过精度不同罢了:

function getDateTimeStamp(dateStr){
 return Date.parse(dateStr.replace(/-/gi,"/"));
}
Categories: 感悟 Tags: , ,

大数据网站降低单点故障损失的方法0+

7,697 views / 2009.09.03 / 12:12 上午

大数据网站的数据具有访问频率高,更新速度快,更新量大,不便于备份等特点,如果我们依然用传统的单服务器单数据库去构架,首先不能保证大流量访问,其次数据备份困难,再次数据出现故障不能及时修复,所以,我们从两个方面着手,本着低成本的原则,提出解决方案。

一 采用双网卡,内网外网分离,维护时内网操作,外网负载均衡后提供服务。采用主从数据库的方式。

目的:提高系统稳健性,降低单点故障给系统构成的影响。

前提:1. BIGIP自动识别异常服务器功能正常工作;2. 系统挂载的存储及数据库正常工作

方式

1. web端的冗余

a) 唯一性数据存放在存储服务器上(模板、静态化文件、碎片等)

b)程序等多份数据(选择一台机器做为主机器,用rysnc进行程序更新以及分发),程序定期更新至svn。

 2 . 数据库冗余

采用M-S模式,进行读写分离。在程序上进行控制,要是有一个出问题直接切回单机模式,来防止数据库机器损害带来的长时间停机。(应用程序修改大,需要较长时间,可以考虑进一步优化)

如图:

1

二 挂载双存储,每个存储分多个挂载点挂载到前端服务器。

如果系统存储只有一台服务器,如果出问题,会造成长时间服务中断,我们讨论出一套方案,可以使损失降到尽量小。

设存储一为s1,存储二为s2, 这两台都有三个挂载点,记为data1,data2,data3,我们把s1的data1,data2挂载在前端机器上,把s2的data3也挂载在前端机器上,同时每天把s1的data1,data2同步到s2, 把s2的data3同步到s1,保证两个存储数据尽量同步。

如图:

2

当故障发生时,比如s2宕掉,可以快速的把前端服务器的data3挂载改为s1的data3,这样只有最多一天的单个目录数据丢失,我们可以再对其进行简单的恢复操作。?

优点:1. 单存储负载被分担 2.线上已有产品程序不用调整 3.故障时处理迅速

缺点:故障恢复时,当天的部分数据可能会丢失。