锁定老帖子 主题:Hibernate的优化:Cache
该帖已经被评为新手帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-07-29
想问下楼主, Hibernate在获取id的同时, 是否也获取了版本号, 以便比较Cache内容是否过时?
这个问题一直想搞清楚, 更想知道它是否支持JTA事务, 不过本人懒惰。。。 拜服楼主的探索精神。 |
|
返回顶楼 | |
发表时间:2010-07-29
Hyphoon 写道 想问下楼主, Hibernate在获取id的同时, 是否也获取了版本号, 以便比较Cache内容是否过时?
这个问题一直想搞清楚, 更想知道它是否支持JTA事务, 不过本人懒惰。。。 拜服楼主的探索精神。 cache的内容是否过期?cache内容过期是memcached维护的,lru算法失效了就不存在了。 支持jta,以前曾经用过,这个项目里没有用到。 |
|
返回顶楼 | |
发表时间:2010-07-31
具体,你从缓存里取数据和从数据库了取数据的代码修改是怎么样的? 我是想问你是怎么修改查询数据逻辑的? 能给点代码,大伙看看吗? |
|
返回顶楼 | |
发表时间:2010-08-01
XTU_xiaoxin 写道 具体,你从缓存里取数据和从数据库了取数据的代码修改是怎么样的? 我是想问你是怎么修改查询数据逻辑的? 能给点代码,大伙看看吗? 我想,你没搞明白我的意思。我没有修改hibernate的代码,是修改自己代码里的逻辑。利用hibernate查询的时候,只差id,然后通过id和,hibernate存储的key的格式去cache里拼装对象。如果cache中没有的,再通过id和hql去数据库查询,让hibernate自动的放入cache,下次查询cache中就存在了。 |
|
返回顶楼 | |
发表时间:2010-08-01
问题虽然解决了 但是方法不是特别优雅
还不然直接抛弃hibernate 二级缓存自己封装一套更痛快 =========================================== 另外如果采用opensessioninview的话,一个请求只打开一个jdbc connction 把连接池开大点 比如1000 也没啥关系 你的并发应该也大不过1000吧 |
|
返回顶楼 | |
发表时间:2010-08-01
xly_971223 写道 问题虽然解决了 但是方法不是特别优雅
还不然直接抛弃hibernate 二级缓存自己封装一套更痛快 =========================================== 另外如果采用opensessioninview的话,一个请求只打开一个jdbc connction 把连接池开大点 比如1000 也没啥关系 你的并发应该也大不过1000吧 呵呵,难道一个系统中只有这一个请求吗?如果只是一个查询就消耗那么多数据库连接,那还有update,insert等等操作呢。另外,opensessioninview的前提是 lazy 加载,lazy 会出现另外一个问题cache连接数的问题,改天会写篇博文描述一下。 |
|
返回顶楼 | |
发表时间:2010-08-01
my_corner 写道 xuzhfa123 写道 你讲得和hibernate做的一样,你查id不需要获取连接吗 我查id需要获取连接(这里还可以优化,可以缓存id list,而且已经实现了,是为了讲查询维持连接cache的机制把id list这个地方忽略掉了)。 我查询id获得连接了,查询结束连接就释放了。我并没有保持着数据库连接去cache里面查找东西。比如查询1000个id,如果1000个id对应的数据在缓存里都有,我的链接时间,只是从数据库中把id取回来。而hibernate是的链接,是要等这1000个id对应的数据从cache里全都查询到,拼装好才释放掉的。 参见log4j的日志,谢谢! 首先声明,我刚开始用hibernate。 文章看了第一遍,没明白lz的意思,再看第二遍,还是没明白,看到这个回复算是明白了。 |
|
返回顶楼 | |
发表时间:2010-08-01
aimer311 写道 my_corner 写道 xuzhfa123 写道 你讲得和hibernate做的一样,你查id不需要获取连接吗 我查id需要获取连接(这里还可以优化,可以缓存id list,而且已经实现了,是为了讲查询维持连接cache的机制把id list这个地方忽略掉了)。 我查询id获得连接了,查询结束连接就释放了。我并没有保持着数据库连接去cache里面查找东西。比如查询1000个id,如果1000个id对应的数据在缓存里都有,我的链接时间,只是从数据库中把id取回来。而hibernate是的链接,是要等这1000个id对应的数据从cache里全都查询到,拼装好才释放掉的。 参见log4j的日志,谢谢! 首先声明,我刚开始用hibernate。 文章看了第一遍,没明白lz的意思,再看第二遍,还是没明白,看到这个回复算是明白了。 你意思是我描述有问题? |
|
返回顶楼 | |
发表时间:2010-08-01
我想是的,你没有将表述的关键点比较明显的表述出来。我理解没错的话,你的观点是:
hibernate的执行过程是这样: 打开连接,取得id,到cache去找,若找到,则取cache,没有找到,执行查询,关闭连接。 而你修改后的执行过程是这样: 打开连接,打开事务,取得id,关闭连接,到cache去找,若找到,则取cache,没有找到,执行查询。 你没有强调问题所在,所以我们(至少包括xuzhfa123 )看得云里雾里 |
|
返回顶楼 | |
发表时间:2010-08-02
my_corner 写道 xuzhfa123 写道 你讲得和hibernate做的一样,你查id不需要获取连接吗 我查id需要获取连接(这里还可以优化,可以缓存id list,而且已经实现了,是为了讲查询维持连接cache的机制把id list这个地方忽略掉了)。 我查询id获得连接了,查询结束连接就释放了。我并没有保持着数据库连接去cache里面查找东西。比如查询1000个id,如果1000个id对应的数据在缓存里都有,我的链接时间,只是从数据库中把id取回来。而hibernate是的链接,是要等这1000个id对应的数据从cache里全都查询到,拼装好才释放掉的。 参见log4j的日志,谢谢! 疑问:当你查询ID获取连接,查询结束连接释放,期间不查找CACHE?如果不查找CACHE,你释放连接,如果CACHE中没有,是否要再次创建连接? 感觉有点自相矛盾的意思,还是我由于半夜看文字出现的问题,GOD。。。 LZ的想法是没错,我写过一个记录google经纬度的程序,也是采用类似的方法,不过好像都是采用这样的方法吧 取得的记录,先去cache 中查找,有则返回,没有则查找数据库记录,然后关闭连接,大多都这样 取1000个id,和取1000个id后,去CACHE中查所对应的数据从cache中查询到,一个是id是从数据库中查找ID,一个是从缓存中查找记录 差距就有你想的那么大吗?这其中的时间会差多少?这可是从缓存拿数据哦,况且最后都会进行数据库的关闭操作 如果你要缓存ID LIST,那你何不key = id & value = ID对应的对象信息,这不一样? 直接ID --> VALUE的形式即可 ---- Hibernate的二级缓存和你文中说的一样,下面引用LZ的文字 “通过对log4j日志分析发现,hibernate每次先get一个jdbcConnection,从数据库查询出一堆id,然后去cache查找对象。如果数据在cache中存在则取出,并提交事务释放连接;如果cache中没有,则查询数据库并将结果保存的cache中,提交事务释放连接。” 通过文字得到结论:1、建立连接获取ID,然后根据ID查找CACHE,有责获得数据返回关闭连接,没有,责查找数据,保存CACHE,关闭连接返回。 引用LZ第二段文字 ”理想的情况是,cache中有的直接去cache中查找,cache中没有的去db查询然后放入cache中。将代码做些修改,只从数据库中查到id,根据id去cache中查找相应的数据,cache中没有的数据则调用hibernate的查询方法“ 通过文字得到结论:1、重点(只从数据库中查到ID,根据ID去CACHE中查找相应的数据) 还是要先建立连接去查找ID,然后对应的数据去保存CACHE,只是关闭连接的时间不同(还是上面的疑问,如果ID所对应的CACHE不存在,咋做,是否要再次建立连接?LZ采用的框架,我的程序中就加入缓存框架加逻辑,可以很容易的控制) Hibernate默认采用的第三方缓存Oscache,亦可设置缓存时间(至于其他memcache就不晓得了)源码阅读过一部分,采用Properties 以key value的形式缓存对象 还有一点疑问:LS有说,如果程序关闭,memcache有缓存时间,那在程序关闭的时候,这个缓存时间还有效么?我理解是没有作用的,只有在缓存到硬盘的时候,才可以再重启的服务器的时候从缓存硬盘中读取数据,再次加载到缓存中,以内存+硬盘的缓存形式来缓存数据,这样的效果最佳 而memcache直接是内存缓存,不可能在重启的时候以判断是否超过缓存时间来断定数据是否还在缓存中保存,因为此时缓存在重启的时候已经清空了 至于楼主曾经讲述到memcache,就不知道了,还没时间来了解,希望下次有机会和LZ沟通 |
|
返回顶楼 | |