条件:数据库有两张表:news和category,新闻10000 条数据,分类7条数据 ,新闻类(News)里包含一个分类(Category) 1) 不使用缓存,n+1 方式获取新闻对应的分类。读取全部(10000 条符合条件) 需11.38 秒左右。
| 20 | 40 | 60 | 80 | 100 |
ibatis 逻辑分页 | 0.45 | 0.47 | 0.52 | 0.55 | 0.57 |
数据库物理分页 | 0.15 | 0.19 | 0.22 | 0.27 | 0.30 |
2) 对分类使用缓存,新闻不使用缓存,n+1 方式读取新闻对应分类。读取全部(10000 条符合条件) 需0.89 秒
| 20 | 40 | 60 | 80 | 100 |
ibatis 逻辑分页 | 0.43 | 0.44 | 0.44 | 0.44 | 0.45 |
数据库物理分页 | 0.11 | 0.11 | 0.12 | 0.12 | 0.13 |
3) 新闻使用缓存(size:150) ,n+1 方式读取新闻对应分类。读取全部(10000 条符合条件) 需0.0007 秒,但很消耗内存。它是把所有的内容读出,作为缓存的一项,后面的查询都能从缓存命中,几乎不用时间。
备注: 1. 第一次使用SqlMapClient 时,ibatis 会做一些初始化工作,所以应该取第二次后读取数据库所用的时间为测试结果
2. ibatis 的把一次查询得到的结果作为缓存的“一项”,缓存size 的单位就是这个项。一个category List 是一项,单个的一个Category 也是一项,并且它们可以同时存在的,相互间没有任何关系。从缓存中取数据的条件是:当前查询和缓存项对应的查询语句相同,并且参数也相同。
从这个测试可以看出,对1对1关联,如果被关联的一方数据量不大,使用缓存可以解决n+1的效率问题。当然,也可以使用联合查询,我更倾向前者,方式优雅,效率不低,而且内存消耗也比后者低。另外,ibatis的分页效果不太好,除非数据量很小,否则不要使用,才10000条数据,速度几乎比物理分页慢了3倍。数据量增大,会慢的更厉害。慎用列表的缓存,尤其是多条件查询生成的列表。如果各种条件组合有n中情况,如果这个n小于size,ibatis几乎会缓存整个数据库。