问题描述
一个查询页面的结果DataTable,数据量最多时候大概几万行。我想用Cache缓存,但是想想如果有多个用户同时在使用这样会出问题的吧。比如用户A查询了一次,给这个DataTable缓存:Cache.Insert("dt",dt,...),这时服务器已经存在缓存dt了。用户B随后又查询了一次又更新了缓存。此时,用户A页面有个“导出数据”按钮,是用Cache["dt"]当数据源的,此时会出错吗。如果错了该用什么效率会高点呢,google了有DataSource缓存和ViewState,不知道哪个好点或者还有其他的方式呢,大神们不吝赐教!
解决方案
解决方案二:
当然,你对数据做了修改操作就应该通知缓存相关数据为脏数据。这是任何缓存框架都能实现的。
解决方案三:
用Cache.lnsert()将数据项加入缓存//将数据项目加入缓存protectedvoidbtnAddCache_Click(objectsender,EventArgse){//利用Cache.Insert()方法将数据加入缓存Cache.Insert("Name",txtUserName.Text);Cache.Insert("Phone",txtTel.Text);Cache.Insert("Position",txtJob.Text);txtMsg.Text="缓存加入成功!";}//读取显示缓存protectedvoidbtnDisplayCache_Click(objectsender,EventArgse){IDictionaryEnumeratorCacheIDE=Cache.GetEnumerator();//显示缓存数据inti=0;stringinfo=null;info+="缓存项目数据(Key/Value):"+"<BR>";while(CacheIDE.MoveNext()){info+=i.ToString()+".";info+=CacheIDE.Key.ToString()+":";info+=CacheIDE.Value.ToString()+"<BR>";i++;}//CodeGo.net/if(Cache["Name"]==null)//判断缓存是否有数据项目{txtMsg.Text="缓存内容为Null值";}else{txtMsg.Text=info;}}
解决方案四:
缓存的话会加大页面的输出,缓存越大输出越慢,页面显示也就越慢。如果你在页面只是查询显示,建议你用分页的存储过程,每次只返回一页,个人感觉还是挺快。
解决方案五:
引用1楼caozhy的回复:
当然,你对数据做了修改操作就应该通知缓存相关数据为脏数据。这是任何缓存框架都能实现的。
脏数据就不能用了啊,那请问下用什么能提高效率呢,Cache还可以实现么
解决方案六:
大量的数据不适合使用缓存(序列化耗时),你拿10万行测试一下就知道了,页面卡死,如果一定要缓存大量数据,那么自己动手做一个基于内存或者基于SqlServer的查询服务,页面级的缓存,需要扩展一下页面对象,做一个Guid标识出每个页面
解决方案七:
引用3楼wangnaisheng的回复:
缓存的话会加大页面的输出,缓存越大输出越慢,页面显示也就越慢。如果你在页面只是查询显示,建议你用分页的存储过程,每次只返回一页,个人感觉还是挺快。
除了分页的存储过程还有其他方法么,可能页面A的查询结果还要用到页面B上,我想把页面A的缓存起来
解决方案八:
引用5楼microtry的回复:
大量的数据不适合使用缓存(序列化耗时),你拿10万行测试一下就知道了,页面卡死,如果一定要缓存大量数据,那么自己动手做一个基于内存或者基于SqlServer的查询服务,页面级的缓存,需要扩展一下页面对象,做一个Guid标识出每个页面
请问有基于内存的或者基于SqlServer的例子么,因为之前没听说过,google百度了好像也不知道哪个才是你说的
解决方案九:
引用5楼microtry的回复:
大量的数据不适合使用缓存(序列化耗时),你拿10万行测试一下就知道了,页面卡死,如果一定要缓存大量数据,那么自己动手做一个基于内存或者基于SqlServer的查询服务,页面级的缓存,需要扩展一下页面对象,做一个Guid标识出每个页面
怎么不指点指点
解决方案十:
引用楼主zdczdcc的回复:
一个查询页面的结果DataTable,数据量最多时候大概几万行。我想用Cache缓存,但是想想如果有多个用户同时在使用这样会出问题的吧。比如用户A查询了一次,给这个DataTable缓存:Cache.Insert("dt",dt,...),这时服务器已经存在缓存dt了。用户B随后又查询了一次又更新了缓存。此时,用户A页面有个“导出数据”按钮,是用Cache["dt"]当数据源的,此时会出错吗。如果错了该用什么效率会高点呢,google了有DataSource缓存和ViewState,不知道哪个好点或者还有其他的方式呢,大神们不吝赐教!
你完全没有理解缓存是干什么的!如果一个缓存数据“几万行”,那么你使用它的有效命中率是多少?小得可怜。真正的缓存应该是只有几行、几十行的。比如说需要把csdn的某一个栏目的首页列表缓存起来,这只要创建一个以“栏目名”为主的key作为这个缓存单元的索引就行了。假设同时需要再把csdn上某一个栏目“最近5天内回帖数超过100个”的帖子的查询结果列表页也缓存起来,这也是要创建一个以“栏目名”为主的另外不一样的key作为这个缓存单元的索引。因此系统中可能同时有上万个、十多万个缓存单元(而不是只有一个“dt”)。即使仅仅是与你的dt数据相关的,可能就有几百个。缓存单元中的数据完全可能重复。缓存单元的查询命中率是100%的。比如说csdn每一分钟都可能要查询“.net栏目的首页列表”(计算出的相同的缓存单元查询key)10000次,只有第一次需要查询一下数据库,然后9999次都是从缓存单元中拿出整个(100%)数据。然后1分钟之后,恰好这个栏目有一个帖子发布时间更新了,于是这个key对应的缓存单元就被自动移除了。半秒钟之后,这个缓存单元会被重建(因为查询了一下数据库)。结果是,这个key对应的缓存单元,被创建之后生命期只有1分钟不到,需要不断刷新。但是在它刷新之前,所有的相同key的查询就不用走数据库查询了(9999:1的性能提高)。而且这个“.net栏目的首页列表”所缓存的数据集合,可能需要读取4个数据库表,而且来自于多个服务器的多个不同的数据库实例。它根本就是业务逻辑服务返回的高层次的系统通讯数据,不是什么低级的“数据库表”概念。而你的所谓“dt”,把某个数据库表你得数据扔到内存里,除了特别严重地滥用内存并且你也不能及时刷新内存中的数据以外,我不在知道有多大作用。
解决方案十一:
把缓存看成是内存数据库,这是一个很荒唐的事情。内存数据库就是内存数据库,它的目的就是“内存数据库”。但是“内存数据库不是缓存”!她们之间完全没有替代关系。缓存就是你的程序中有了反复需要调用的东西。比如说你的程序首先计算出了“用户887373的角色授权列表”,然后这个数据可能随后在同一个或者不同线程中、在同一个层次或者深度的调用过程中,被反复调用几万次。而这类数据在数据库中被改动(例如通过SqlDependency机制通知缓存清除)的机会相对来说比读取它的机会要小太多了。这时候使用缓存。你不能把所有5000个用户的所有角色授权给弄什么“缓存”。你也不应该在人家单独查询887373用户的授权列表时再去从什么DataTable的几十万条数据中去查询什么。对于系统来说,一段时间内(比如说10分钟内)访问过十几个用户的角色授权,那么缓存系统中就只存有这十几个用户的角色授权列表,而不是所有人的。缓存系统会智能地根据多种条件去自动清除缓存单元。我们可以看到,根本不理解缓存、把缓存当作“内存数据库表”的那种做法,跟缓存根本不搭界。你那个哪里是“缓存”,你那个纯粹是把数据库表“静态地”搬到内存里。
解决方案十二:
会点编程语句不是什么很重要的事情,除非你把这些基本的概念反复了解清除了,否则写出的那几行编程语句往往给以后的工作埋下祸根。
解决方案十三:
引用11楼sp1234的回复:
会点编程语句不是什么很重要的事情,除非你把这些基本的概念反复了解清除了,否则写出的那几行编程语句往往给以后的工作埋下祸根。
亲,首先谢谢你的热心回答。不过我这个是要另一个页面可能要把dt导出道csv文件,不想再查询一次所以就想用下缓存。说实话,真的不知道缓存和内存数据库还有区别。还有,能指点下内存数据库么...
解决方案十四:
引用12楼zdczdcc的回复:
Quote: 引用11楼sp1234的回复:
会点编程语句不是什么很重要的事情,除非你把这些基本的概念反复了解清除了,否则写出的那几行编程语句往往给以后的工作埋下祸根。亲,首先谢谢你的热心回答。不过我这个是要另一个页面可能要把dt导出道csv文件,不想再查询一次所以就想用下缓存。说实话,真的不知道缓存和内存数据库还有区别。还有,能指点下内存数据库么...
走SQL服务器的导出数据那个功能,然后保存到用户目录下进行下载。
解决方案十五:
只有相对稳定的数据才适合混存,经常改变的数据,并不适合创建混存。小数据缓存的另外一种替代方式:将数据按规则分块,存为xml文件或者其他格式文件