我们公司的开发框架有个叫做dict的基础服务,用于把数据库中保存的状态码“翻译”成用于显示的状态。
比如:0-有效,1-过期,2-失效这样的。
而数据库中有两张表专门用于保存这种转换关系
我看到公司的实现是在tomcat启动时就把dict表中所有数据全部读出,然后缓存成全局的键值对。
但是我在思考一个问题,由于dict中的记录有至少一半是千年都不一定用得上的,所以如果写个类用于缓存dict键值对,调用get时检查记录是否存在,如果不存在就查数据库取得之后返回
这样就能 只缓存用到过的数据了,但是这样却 导致查库的次数增加了(因为每次只取一条记录)
所以我很纠结哪种实现性能更好些呢?希望各位赐教
15 个解决方案
#1
如果有一半多的一般都用不到还是按需取,缓存常用的比较好吧
#2
取出常用的部分放在缓存中,并对数据库按照常用和不常用做一下索引排序,查找时先找缓存,找不到的时候在从数据库中按照不常用->常用找
#3
要么就做二级缓存,一级常用,二级不常用也可以,取决于你的数据量和不常用数据的占比
#4
我也是这样做的
#5
关键是“常用”与“不常用”本身就是个模糊而无法界定的概念,某个功能客户用得多自然对应的dict也查找得多。这个不能主观推断。然而,如果按以上诸君说的,那岂不是还得统计查找量,得不偿失,本来就是为了减少数据库访问才缓存的。
我的意思也就是“常用”的和“不常用”的是完全混在一起的,我们无法把它们单独分拣出来,甚至连按常用的程度排序都不能。所以我们只能一视同仁的对待这些数据。在这样的情况下,是一次性全部进行缓存还是按需取出来缓存好些呢?前者可能浪费一些内存资源,后者可能使数据库访问次数增加。
我的意思也就是“常用”的和“不常用”的是完全混在一起的,我们无法把它们单独分拣出来,甚至连按常用的程度排序都不能。所以我们只能一视同仁的对待这些数据。在这样的情况下,是一次性全部进行缓存还是按需取出来缓存好些呢?前者可能浪费一些内存资源,后者可能使数据库访问次数增加。
#6
常用的大约占百分之四五十吧,总共也就几千条记录。
#7
除了楼上的办法外,可以参考ibatis式的缓存方式。
ibatis的缓存设计是以SQL的hash值为KEY的,每个SQL第一次查询后结果会形成单独的缓存,SQL相同缓存就相同,SQL不同就算是同一张表也会读不同的缓存。
这种设计方式是典型的缓存冗余+按需获取,连缓存内的查询都不需要了,不过缺点也比较明显,为了防止缓存膨胀的太厉害,需要设定缓存上限和替换策略。
ibatis的缓存设计是以SQL的hash值为KEY的,每个SQL第一次查询后结果会形成单独的缓存,SQL相同缓存就相同,SQL不同就算是同一张表也会读不同的缓存。
这种设计方式是典型的缓存冗余+按需获取,连缓存内的查询都不需要了,不过缺点也比较明显,为了防止缓存膨胀的太厉害,需要设定缓存上限和替换策略。
#8
楼上的说的我没听懂哦,这与sql语句有什么关联?况且我也不用考虑缓存上限和替换策略
不知是我没说清楚还是怎样,我打个比方:
比如我有一个dict{k,v}表,里面有几千条记录,因要频繁做依据k字段查v字段的操作所以考虑缓存
方案一相当于在tomcat启动时执行sql='select * from dict',然后把全部记录转化成一个hashmap,从此再也不查表。 优点:一共仅需查库一次;缺点:即使从未使用过的记录,也占用了内存。
方案二相当于我查找k=123的值时,先在hashmap中找有没有,如果有则直接返回,如果没有则执行sql='select * from dict where k=123',将结果放入缓存然后返回。 优点:仅缓存用过的记录;缺点:每次仅取一条记录,查库次数太多。
不知是我没说清楚还是怎样,我打个比方:
比如我有一个dict{k,v}表,里面有几千条记录,因要频繁做依据k字段查v字段的操作所以考虑缓存
方案一相当于在tomcat启动时执行sql='select * from dict',然后把全部记录转化成一个hashmap,从此再也不查表。 优点:一共仅需查库一次;缺点:即使从未使用过的记录,也占用了内存。
方案二相当于我查找k=123的值时,先在hashmap中找有没有,如果有则直接返回,如果没有则执行sql='select * from dict where k=123',将结果放入缓存然后返回。 优点:仅缓存用过的记录;缺点:每次仅取一条记录,查库次数太多。
#9
顶~要六个字
#10
顶~~~顶~~~
#11
你可以增加一个字段来统计记录的读写次数,然后在分类
#12
内存调度算法
#13
To 11楼:
我在引文第一段最后一句已经说了,不统计读写次数,不进行分类。因为这样的做法是完全没有意义的,因为这根我的目的背道而驰了。
To 12楼:
没看懂哦~
我在引文第一段最后一句已经说了,不统计读写次数,不进行分类。因为这样的做法是完全没有意义的,因为这根我的目的背道而驰了。
To 12楼:
没看懂哦~
#14
+1
#15
键值对的数据在内存的占用本来就比较少,就算有个几万条,内存的使用量也就个几M;如果只是几千条的话,也就是k的数量级,直接放内存应该没什么问题的。。。
#1
如果有一半多的一般都用不到还是按需取,缓存常用的比较好吧
#2
取出常用的部分放在缓存中,并对数据库按照常用和不常用做一下索引排序,查找时先找缓存,找不到的时候在从数据库中按照不常用->常用找
#3
要么就做二级缓存,一级常用,二级不常用也可以,取决于你的数据量和不常用数据的占比
#4
我也是这样做的
#5
关键是“常用”与“不常用”本身就是个模糊而无法界定的概念,某个功能客户用得多自然对应的dict也查找得多。这个不能主观推断。然而,如果按以上诸君说的,那岂不是还得统计查找量,得不偿失,本来就是为了减少数据库访问才缓存的。
我的意思也就是“常用”的和“不常用”的是完全混在一起的,我们无法把它们单独分拣出来,甚至连按常用的程度排序都不能。所以我们只能一视同仁的对待这些数据。在这样的情况下,是一次性全部进行缓存还是按需取出来缓存好些呢?前者可能浪费一些内存资源,后者可能使数据库访问次数增加。
我的意思也就是“常用”的和“不常用”的是完全混在一起的,我们无法把它们单独分拣出来,甚至连按常用的程度排序都不能。所以我们只能一视同仁的对待这些数据。在这样的情况下,是一次性全部进行缓存还是按需取出来缓存好些呢?前者可能浪费一些内存资源,后者可能使数据库访问次数增加。
#6
常用的大约占百分之四五十吧,总共也就几千条记录。
#7
除了楼上的办法外,可以参考ibatis式的缓存方式。
ibatis的缓存设计是以SQL的hash值为KEY的,每个SQL第一次查询后结果会形成单独的缓存,SQL相同缓存就相同,SQL不同就算是同一张表也会读不同的缓存。
这种设计方式是典型的缓存冗余+按需获取,连缓存内的查询都不需要了,不过缺点也比较明显,为了防止缓存膨胀的太厉害,需要设定缓存上限和替换策略。
ibatis的缓存设计是以SQL的hash值为KEY的,每个SQL第一次查询后结果会形成单独的缓存,SQL相同缓存就相同,SQL不同就算是同一张表也会读不同的缓存。
这种设计方式是典型的缓存冗余+按需获取,连缓存内的查询都不需要了,不过缺点也比较明显,为了防止缓存膨胀的太厉害,需要设定缓存上限和替换策略。
#8
楼上的说的我没听懂哦,这与sql语句有什么关联?况且我也不用考虑缓存上限和替换策略
不知是我没说清楚还是怎样,我打个比方:
比如我有一个dict{k,v}表,里面有几千条记录,因要频繁做依据k字段查v字段的操作所以考虑缓存
方案一相当于在tomcat启动时执行sql='select * from dict',然后把全部记录转化成一个hashmap,从此再也不查表。 优点:一共仅需查库一次;缺点:即使从未使用过的记录,也占用了内存。
方案二相当于我查找k=123的值时,先在hashmap中找有没有,如果有则直接返回,如果没有则执行sql='select * from dict where k=123',将结果放入缓存然后返回。 优点:仅缓存用过的记录;缺点:每次仅取一条记录,查库次数太多。
不知是我没说清楚还是怎样,我打个比方:
比如我有一个dict{k,v}表,里面有几千条记录,因要频繁做依据k字段查v字段的操作所以考虑缓存
方案一相当于在tomcat启动时执行sql='select * from dict',然后把全部记录转化成一个hashmap,从此再也不查表。 优点:一共仅需查库一次;缺点:即使从未使用过的记录,也占用了内存。
方案二相当于我查找k=123的值时,先在hashmap中找有没有,如果有则直接返回,如果没有则执行sql='select * from dict where k=123',将结果放入缓存然后返回。 优点:仅缓存用过的记录;缺点:每次仅取一条记录,查库次数太多。
#9
顶~要六个字
#10
顶~~~顶~~~
#11
你可以增加一个字段来统计记录的读写次数,然后在分类
#12
内存调度算法
#13
To 11楼:
我在引文第一段最后一句已经说了,不统计读写次数,不进行分类。因为这样的做法是完全没有意义的,因为这根我的目的背道而驰了。
To 12楼:
没看懂哦~
我在引文第一段最后一句已经说了,不统计读写次数,不进行分类。因为这样的做法是完全没有意义的,因为这根我的目的背道而驰了。
To 12楼:
没看懂哦~
#14
+1
#15
键值对的数据在内存的占用本来就比较少,就算有个几万条,内存的使用量也就个几M;如果只是几千条的话,也就是k的数量级,直接放内存应该没什么问题的。。。