2011-07-27 25 views
1

我有这样一个相当简单的数据模型:Ehcache - 为什么这些条目如此之大?

class MyParent { 
    // 7 fields here, some numeric, some String, not longer than 50 chars total 
    Set<MyChild> children; 
} 

class MyChild { 
    int ownerId; 
    // 3 more fields, numeric or dates 
} 

MyParentMyChildMyParent.children都缓存与read-only

我有40,000个MyParent的实例和MyChild的100,000个实例。这会在缓存中产生180,000个条目(如果添加40,000个MyParent.children)。我想缓存一切,按ownerId分组。不想推倒重来,我想用查询缓存,如:

Query query = session 
       .createQuery(
         "select distinct p from MyParent p join fetch p.children c where c.ownerId = :ownerId"); 
query.setParameter("ownerId", ownerId); 
query.setCacheable(true); 
query.setCacheRegion("MyRegion"); 
query.list(); 

对于ownerId所有1500倍的值。

缓存工作,但我注意到它是巨大的!用Ehcache.calculateInMemorySize()来衡量,平均每个条目超过一千字节大。为了缓存〜180,000个条目,我需要超过200 MB。考虑到参赛作品本身要小得多,那就太过分了。

开销从哪里来,我该如何减少它?

回答

2

我不确定从问题中可以看出你使用什么缓存来做数学运算,但让我以MyParent类为例。考虑到你对类的解释,在启用了compressedOops的64位虚拟机上,MyParent实例将在堆中略低于500字节。这是没有集合,我会解释为什么后面(否则将是另一个128字节顶部)。缓存还需要保存该条目的密钥,该条目添加到计算中...

Hibernate不直接使用主键来存储它在缓存中存储的内容,而是CacheKey条目。该实例包含值表示的实体的pk以及四个其他字段:type,Hibernate类型映射; entityOrRoleName,实体或集合 - 角色名称; tenantId,与此数据关联的租户标识符;最后是pk的hashCode(参见org.hibernate.type.get.getHashCode)。

现在可悲的是,它并没有在这里结束,该条目的值不是MyParent实例,而是一个CacheEntry实例。这一次,除了更多的元数据(subClass,实体的名称,默认为FQCN; lazyPropertiesAreUnfetched,布尔值;以及实体外的optimisitc锁定值)之外,该实例仍然不包含MyParent实例,而是反汇编代表它。此表示形式是实体的状态(所有属性)的数组。

我想用这个信息来说,你的hibernate缓存“估计”的大小会更有意义。我想强调,这些只是估计,如果我没有记错它是如何计算的,它可能略高于现实。确实,CacheKey中的一些信息可能应该以不同的方式解释。从Ehcache 2.5开始,您将能够在缓存上启用基于内存的优化(甚至在CacheManager级别)。完成后,高速缓存条目将被精确测量,并且calculateInMemorySize()将为您提供实际测量的高速缓存大小。

您现在可以从ehcache.org下载2.5版的测试版。还要注意,当在缓存中使用基于字节的大小时,调整引擎将在Hibernate缓存类型中的缓存条目中考虑这些共享实例。你可以阅读更多的道路上这一切都在这里工作:http://ehcache.org/documentation/configuration.html#Memory_Based_Cache_Sizing_Ehcache_2.5_and_higher

希望帮助你更有意义了这一切...... 亚历

相关问题