锁定老帖子 主题:关系模型和对象模型的究竟匹配还是不匹配?
精华帖 (12) :: 良好帖 (11) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-01-03
看看这样的需求,三五百万行的表有三四张,一对多,多对多的关系都有,列多的有七八十,少的也有十来列,所有表的80%字段都要查(还有好多张十来万的小子表,暂时先忽略掉不讨论).而且是关联查询.有没有人搞过这类的东西?性能不好可把我逼疯了.现在的查询选项的表单只是录入框就有一两百个,查询哪个表客户自己选.(我靠,都想培训客户去写sql了,呵呵)目前做了一个sql语句的生成器,根据表单的命名自动产生查询条件和表关联.功能倒是实现了,发现性能有问题.物化视图稍微能缓解一下,刷新恐怕有点问题.指标不治本.
我现在考虑适当的冗余,减少联接,也可能没有使用查询缓存的缘故.但是由于项目是在别人开发过的旧系统升级新功能,所以只敢用jdbc.这就是目前的情况.不知道像这样的系统,这种需求使用orm+Hql能行吗?如果开启缓存功能.数据有可能是另外的系统更新.我的缓存岂不都废了.先不考虑更新问题.即便开了查询缓存性能又能提高多少? 劳驾各位给看看,有没有好办法?指点一二.谢谢 |
|
返回顶楼 | |
发表时间:2008-01-04
javaeye是个网站,大家关注的地方的有很多重叠的地方,
例如首页,每个版块的第一页内容,再加上同时在人多 使用orm缓存效果很明显, 但是有些情况,本身同时在线的人数就很少,再加上人人关注的地方都不同,缓存效果肯定不明显,要求在几秒内响应,单靠符合3范式orm缓存,我觉得不现实 |
|
返回顶楼 | |
发表时间:2008-01-06
关系数据库模型在理论上主要解决的是消除数据冗余的问题。关系模型的数学基础是所谓的集合论,而集合的基本含义正是一组具有某种原子性的互不相同的元素。面向对象技术是对相关性进行局域化的一种手段(相关的数据和操作聚集到同一对象名义下),在这一局域化过程中,相同的元素被识别出来,成为独立的对象。从某种意义上说,关系模型与对象模型是殊途同归的过程,是从不同侧面对同一事物的反映。关系模型中,我们关注的重点是元素组成的集合,允许的连接关系定义在集合之上。而在对象模型中,我们关注的首先是横向关联的实体,实体之间具有稳定的联系。在概念层面上,从对象模型映射到一种关系存储模型只是一个分组问题。为了断开实体之间的直接联系,关系模型创造了一个id字段,而对象模型并不是需要显式id的。在关系模型中,关联并不是通过某种存在的结构来表达的(一个实体持有另一个实体的指针,拥有直接联系),而是将直接关联问题弱化为某种计算过程,我们必须检查id的值(不是某种直接的存在性),通过某种运算过程才能重新发现数据之间的关联。
通过id(伴随一个匹配计算过程)来进行间接关联对于保证模型的一致性是非常关键的。在ORM中恢复了对象的强关联其实会造成很多潜在的复杂性。例如为了维护对象层面结构的一致性,在更新父子关系的时候,我们需要同时调用 child.setParent(parent); parent.getChildren().remove(child); 当关联结构更加复杂的时候,这里所需要的维护工作是随之增加的。不过,在ORM中,对象的形态是暂时性的。在ORM的一次session的操作过程中,对于对象状态的修改可以是不一致的。例如我们可以只调用child.setParent(parent); 而不需要同时 parent.getChilren().remove(child); 只要我们在此次session操作中,不需要同时用到parent.getChildren(). 这种关联的暂时性对于很多ORM应用来说是必不可少的。 对象模型中可以直接表达的结构关系比关系模型要丰富一些,例如继承关系,many-to-many, one-to-list等。但是所有这些都不是真正本质性的差异。抛弃概念诠释,基类与众多派生类之间的关系基本上可以等价于一组one-to-one关系。而当关联对象本身的重要性凸现出来的时候,当我们无法把它约化为对象上的一些附属特性的时候(例如数组的下标),我们必然要建立相应的关联对象,而这正对应于关系模型中的中间关联表。中间关联表上增加额外的字段是一个自然的扩展过程,而对象模型上做这样的扩充往往表现为形态上的重大的不兼容的变化,例如从getManyToManyEntity() -> getToManyRelation(), 这实际上意味着这里的对象形式是偶然的,简化的。 在原始的关系数据库模型中,所有的表之间的地位是平等的,所有字段之间的地位是平等的(主键和外键在参与数据关联时和其他字段的处理方式一致)。这种概念上的均一性和普遍性往往被认为是理论的优美之处。但是现实世界是复杂的,发展的方向就是逐步识别出不同之处,并找出自然的表达形式将这些不同表达出来。均匀的关系模型是对称性最高的,最简化的模型。在面对物理约束时,它隐含的假设是集合之间很少发生相互作用,单表(表单到数据表之间的映射)和主从表是最广泛的情况。试着想象一下关系模型,在思维中一般我们只能看到两个数据表,当考虑到多个表的时候,因为这些表之间没有明确的可区分性,因此它们的意象是模糊的。只有明确意识到主键,外键,主表,从表,字典表,事实表,纬度表这些不同的概念的时候,当对称性出现破缺的时候,我们思维中的模型才能够丰富化起来。 关系模型理论应用到数据库具体应用中时,并不需要死守关系范式教条,它们只是描述了某种极端化的对唯一性的追求。面对具体应用的时候,理论本身也在不断丰富化。我并不把现实应用中必然需要增加冗余字段看作是关系理论失效的结果。从关系完全分解,到关系完全不分解之间,我们可以建立大量的模型。建立冗余字段的时候,我们存在着大量可能的选择,到底哪一种选择是最优的,理论方面仍然可以给我们以具体的指导。理论在各种不同纯化程度的关系模型中都可以给我们以直观的建议。数据仓库理论中建立的snowflake模式和star模式,强调了针对主题域的允许部分冗余的关系分解。这里实际上是强调了表之间的不同性。不再是所有的表都处于同一地位。Fact Table和Dimension Table之间的区别被识别出来,并被明确处理。在我看来,这是原始关系模型的一种自然发展,它也是关系模型理论的一部分。理论不应该是单一的,而是提供一个模型级列,在不同的复杂性层次上,我们可以根据理论的指导选择具体的实现模型。 关于ORM http://canonical.iteye.com/blog/111500 关系模型中的所谓关系是在使用时刻才定义的,所有建立关系的方式在某种程度上都是等价的,也是外在的。而在ORM中主键与外键之间的关联被独立出来,成为模型内置的部分。这在很多时候简化了数据查询的结构构造过程。 在ORM中主键因为缓存的存在而显出与其他字段的区别。ORM的使用使得数据存储的分解策略得到扩充。并不是所有的表的更新频度都是一致的,而且表中的数据量大小也不同。字典表一般较小,而且很少更新,可以安全的复制。在整个数据存储框架中,ORM作为独立的技术元素参与数据存储过程,通过主键提供缓存服务,产生了新的数据分布模型,提供了新的性能优化契机。 |
|
返回顶楼 | |
发表时间:2008-01-20
对象还是关系? 没有绝对的好坏,这要从具体的设计方、需求方和任务本身谈起。
我以前是学机械的,就拿机械作比方吧,对象模型就象比三维立体建模,是一个有机的整体,关系模型就象是平面三视图,是对这个整体从各个视角或者截面进行的描述。三维建模是没有冗余的,平面三视图理论上是可以做到没有冗余,但事实上很少有人能画出没有冗余信息的三视图。通常,平面图是唯一用来进行沟通的标准工程语言,但也有个别例外是,有些高级机床可以直接读取三维模型的进行加工的。 有一天,一个工厂对你说,我需要这么这么一个机器, 给我设计一下吧.... 于是,我们就来分析: 从设计者角度: 如果我自已是个老工程师,不会SolidWork,Pro-E之类高级三维工具,只会图二维图,哪毫无疑问,只能给出平面图了。 (只懂关系模型) 如果我SolidWork之类工具用的很熟,很讨厌一张一张的图二维图,哪肯定是先三维建模, 然后再由三维建模导出平面图。(只懂对象建模) 从工厂的角度: 如果这个工厂全是些高级数控中心,只接收三维数据,哪没办法,只能要求设计者采用立体建模了。 (甲方能理解你的对象模型,需求变更时能直接在这个模型层次上展开讨论) 如果工厂里全是些老机床,只会看平面图的工人,即可以直接给平面图,也可以三维建模后再转成平面图(甲方只理解关系模型,关系模型是双方交流的语言) 从任务本身: 如果机器是由常见的铸件螺栓螺母标准件组成,用立体建模肯定是最快了.(对象模型容易归纳出) 如果要设计的不是机器,而是一件新款的裙子,这时只会用solidwork的头疼了,因为solidwork很难画出个三维的裙子。 (业务本身不适用或没有必要对象建模) 总之要考虑的因素太多了,以上都是极端的情况,还有介于中间的,总之具体的情况具体对待,空泛的谈谁好谈坏是没有意义的。 |
|
返回顶楼 | |
发表时间:2008-01-21
本人以前自学数据库的时候对三大范式印象太深,以至于工作中大部分是以DB建模。而遵循范式设计出来的模型基本上是符合OO的。
实践中,以此模型为基础的系统性能是相当好的(大家要考虑到外键索引、尤其是数字型索引所带来的巨大优势),根本不是某些所谓DBA想像中的过不了日子。相反,那些个高冗余度的系统,才是难以维护、一动百摇。 |
|
返回顶楼 | |
发表时间:2008-01-23
http://www.iteye.com/topic/25649
一年前的老文. 赫赫 |
|
返回顶楼 | |
发表时间:2008-01-27
CREATE TABLE user (
user_id int(11) NOT NULL AUTO_INCREMENT, name varchar(16) NOT NULL, pass char(40) NOT NULL, PRIMARY KEY (user_id) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; CREATE TABLE note ( note_id int(11) NOT NULL AUTO_INCREMENT, user_id int(11) NOT NULL, title varchar(16) NOT NULL, content text NOT NULL, PRIMARY KEY (note_id), KEY user_id (user_id) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; 以上两各表各1000万条记录: mysql> SELECT COUNT(*) FROM user; +----------+ | COUNT(*) | +----------+ | 10000000 | +----------+ 1 row in set (0.00 sec) mysql> SELECT COUNT(*) FROM note; +----------+ | COUNT(*) | +----------+ | 10000000 | +----------+ 1 row in set (0.00 sec) mysql> 只要索引设置得好,性能根本不是问题: mysql> EXPLAIN SELECT * FROM user INNER JOIN note ON user.user_id = note.user_id WHERE user.user_id = 1234567; +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ | 1 | SIMPLE | user | const | PRIMARY | PRIMARY | 4 | const | 1 | | | 1 | SIMPLE | note | ref | user_id | user_id | 4 | const | 1 | | +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ 2 rows in set (0.00 sec) mysql> EXPLAIN SELECT * FROM note INNER JOIN user ON note.user_id = user.user_id WHERE note.user_id = 1234567; +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ | 1 | SIMPLE | user | const | PRIMARY | PRIMARY | 4 | const | 1 | | | 1 | SIMPLE | note | ref | user_id | user_id | 4 | const | 1 | | +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+ 2 rows in set (0.00 sec) mysql> 所以不要武断地认为大表的关联是性能杀手。 |
|
返回顶楼 | |
发表时间:2008-04-12
我觉得对于软件专业科班出身的人而言,此帖应该属于入门帖吧,尤其是实体关系建模与对象建模的历史渊源,很多软件工程的书都会提及,并且Robbin号称精通Hibernate,怎么会到2007年末才接触到三大范式这种在关系数据库理论中最为基础的知识呢?
|
|
返回顶楼 | |
发表时间:2008-04-13
在做项目的过程中,我找到了一点不匹配的地方,那就是对象是数据与操作的集合,对象可以只有操作而没有数据,而数据表是数据的集合,只有在有数据的情况下才有存在的意义。
面向对象的目标应该是为了避免数据和操作的冗余,而数据库范式的目标仅仅是避免数据的冗余。 比如:Resource <- SpiritResource, Resource <- EntityResource, SpiritResource <- User, Organization, OrganizationalUnit... EntityResource <- WebSite, Column... SpiritResource和EntityResource是抽象类,且不含有任何属性,它们的存在是为了避免一些代码的冗余,这样,它们无法和数据表对应起来,因为,只有一个id列的表没有什么存在的意义。 |
|
返回顶楼 | |
发表时间:2008-04-13
diogin 写道 只要索引设置得好,性能根本不是问题: mysql> EXPLAIN SELECT * FROM user INNER JOIN note ON user.user_id = note.user_id WHERE user.user_id = 1234567; 2 rows in set (0.00 sec) mysql> EXPLAIN SELECT * FROM note INNER JOIN user ON note.user_id = user.user_id WHERE note.user_id = 1234567; 2 rows in set (0.00 sec) mysql> 所以不要武断地认为大表的关联是性能杀手。 用例太简单了,where 条件用的是唯一索引,这样关联下来肯定快。我说一个复杂一点但是很普遍的用例,你title like一个'%xxxx%',再order by title, 然后分一个页,试试。 |
|
返回顶楼 | |