NoSQL和MemeryCache的出现意味着传统数据库使用方式的变革吗?(arvin-推荐--看评论)

前端之家收集整理的这篇文章主要介绍了NoSQL和MemeryCache的出现意味着传统数据库使用方式的变革吗?(arvin-推荐--看评论)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

来自:http://www.cnblogs.com/nankezhishi/archive/2012/02/12/2348091.html#2617778

故事的起源

作为软件工程专业出身的程序员,之前所接受的关于数据库的教育都是基于关系型数据库。对key-value based数据库和document-based数据库的都只是仅仅了解而已。

最近公司要做一个类似电商的系统,我来负责数据库的设计和接口的提供。当然,我们使用的数据库也是传统的关系型数据库sql SERVER 2005,所以我也并没有什么太大压力。

但是当头儿看到我设计的分类系统的数据库表结果时意见很大,一翻沟通下来,我基本上就崩溃了。他的一翻话基本上推翻了我对数据库的基本认识。


我的设计

要实现的分类是书籍分类体系,会至少有4层,总共大约有几百个分类。我很自然地想到了邻接表(Adjacency List)模式。然后设计了的表结构大体如下:

列名 CategoryId ParentId Name
描述 主键 父键 分类

当然还有别的字段,与问题无关就不列了。

使用CTE递归的方式来获取一个分类下的子分类树。我考虑数据量并不大,所以性能上应该不成什么问题。

和头儿的争论

头儿看到我的设计,直接说,不用这么麻烦了,不是有4层吗?那就用4列,一列表示一级。

我说国图法分类可能有7层以上。他说那就7列好了。

我说这样数据量会有大量冗余,更新起来会很麻烦。

头儿说,我之前做过很多树型结构,一开始也和你一样。但是做着做着就发现查询继承关系好麻烦啊,还不如直接用列存储下来。

我说查询继承的代码我已经写好了,用CTE递归我并不觉得麻烦啊。

头儿说,不要用递归,我们要为读优化,而不是为写优化。

这个我完全赞同,但是这个数据量并不大,但是我还是觉得这个做法很山寨。不符合数据库的基本范式啊。

他说你知道范式,也要了解反范式。而且这个数据库本身不要包含业务逻辑。你看现在出来的Redis和MemeryCached,存的都是名值对儿,没有逻辑。逻辑是给业务处理的。什么是程序?程序就是算法加数据,数据和逻辑是要分开的。

我说从属关系也是逻辑吗?数据一致性也是逻辑吗?

应该算啊,数据库就是负责存储数据的就够了,你自己好好想想吧。

之后我还是坚持了自己的做法,头儿勉强接受,但是要多加一个Path列,存储这个分类的所有父节点。

这个我倒是同意加上,这属于为特定查询做的优化。

背景和现状

我进这个项目的时候,这个项目的数据库基本上已经建立完了。现在只是由于业务扩展需要新建数据库表。刚进公司的时候,我就觉得这里的数据库用法很诡异。

  1. 只有主键,没有外键,也就是数据库基本无从保证数据的一致性。
  2. 没有使用ORM,需要在C#代码中拼sql来实现业务对象的读取和写入。
  3. 不允许使用存储过程。这会引入过多的业务逻辑。
  4. 我也没见过任何View,任何Trigger,任何自定义函数

现在发现这些现状与头儿的想法其实是比较一致的。但是给人的感觉就是把sql SERVER当作一个Key-Value的Database来实用。自然也就不需要那些sql SERVER的功能

但是我很奇怪,这样的用法,为什么不直接用No sql方案呢?不用也就算了,更让我困惑的地方就在于,把No sql的理念用在关系型数据库上合适吗?

我在这里也没有看到过任何数据库性能Profiling的代码,对于数据库性能的考量,基本上依赖数据库服务器的cpu占用。(也许有测试人员做过我不知道而已吧。希望是这样。)我们仅有的一名DBA也于年前离职了。

我的想法

我一直觉得数据库设计是一项很重要很复杂的工作,需要了解业务需求,需要了解用户的使用方式,需要能够遇见到基本的可变性,需要对数据库底层机制有深入的了解,等等等等。也听过很多数据库高手改写一段sql,就让数据库查询变得飞快的故事。而且一切优化都应该有实际的数据来说话。也许我们头儿在数据库设计上有相当的功力,很有感觉。但是真的是这样的吗?我有我自己的想法,不知道是不是正确,但希望能和大家讨论一下。

关于反范式和优化

反范式作为一种数据库优化方案,我并觉得和其它的优化有什么根本上的不同。但是从优化的次序上来讲,我个人觉得应该先在查询sql上做足功夫,不行了再祭出反范式这个以空间换时间的杀手锏。不应该是从数据库设计一开始就惦记着的事情,尤其是这还是在关系型数据库上。当然,资深人员一眼就能感觉出哪里需要这么干当然更好。不过对于上面的情况,我个人觉得不需要。

关于数据库不能有逻辑

这句话首先需要澄清什么属于逻辑。由于这是我们头的观点,我也没有跟他详细讨论过这个问题。我来讲下我的理解吧。数据库在设计之初就是为某个业务设计的,脱离了这个业务,这个设计本身也没有了意义。所以我不认为逻辑从数据库分离能让数据库可以被重用。但是数据库包含了过多的逻辑会增加数据库服务器的负担,所以逻辑还是少放在数据库为好。所以我基本同意这句话。

但是,我认为。数据关系(如外键)不属于逻辑,数据完全性不属于逻辑。而且这些就应该主是由数据库来保证的。Web 服务器可以去检查外键,检查唯一约束,但是即使Web服务器不做这些,数据库也应该做到这些。

最常见的就是数据插入和更新,如果涉及到多张表,那这些sql写入一个存储过程以方便外界调用是很好的。同时,存储过程或是View也可以把数据库表设计与程序之间的依赖解除,在一些简单的情况下实现不修改程序而对数据库表结构进行变更。使用存储过程也许会给数据迁移带来麻烦,但是有谁没事儿换数据库呢?

我们目前这种在程序中拼sql去操作数据库的做法,我没有看到什么优势。纯粹就是为了“数据库不能有‘逻辑’”而拆分出来的东西。

关于数据库系统的选用

我并没有反对Nosql或MemeryCached的理念,毕竟是用于处理不同的情况问题的。

像微博、社交、互动相关的系统。因为数据量大,访问量大,数据结构相对简单,用户访问具有时效性、地域性,使用这种Nosql+MemeryCache方案是合理甚至是唯一的选择。但是任何产品或是理念都有它适用的范围,没有银弹。把 MemoryCache用在员工作业平台或是项目管理系统上我觉得就相当的不靠谱。

但是电商系统似乎是处于两者之间的一种模式,而且我们的业务量在可预见的未来也不会增长到淘宝的那个级别。我和头的争论也就源于这些理念上的差别,他像是在建立大统一理论,把各种先进思想整合在一起,而我又不确定这是创新呢?还是不伦不类的方式?于是有了题目上的疑问。而按头的说法,也许这就是思考问题层次上的差别。

我在数据库设计上并没有什么经验,却又做不到别人说什么我就听什么。上面只是我根据对于数据库自身的理解产生的一些想法,还很不成熟,希望大家能说说自己的见解。如果实在看不下去了,也欢迎吐槽。

9
0
(请您对文章做出评价)
« 上一篇不使用反射进行C#属性的运行时动态访问
» 下一篇从一个UI交互设计师的讲座说开去

posted on 2012-02-12 17:20 南柯之石 阅读(3151) 评论(29) 编辑 收藏

评论

#1楼 2012-02-12 17:55一味

其实我比较倾向于你的头头的想法。
如果使用了过多的数据库的特性(存储过程,触发器等),会将我们的系统架构局限于该数据库平台,对于项目还好,对于产品来说,可能是一种风险。特别是在将来可以预见到有迁移数据库平台的可能的时候。

#2楼[楼主] 2012-02-12 18:21南柯之石

引用 一味:
其实我比较倾向于你的头头的想法。
如果使用了过多的数据库的特性(存储过程,触发器等),会将我们的系统架构局限于该数据库平台,对于项目还好,对于产品来说,可能是一种风险。特别是在将来可以预见到有迁移数据库平台的可能的时候。

这代价是不是有点儿大了。
这样的话,每个平台特有特性是不能用了。我还没有做过迁移平台的事情,但存储过程和触发器这种东西并不是每个平台特有的东西,大家都有。应该不会给迁移带来多大麻烦,即使语法上略有不同,写在存储过程的sql可以很容易用工具进行格式转化,但是写在代码里的sql语句就没有办法了。

#3楼 2012-02-12 18:25Stephen_Liu

Nosql数据库的应用场景非常宽泛,一般都可以提前预见。至于关系型数据库中的逻辑,说说我们以前公司的产品设计,存储过程和触发器基本不会写,这是因为我们必须考虑跨数据库的问题,但是表的一致性等问题还是需要使用的,因为几乎所有的数据库都有这样的特性,因此不会带来移植性问题。还有就是视图一般都是非常必要的,主要是为了尽量保证数据库结构和代码之间的松耦合。

#4楼[楼主] 2012-02-12 18:35南柯之石

@Stephen_Liu
引用 Stephen_Liu:Nosql数据库的应用场景非常宽泛,一般都可以提前预见。至于关系型数据库中的逻辑,说说我们以前公司的产品设计,存储过程和触发器基本不会写,这是因为我们必须考虑跨数据库的问题,但是表的一致性等问题还是需要使用的,因为几乎所有的数据库都有这样的特性,因此不会带来移植性问题。还有就是视图一般都是非常必要的,主要是为了尽量保证数据库结构和代码之间的松耦合。


谢谢。请问你们的sql语句是存放在什么地方的?有没有用ORM?另外,存储过程应该是所有数据库系统都有的功能,为什么会给迁移带来麻烦呢?

#5楼 2012-02-12 18:42bluce chen

很简单,你们头的思路是,维护方便,新人入手容易,不用去花很多时间熟悉业务流程·也算是种偷懒吧·

#6楼 2012-02-12 19:15Stephen_Liu

@南柯之石
没有ORM,我们是用C++进行开发的,操作数据库也是直接使用数据库提供的C接口API。sql语句完全在代码中,代码中有相应的class来适配不同的DB。存储过程并不是每一个DB都有的,比如老版本的MysqL、Postgresql和现在的sqlite。因为我们的客户可能已经有了自己的DB,我们的产品不能强制要求客户进行更换,特别是一些日本客户,他们都比较谨慎,所以只能是我们的产品提供这样的支持了。

#7楼 2012-02-12 20:23午后的小睡

用几年ORM就会喜欢写sql了,维护几个别人做的项目,就会讨厌层次太多的数据库设计和各种触发器约束了。

人啊,都是被逼出来的。

#8楼 2012-02-12 23:07pulihe

做网页产品,树递归可以放在客户端用js来生成,这样大大降低服务器资源占用。
如果你搞一个大型网站,可以在sql性能分析器里看到,树生成很占资源的。

#9楼 2012-02-13 00:26不若相忘于江湖

1 只有主键,没有外键,也就是数据库基本无从保证数据的一致性。
在访问量大的系统,不同意使用外键,我认为是性能问题,如果是内部软件,则可以,

2 没有使用ORM,需要在C#代码中拼sql来实现业务对象的读取和写入。
我们现在的做法也是一样,拼sql,不过之前会有相应的安全过滤机制。

3 不允许使用存储过程。这会引入过多的业务逻辑。
我们现在也是不能使用存储过程,理由嘛,有些人写习惯了,会经常把业务逻辑也写到里面去的,维护起来很吃力。

4 我也没见过任何View,任何Trigger,任何自定义函数
Trigger除非非常有必要,否则坚决不用。

#10楼 2012-02-13 01:47Gu

同意1,3,部分同意4

1 只有主键,没有外键,也就是数据库基本无从保证数据的一致性。
方便扩容和copy数据

2 没有使用ORM,需要在C#代码中拼sql来实现业务对象的读取和写入。
用orm对性能没太大影响,还是应该用的

3 不允许使用存储过程。这会引入过多的业务逻辑。
你只要维护过一堆存储过程的系统,你就知道这个苦啊...

4 我也没见过任何View,任何Trigger,任何自定义函数
尽量不要用trigger和自定义函数. 但view我还是很喜欢用的.

#11楼 2012-02-13 08:21Kain

1、外键,我是这样看的数据一致性要求不是非常高的情况,如果一个db就一个输入,基于信任的原则,那就通过业务逻辑来保证数据的完整性吧。或者开发的时候启用外键,部署的时候不启用了。
2、ORM么,什么都有两面性,ORM牺牲了部分性能来换取开发的效率,就看系统中这种牺牲是否值得了。
3、SP么,现在基本不推荐使用了,能用业务层处理的尽量不用SP干,哪怕效率低上很多,毕竟DB的扩展实在是太难了。

#12楼 2012-02-13 09:07imfunny

@H_403_367@ 程序就是算法加逻辑。的确是这样。数据库什么的在某种程度上说的确就是浮云,只是一种介质。

#13楼 2012-02-13 14:10睡不醒

很明显,你们头就是把数据库当作一个高性能的数据容器了,如果有个高性能的NOTEPAD能作为数据容器的,估计他会更喜欢!当然,这也不是什么错,范式什么的也是有应用场景的,如果是做管理、金融一类的项目,这些范式是很有必要的。但是如果只是一个简单的数据存储而已,真没必要弄那么复杂。
1:只有主键,没有外键,也就是数据库基本无从保证数据的一致性。
答:关于外键:仁者见仁、智者见智了,有人喜欢有人讨厌!如果业务要求数据必须保持高度一致性,那必须要外键,否则就无所谓了。
2:没有使用ORM,需要在C#代码中拼sql来实现业务对象的读取和写入。
答:ORM不是万金油,更不是银弹,成也萧何败萧何,如果系统的业务逻辑很简单,而且业务需求也很明确,不会经常修改业务逻辑,那真没必要使用ORM,因为ORM的性能实在是不敢恭维,能用几句sql搞定的真没必要用ORM,而且读的并发达到100万的话,还是用sql吧。
3:不允许使用存储过程。这会引入过多的业务逻辑。
答:如果考虑到跨平台的特性,还是别用存储过程了,sqlSERVER和ORACLE虽然都有存储过程,但是写法不一样的!这个会造成部署的困难,但是把逻辑写到程序中的话,至少很容易保证逻辑一致。当然,如果用户都是微软的合作伙伴的话,还是使用存储过程的好,性能会好些。
4:我也没见过任何View,任何Trigger,任何自定义函数
答:Trigger太影响性能和稳定性了,自定义函数同存储过程,不再赘述,View?你都是手写sql,自己直接JOIN就是了,VIEW无非就是帮你JOIN了,再加个缓存。而且每次更改表结构都要刷新视图,很讨厌!

#14楼 2012-02-13 21:03fchzzwcsr201

我想问个问题:数据的存储介质应该有很多吧,希望各位大侠能列出自己所知道的存储介质?各种存储介质都各有优劣,不知道能不能混合使用的

#15楼 2012-02-14 09:28imfunny

引用 fchzzwcsr201:我想问个问题:数据的存储介质应该有很多吧,希望各位大侠能列出自己所知道的存储介质?各种存储介质都各有优劣,不知道能不能混合使用的

其实看需要的。想简单sqllite,想对象化用db4o,普通的使用mssql或者MysqL,想高端用oracle,db2,之外还有很多很多。同时还有MongoDB这样的kv6格式的数据库。随便选择吧。
无所谓那种数据库,其实关键还是程序和算法。数据只是一个成品。比如blogengine人家默认的直接使用xml存储数据。

#16楼 2012-02-14 09:52遗忘海岸

头其实有道理的,人家这么都年也不是白混的

#17楼 2012-02-14 10:07adexbn

你的头的做法是对的。
从你描述的背景和现状来看,有充分的理由说明应该这样。

#18楼 2012-02-14 22:47Fish Li

树型用ParentId最麻烦了,除非不搞子孙节点的查询

#19楼 2012-02-15 10:53luofer

上面都是想当然的说法,既没仔细看人家的实际情况,也没做深入的思考就凭感觉说。
数据库设计要在一致性和性能上进行取舍,如果是可以容忍延迟一致性和一致性失败而是看重高可读,Nosql当然是首选,但在关系数据库上搞这些还是很怪异,还是用Nosql去吧。如果是要保证高可用和一致性那就只能是关系型数据库了。所有的范式和设计规则基本都是为了保证在一致性的前提下保证性能
反范式首先是要有范式才对吧,否则反范式从何而来?

#20楼 2012-02-15 11:09luofer

补充一句仔细看看大伙的回复普遍(大部分)表现出对数据库实现的蔑视,作为程序依托,轻视数据库的代价可能就是一遍又一遍的recode,举个例子,如果程序是一座大厦,你愿意让大厦的地基随便设计吗?
至于有人说不用存储过程是怕有人把业务逻辑塞到里面,我想是误会了关系型数据库的用途,毕竟数据库最擅长的还是以集合,批来处理数据,所有在里面大量使用游标,流控制的建议多看看数据库原理,现在还有那种主流的关系型数据库不支持存储过程吗

#21楼 2012-02-17 14:32Ivony...

数据结构和物理结构的分离是老早的事儿了,几乎没有数据库的物理结构是与数据结构完全吻合的,你分析的数据结构是非常正确的,但做数据库设计的时候,几乎不可能将数据结构完全搬到物理结构上,一定要考虑性能和其他因素的影响从而作出冗余的妥协,冗余的副作用数据的一致性也需要给出方案来规避和解决

至于你说的sql优化,君不知主流的关系型数据库都是自行查询优化的。你写的sql并不能决定其实际行为。

#22楼 2012-02-23 23:24@L_403_152@

1 只有主键,没有外键,也就是数据库基本无从保证数据的一致性。
外键影响性能,在高性能的系统中不应该使用
一般开始可以做范式设计,然后再做反范式设计

2 没有使用ORM,需要在C#代码中拼sql来实现业务对象的读取和写入。
ORM优势和劣势都很明显
开发速度快,处理简单逻辑简单,不过功能和定制性太差了,想搞点复杂功能或者是优化sql性能都非常困难

3 不允许使用存储过程。这会引入过多的业务逻辑。
存储过程的好处是功能性能稍好,和程序脱离的部署,良好的权限控制和安全机制
坏处是部署麻烦,版本要一致,程序员的控制能力有一点小问题
我很讨厌强制要求使用存储过程的公司

4 我也没见过任何View,任何Trigger,任何自定义函数
Trigger? 万不得已别用它
View啊....搞搞内部系统用一下还行,平时就不要拿出来玩了

如果是搞小系统,内部系统,或者是学术系统(设计的很漂亮,不实用)
那么爱怎么搞怎么搞

回来说
那个树形结构,网络上有现成的了,随便搞一个吧,看的不爽自己优化也ok,自己写的东西如果没经过验证的复杂东西,老板出于风险控制的目的,八成会砍掉
用不用Nosql或者Memcached主要是架构方面的考虑

#23楼 2012-03-09 10:51Alvin

楼主技术人员的执拗可见一斑,系统是用来用的,教条主义会害死人。
外键本来就是业务逻辑上的需求,为何一定要数据库来维护?
有谁会不计后果的用触发器?
ORM只不过是方便了懒惰的程序员而已。

#24楼 2012-03-11 10:20BFL

你头儿让你加上一个PATH是经验之谈.

#25楼 2012-03-18 22:11通心菜

1 只有主键,没有外键,也就是数据库基本无从保证数据的一致性。
同意 我们目前开发规范明确规定 不许有外键

2 没有使用ORM,需要在C#代码中拼sql来实现业务对象的读取和写入。
这个可以适当考虑加进去

3 不允许使用存储过程。这会引入过多的业务逻辑。
同意 我们目前开发规范明确规定 不许有存储过程 .迁移过一次带SP的项目痛苦...

4 我也没见过任何View,任何Trigger,任何自定义函数
同意

#26楼[楼主] 2012-03-18 22:20南柯之石

@通心菜
哥们,我错了,我应该说得更明白些的。我说的太绕了,真是全拧了。汗啊。。。。

#27楼 2012-03-19 17:11Henming

之前的项目是使用ORM开发的,最近在做项目总结的时候跟楼主一样考虑了这些问题。
其实数据库越来越倾向于单独存储,对软件越来越透明。
公司的架构师跟你们老大的想法几乎都是吻合的,数据库只用作存储,不做其它附加。

#28楼 2013-02-09 05:36Michael.zh

从楼主描述的情况看,估计还比较年轻的,没有任何歧视年轻的意思,我想说的是,等你以后有机会接触到真正企业级的数据处理,你就会发现几个很有意思的特点:
1,没有任何一个数据是符合数据完整心规范的,使用外键的唯一结果就是大量的数据无法导入;
2,报表基本上都给予“非完整性”数据出来,不精确但完全不影响报表使用者进行决策;
3,在一定规模以后,数据的性能成为几乎是唯一的考量指标,这时候你就会发现具有复杂逻辑的存储过程,trigger 有多么令人绝望;

ORM应该采用,但目的是为了规范编码,防止低性能sql语句出现,而不是为了以后所谓的迁移,选择数据库平台是首要需要决定的事情,一旦开始使用99%不会考虑迁移。

#29楼[楼主] 2013-02-17 22:34南柯之石

@Michael.zh 受教了,也非常赞同。谢谢。
原文链接:https://www.f2er.com/nosql/204381.html

猜你在找的NoSQL相关文章