关于缓存命中
对于hashCode()而言,我发现了一个现象。
首先说明,我开启了二级缓存的。
<cache eviction="LRU" flushInterval="600000" size="512" readOnly="true"/>
查询代码:
List<Goods> list = sqlSession.selectList("goods.selectAll"); System.out.println("There are "+list.size()+" records in the results."); for (Goods goods : list) { System.out.println(goods.hashCode()+" : "+goods); }
结果:
859123506 : Goods{goods_id=2673, title='美赞臣蓝臻Enfinitas 2段婴儿奶粉900g单罐(6-12月龄) 荷兰进口', sub_title='臻选天生黄金组合乳铁蛋白、MFGM乳脂球膜、DHA,带来划时代*的科研结晶——旗舰新产品蓝臻,为万千妈妈带来配方奶粉的新体验', original_cost=436.0, current_price=436.0, discount=1.0, is_free_delivery=1, category_id=5}
97901029 : Goods{goods_id=2672, title='美赞臣蓝臻Enfinitas 1段婴儿奶粉900g单罐(0-12月龄) 荷兰进口', sub_title='臻选天生黄金组合乳铁蛋白、MFGM乳脂球膜、DHA,带来划时代*的科研结晶——旗舰新产品蓝臻,为万千妈妈带来配方奶粉的新体验', original_cost=442.0, current_price=442.0, discount=1.0, is_free_delivery=1, category_id=70}
809383315 : Goods{goods_id=2671, title='美赞臣蓝臻Enfinitas 1段婴儿奶粉400g单罐(0-12月龄) 荷兰进口', sub_title='臻选天生黄金组合乳铁蛋白、MFGM乳脂球膜、DHA,带来划时代*的科研结晶——旗舰新产品蓝臻,为万千妈妈带来配方奶粉的新体验', original_cost=199.0, current_price=199.0, discount=1.0, is_free_delivery=1, category_id=69}
1324514662 : Goods{goods_id=2670, title='美赞臣蓝臻Enfinitas 3段婴儿奶粉900g单罐(12-36月龄) 荷兰进口', sub_title='【16年7月生产,保质期18个月,请放心使用】', original_cost=398.0, current_price=398.0, discount=1.0, is_free_delivery=1, category_id=68}
908722588 : Goods{goods_id=2669, title='飞利浦新安怡羊毛脂乳头保护霜/膏 孕妇羊脂护理霜 乳头皲裂滋润保湿 SCF504/88', sub_title='防皲裂 澳洲羊毛脂 多效护理,不添加任何色素', original_cost=99.0, current_price=79.0, discount=0.79798, is_free_delivery=1, category_id=67}
496757837 : Goods{goods_id=2668, title='飞利浦新安怡英国进口原生单边电动吸奶器吸乳器吸力大SCF332/01', sub_title='英国原装进口,宽口径电动吸奶器,花瓣按摩垫设计。模仿宝宝吸吮,轻柔按摩,带来温热感受。临床验证,有助于刺激乳汁分泌。三种吸乳节奏,不必身体前倾,舒适坐姿更易泌乳。', original_cost=1799.0, current_price=1079.4, discount=0.6, is_free_delivery=1, category_id=66}
1548271808 : Goods{goods_id=2667, title='飞利浦AVENT/新安怡VIA储奶杯母乳储存杯组240毫升*5只 SCF639/05', sub_title='密封盖,便利性,安全环保 多种用途', original_cost=98.0, current_price=66.0, discount=0.673469, is_free_delivery=1, category_id=57}
17600354 : Goods{goods_id=2666, title='飞利浦新安怡 防溢乳垫 一次性干爽 舒适透气抛弃型SCF254/11', sub_title='安全放心的乳垫,多层强吸力 柔软干爽 防渗漏侧漏', original_cost=129.0, current_price=49.9, discount=0.386822, is_free_delivery=1, category_id=56}
1733056574 : Goods{goods_id=2665, title='飞利浦新安怡 婴儿温奶器 宝宝暖奶器热奶器 SCF355/01', sub_title='智能恒温,温奶温副食,一应俱全。', original_cost=299.0, current_price=169.0, discount=0.565217, is_free_delivery=1, category_id=55}
636959006 : Goods{goods_id=2664, title='飞利浦新安怡 经典宽口PES手动吸奶器花瓣按摩垫吸乳器SCF300/88', sub_title='拥有柔软的花瓣按摩垫;操控灵活,携带方便;不含双酚A,更加安全健康。', original_cost=399.0, current_price=239.4, discount=0.6, is_free_delivery=1, category_id=54}
现在我增加了一条记录:
insert into t_goods values (2674, "test goods", "test sub goods", 100, 50, 0.5, 43, 32662);
重新查询:
859123506 : Goods{goods_id=2674, title='test goods', sub_title='test sub goods', original_cost=100.0, current_price=50.0, discount=0.5, is_free_delivery=43, category_id=32662}
97901029 : Goods{goods_id=2673, title='美赞臣蓝臻Enfinitas 2段婴儿奶粉900g单罐(6-12月龄) 荷兰进口', sub_title='臻选天生黄金组合乳铁蛋白、MFGM乳脂球膜、DHA,带来划时代*的科研结晶——旗舰新产品蓝臻,为万千妈妈带来配方奶粉的新体验', original_cost=436.0, current_price=436.0, discount=1.0, is_free_delivery=1, category_id=5}
809383315 : Goods{goods_id=2672, title='美赞臣蓝臻Enfinitas 1段婴儿奶粉900g单罐(0-12月龄) 荷兰进口', sub_title='臻选天生黄金组合乳铁蛋白、MFGM乳脂球膜、DHA,带来划时代*的科研结晶——旗舰新产品蓝臻,为万千妈妈带来配方奶粉的新体验', original_cost=442.0, current_price=442.0, discount=1.0, is_free_delivery=1, category_id=70}
1324514662 : Goods{goods_id=2671, title='美赞臣蓝臻Enfinitas 1段婴儿奶粉400g单罐(0-12月龄) 荷兰进口', sub_title='臻选天生黄金组合乳铁蛋白、MFGM乳脂球膜、DHA,带来划时代*的科研结晶——旗舰新产品蓝臻,为万千妈妈带来配方奶粉的新体验', original_cost=199.0, current_price=199.0, discount=1.0, is_free_delivery=1, category_id=69}
908722588 : Goods{goods_id=2670, title='美赞臣蓝臻Enfinitas 3段婴儿奶粉900g单罐(12-36月龄) 荷兰进口', sub_title='【16年7月生产,保质期18个月,请放心使用】', original_cost=398.0, current_price=398.0, discount=1.0, is_free_delivery=1, category_id=68}
496757837 : Goods{goods_id=2669, title='飞利浦新安怡羊毛脂乳头保护霜/膏 孕妇羊脂护理霜 乳头皲裂滋润保湿 SCF504/88', sub_title='防皲裂 澳洲羊毛脂 多效护理,不添加任何色素', original_cost=99.0, current_price=79.0, discount=0.79798, is_free_delivery=1, category_id=67}
1548271808 : Goods{goods_id=2668, title='飞利浦新安怡英国进口原生单边电动吸奶器吸乳器吸力大SCF332/01', sub_title='英国原装进口,宽口径电动吸奶器,花瓣按摩垫设计。模仿宝宝吸吮,轻柔按摩,带来温热感受。临床验证,有助于刺激乳汁分泌。三种吸乳节奏,不必身体前倾,舒适坐姿更易泌乳。', original_cost=1799.0, current_price=1079.4, discount=0.6, is_free_delivery=1, category_id=66}
17600354 : Goods{goods_id=2667, title='飞利浦AVENT/新安怡VIA储奶杯母乳储存杯组240毫升*5只 SCF639/05', sub_title='密封盖,便利性,安全环保 多种用途', original_cost=98.0, current_price=66.0, discount=0.673469, is_free_delivery=1, category_id=57}
1733056574 : Goods{goods_id=2666, title='飞利浦新安怡 防溢乳垫 一次性干爽 舒适透气抛弃型SCF254/11', sub_title='安全放心的乳垫,多层强吸力 柔软干爽 防渗漏侧漏', original_cost=129.0, current_price=49.9, discount=0.386822, is_free_delivery=1, category_id=56}
636959006 : Goods{goods_id=2665, title='飞利浦新安怡 婴儿温奶器 宝宝暖奶器热奶器 SCF355/01', sub_title='智能恒温,温奶温副食,一应俱全。', original_cost=299.0, current_price=169.0, discount=0.565217, is_free_delivery=1, category_id=55}
看起来似乎应该理所当然,但是看看左边的HashCode就知道,对象是变了,但是HashCode没有变,甚至连重用的顺序都是一样的,所以HashCode并不能看出缓存是否生效了,因为它很可能只是被重新覆盖了而已。
再看另外一个例子,这个例子得到的结果和老师讲解的有出入。
SqlSession sqlSession = MyBatisUtils.openSession(true); // Connection connection = sqlSession.getConnection(); // PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM t_goods;"); // ResultSet resultSet = preparedStatement.executeQuery(); List<Goods> list = sqlSession.selectList("goods.selectAll"); System.out.println("There are "+list.size()+" records in the results."); for (Goods goods : list) { System.out.println(goods.hashCode()+" : "+goods); } MyBatisUtils.closeSession(sqlSession); sqlSession = MyBatisUtils.openSession(true); List<Goods> lists = sqlSession.selectList("goods.selectAll"); System.out.println("There are "+lists.size()+" records in the results."); for (Goods goods : lists) { System.out.println(goods.hashCode()+" : "+goods); } MyBatisUtils.closeSession(sqlSession);
这段代码中,sqlSession开启了自动事务,也就是说,执行完语句会自动commit,即便它只是查询语句,但看一下结果:
17:12:45.087 [main] DEBUG o.a.i.t.jdbc.JdbcTransaction - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@2dbe250d]
17:12:45.087 [main] DEBUG o.a.i.d.pooled.PooledDataSource - Returned connection 767436045 to pool.
17:12:45.087 [main] DEBUG goods - Cache Hit Ratio [goods]: 0.5 !!!!!!!!
There are 10 records in the results.
859123506 : Goods{goods_id=2674, title='test goods', sub_title='test sub goods', original_cost=100.0, current_price=50.0, discount=0.5, is_free_delivery=43, category_id=32662}
在标注感叹号的地方发现,Cache仍然命中了。
第一个问题来了:对于一个sqlSession,如果全程只有查询语句,即便commit(),是不是也不会清空缓存?
我试验了一下手动提交事务,发现还是能命中,暂且就认为这个问题的答案是肯定的吧。
接下来是第二个现象
如果我在开启二级缓存后,反而只在同一个sqlSession对象中进行两次相同查询,按道理说,这是一级缓存的范围,我现在开启了二级缓存,理应能够兼容一级缓存。
代码如下:
SqlSession sqlSession = MyBatisUtils.openSession(false); List<Goods> list = sqlSession.selectList("goods.selectAll"); System.out.println("There are "+list.size()+" records in the results."); for (Goods goods : list) { System.out.println(goods.hashCode()+" : "+goods); } sqlSession = MyBatisUtils.openSession(true); List<Goods> lists = sqlSession.selectList("goods.selectAll"); System.out.println("There are "+lists.size()+" records in the results."); for (Goods goods : lists) { System.out.println(goods.hashCode()+" : "+goods); } MyBatisUtils.closeSession(sqlSession);
事实当然是很失望,
17:22:48.388 [main] DEBUG org.apache.ibatis.logging.LogFactory - Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter.
17:22:48.409 [main] DEBUG o.a.i.d.pooled.PooledDataSource - PooledDataSource forcefully closed/removed all connections.
17:22:48.409 [main] DEBUG o.a.i.d.pooled.PooledDataSource - PooledDataSource forcefully closed/removed all connections.
17:22:48.409 [main] DEBUG o.a.i.d.pooled.PooledDataSource - PooledDataSource forcefully closed/removed all connections.
17:22:48.410 [main] DEBUG o.a.i.d.pooled.PooledDataSource - PooledDataSource forcefully closed/removed all connections.
17:22:48.486 [main] DEBUG goods - Cache Hit Ratio [goods]: 0.0
17:22:48.490 [main] DEBUG o.a.i.t.jdbc.JdbcTransaction - Opening JDBC Connection
17:22:48.946 [main] DEBUG o.a.i.d.pooled.PooledDataSource - Created connection 767436045.
17:22:48.947 [main] DEBUG o.a.i.t.jdbc.JdbcTransaction - Setting autocommit to false on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@2dbe250d]
17:22:48.950 [main] DEBUG goods.selectAll - ==> Preparing: SELECT * FROM t_goods ORDER BY goods_id DESC limit 10
17:22:48.990 [main] DEBUG goods.selectAll - ==> Parameters:
17:22:49.036 [main] DEBUG goods.selectAll - <== Total: 10
There are 10 records in the results.
859123506 : Goods{goods_id=2674, title='test goods', sub_title='test sub goods', original_cost=100.0, current_price=50.0, discount=0.5, is_free_delivery=43, category_id=32662}
97901029 : Goods{goods_id=2673, title='美赞臣蓝臻Enfinitas 2段婴儿奶粉900g单罐(6-12月龄) 荷兰进口', sub_title='臻选天生黄金组合乳铁蛋白、MFGM乳脂球膜、DHA,带来划时代*的科研结晶——旗舰新产品蓝臻,为万千妈妈带来配方奶粉的新体验', original_cost=436.0, current_price=436.0, discount=1.0, is_free_delivery=1, category_id=5}
809383315 : Goods{goods_id=2672, title='美赞臣蓝臻Enfinitas 1段婴儿奶粉900g单罐(0-12月龄) 荷兰进口', sub_title='臻选天生黄金组合乳铁蛋白、MFGM乳脂球膜、DHA,带来划时代*的科研结晶——旗舰新产品蓝臻,为万千妈妈带来配方奶粉的新体验', original_cost=442.0, current_price=442.0, discount=1.0, is_free_delivery=1, category_id=70}
1324514662 : Goods{goods_id=2671, title='美赞臣蓝臻Enfinitas 1段婴儿奶粉400g单罐(0-12月龄) 荷兰进口', sub_title='臻选天生黄金组合乳铁蛋白、MFGM乳脂球膜、DHA,带来划时代*的科研结晶——旗舰新产品蓝臻,为万千妈妈带来配方奶粉的新体验', original_cost=199.0, current_price=199.0, discount=1.0, is_free_delivery=1, category_id=69}
908722588 : Goods{goods_id=2670, title='美赞臣蓝臻Enfinitas 3段婴儿奶粉900g单罐(12-36月龄) 荷兰进口', sub_title='【16年7月生产,保质期18个月,请放心使用】', original_cost=398.0, current_price=398.0, discount=1.0, is_free_delivery=1, category_id=68}
496757837 : Goods{goods_id=2669, title='飞利浦新安怡羊毛脂乳头保护霜/膏 孕妇羊脂护理霜 乳头皲裂滋润保湿 SCF504/88', sub_title='防皲裂 澳洲羊毛脂 多效护理,不添加任何色素', original_cost=99.0, current_price=79.0, discount=0.79798, is_free_delivery=1, category_id=67}
1548271808 : Goods{goods_id=2668, title='飞利浦新安怡英国进口原生单边电动吸奶器吸乳器吸力大SCF332/01', sub_title='英国原装进口,宽口径电动吸奶器,花瓣按摩垫设计。模仿宝宝吸吮,轻柔按摩,带来温热感受。临床验证,有助于刺激乳汁分泌。三种吸乳节奏,不必身体前倾,舒适坐姿更易泌乳。', original_cost=1799.0, current_price=1079.4, discount=0.6, is_free_delivery=1, category_id=66}
17600354 : Goods{goods_id=2667, title='飞利浦AVENT/新安怡VIA储奶杯母乳储存杯组240毫升*5只 SCF639/05', sub_title='密封盖,便利性,安全环保 多种用途', original_cost=98.0, current_price=66.0, discount=0.673469, is_free_delivery=1, category_id=57}
1733056574 : Goods{goods_id=2666, title='飞利浦新安怡 防溢乳垫 一次性干爽 舒适透气抛弃型SCF254/11', sub_title='安全放心的乳垫,多层强吸力 柔软干爽 防渗漏侧漏', original_cost=129.0, current_price=49.9, discount=0.386822, is_free_delivery=1, category_id=56}
636959006 : Goods{goods_id=2665, title='飞利浦新安怡 婴儿温奶器 宝宝暖奶器热奶器 SCF355/01', sub_title='智能恒温,温奶温副食,一应俱全。', original_cost=299.0, current_price=169.0, discount=0.565217, is_free_delivery=1, category_id=55}
17:22:49.060 [main] DEBUG goods - Cache Hit Ratio [goods]: 0.0
17:22:49.060 [main] DEBUG o.a.i.t.jdbc.JdbcTransaction - Opening JDBC Connection
17:22:49.100 [main] DEBUG o.a.i.d.pooled.PooledDataSource - Created connection 1134202713.
17:22:49.100 [main] DEBUG goods.selectAll - ==> Preparing: SELECT * FROM t_goods ORDER BY goods_id DESC limit 10
17:22:49.101 [main] DEBUG goods.selectAll - ==> Parameters:
17:22:49.110 [main] DEBUG goods.selectAll - <== Total: 10
There are 10 records in the results.
1576277927 : Goods{goods_id=2674, title='test goods', sub_title='test sub goods', original_cost=100.0, current_price=50.0, discount=0.5, is_free_delivery=43, category_id=32662}
2080643905 : Goods{goods_id=2673, title='美赞臣蓝臻Enfinitas 2段婴儿奶粉900g单罐(6-12月龄) 荷兰进口', sub_title='臻选天生黄金组合乳铁蛋白、MFGM乳脂球膜、DHA,带来划时代*的科研结晶——旗舰新产品蓝臻,为万千妈妈带来配方奶粉的新体验', original_cost=436.0, current_price=436.0, discount=1.0, is_free_delivery=1, category_id=5}
2137642385 : Goods{goods_id=2672, title='美赞臣蓝臻Enfinitas 1段婴儿奶粉900g单罐(0-12月龄) 荷兰进口', sub_title='臻选天生黄金组合乳铁蛋白、MFGM乳脂球膜、DHA,带来划时代*的科研结晶——旗舰新产品蓝臻,为万千妈妈带来配方奶粉的新体验', original_cost=442.0, current_price=442.0, discount=1.0, is_free_delivery=1, category_id=70}
1627883152 : Goods{goods_id=2671, title='美赞臣蓝臻Enfinitas 1段婴儿奶粉400g单罐(0-12月龄) 荷兰进口', sub_title='臻选天生黄金组合乳铁蛋白、MFGM乳脂球膜、DHA,带来划时代*的科研结晶——旗舰新产品蓝臻,为万千妈妈带来配方奶粉的新体验', original_cost=199.0, current_price=199.0, discount=1.0, is_free_delivery=1, category_id=69}
481553464 : Goods{goods_id=2670, title='美赞臣蓝臻Enfinitas 3段婴儿奶粉900g单罐(12-36月龄) 荷兰进口', sub_title='【16年7月生产,保质期18个月,请放心使用】', original_cost=398.0, current_price=398.0, discount=1.0, is_free_delivery=1, category_id=68}
1076966140 : Goods{goods_id=2669, title='飞利浦新安怡羊毛脂乳头保护霜/膏 孕妇羊脂护理霜 乳头皲裂滋润保湿 SCF504/88', sub_title='防皲裂 澳洲羊毛脂 多效护理,不添加任何色素', original_cost=99.0, current_price=79.0, discount=0.79798, is_free_delivery=1, category_id=67}
1908781622 : Goods{goods_id=2668, title='飞利浦新安怡英国进口原生单边电动吸奶器吸乳器吸力大SCF332/01', sub_title='英国原装进口,宽口径电动吸奶器,花瓣按摩垫设计。模仿宝宝吸吮,轻柔按摩,带来温热感受。临床验证,有助于刺激乳汁分泌。三种吸乳节奏,不必身体前倾,舒适坐姿更易泌乳。', original_cost=1799.0, current_price=1079.4, discount=0.6, is_free_delivery=1, category_id=66}
749443480 : Goods{goods_id=2667, title='飞利浦AVENT/新安怡VIA储奶杯母乳储存杯组240毫升*5只 SCF639/05', sub_title='密封盖,便利性,安全环保 多种用途', original_cost=98.0, current_price=66.0, discount=0.673469, is_free_delivery=1, category_id=57}
796553753 : Goods{goods_id=2666, title='飞利浦新安怡 防溢乳垫 一次性干爽 舒适透气抛弃型SCF254/11', sub_title='安全放心的乳垫,多层强吸力 柔软干爽 防渗漏侧漏', original_cost=129.0, current_price=49.9, discount=0.386822, is_free_delivery=1, category_id=56}
1721045976 : Goods{goods_id=2665, title='飞利浦新安怡 婴儿温奶器 宝宝暖奶器热奶器 SCF355/01', sub_title='智能恒温,温奶温副食,一应俱全。', original_cost=299.0, current_price=169.0, discount=0.565217, is_free_delivery=1, category_id=55}
17:22:49.113 [main] DEBUG o.a.i.t.jdbc.JdbcTransaction - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@439a8f59]
17:22:49.113 [main] DEBUG o.a.i.d.pooled.PooledDataSource - Returned connection 1134202713 to pool.
它仍旧进行了两次查询,虽然HashCode是一样的,但日志中可以看出来,两次命中率都是0.0,并且,SQL语句出现了两次,这就是为什么我一开始要反驳HashCode来判断的原因。
于是问题二得出来:二级缓存并不会缓存同一次sqlSession中的数据,而是缓存这个sqlSession最后一次使用这个namespace的数据对吗?
那么,如果在同一次sqlSession中,也会多次查询同一的数据,需要加快查询速度,有办法吗?二级和一级是互斥的吗?
正在回答
同学你好,
现象:同一个sqlSession下,执行同一个select语句时,Cache Hit Ratio [goods]: 0.0,二级缓存的命中率为0。只会执行一次SQL。
原因:这涉及到二级缓存的缓存什么时候存入。只有当当前的sqlSession.close()时,该sqlSession的数据才会存入二级缓存。在同一sqlSession下时,肯定没有执行.close()关闭sqlSession,自然也就没有存入二级缓存。第二次执行却没有重新发送sql语句,是因为第二次调用的是一级缓存中的数据,这两次查询使用的是同一个sqlSession对象。
如果想让二级缓存命中率不为0,需要先开启一个sqlSession,执行一个sql语句,然后关闭该sqlSession,然后在创建一个新的sqlSession,执行相同的sql语句,这时,二级缓存才会命中。
如果我的回答解决了你的疑惑,请采纳!祝学习愉快~
- 参与学习 人
- 提交作业 9393 份
- 解答问题 16556 个
综合就业常年第一,编程排行常年霸榜,无需脱产即可学习,北上广深月薪过万 无论你是未就业的学生还是想转行的在职人员,不需要基础,只要你有梦想,想高薪
了解课程
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星