欢迎访问我的个人网站==》 jiashubing.cn

数据库的设计问题-分表的好处

问题:

  注意:这里说的不是【分库分表】里的分表,而是将一个大表的某些字段拆分到别的表里

  一个论坛系统,有两个页面,一个是帖子基本信息列表页面,一个是展示某个帖子的详细内容页面。现在可以在一张表A中,同时存储帖子的基本信息和详细内容。

  1、后来发现,帖子的数量多了,帖子列表页面的加载速度明显慢了很多。这是为什么?
  2、是不是说将表A拆分成两张一对一关联的表,一张表只放基本信息,用来加载帖子列表页面;另一张表只放详细内容,在查询的时候也只是查单张表,不会影响效率?

 

解决过程:

  想了想,搜了搜,才发现自己真的是二了。

  1、我只是用到了某些基本信息字段(比如标题等),但是查询的时候却查了所有的字段,其中单content列的数据就十分庞大,速度自然就慢了。所以查询的字段越多,查询的速度越慢
  下图,可以看到两条sql语句的查询时间:

  

  2、可以将表拆成一对一关联的表,但这是表设计方面的问题了,现在数据已经很多了,调整数据结构太复杂了。

    那么根据“hibernate查询部分字段值,比查询所有字段值效率高”的原理,如上图那样,查询的时候,只查部分数据,是不是也可以呢?
    兴致勃勃得尝试了以后,才发现自己太天真了
    以下是我更改后的查询方法:

//String hql="from Topic where top=1";
String hql="select id,modifyTime,publishTime,title,good,top,replySum,remark,firstimg,section,user from Topic where top=1");
Query query = em.createQuery(hql);
List<Topic> result = query.getResultList();

 

  结果报错:java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to forum.po.Topic
  类型转换出错。调试发现,只有部分字段数据根本不能转换成真正的对象,最后页面调用的时候,自然会出错。

  后来研究“hibernate是如何把查询结果转换为对象的”,感觉只取查询结果中的一部分值到对象里并不容易。

  

  最后还是更改了数据库和实体类:
    将帖子的基本信息,和帖子的详细内容分成两张表A、B存储。
    刚开始使用@OneToOne关联映射,懒加载。仍然报错,懒加载没有加载到。
    后来,我就决定不使用OneToOne了,而是手动定义详细内容表B中的一列为基本信息表A中的主键。只是增加、删除的时候需要多考虑一张表。


  结果:页面加载速度也快了,问题解决。

  分析:使用@OneToOne关联,就必须定义外键了,在查询的时候懒加载,可能加载不到外键的数据,所以页面中也获取不到

    后来分成的A、B两张表,并没有定义外键关联,只是有B表的一列表示A表的主键。这样的话,两张表之间是完全没有关联的,可以单独查询。麻烦的是在增删的时候,要在代码中控制一起创建(A先B后),或者一起删除(先后无所谓)。

 

  原创文章,欢迎转载,转载请注明出处!

 

posted @ 2017-04-18 17:45  贾树丙  阅读(3970)  评论(0编辑  收藏  举报