Closed testnet0 closed 1 week ago
从你的优化来看,双方代码差别在于以下几点: 1.返回结果从String[](key_value)变成了hashmap key:value 2.节省了List 转 String[] 操作 3.后续操作不再需要重新分割key_value,进行值替换。
另外从你的描述中,我发现了几点问题,顺便提一下: 1.如果说数据表记录有2万行,每一行数据如果有3个字典项,那么进行的替换操作应该是6万次,而不是会2万*字典表总记录 2.紧接上面的问题可以回答另外一个问题,如果说这里不加缓存的话,那么数据库将会在导出一次操作就会承受6万次sql访问。我看你的代码中使用了带缓存的函数,所以这个风险就没有暴露出来 3.紧接上面缓存的问题,你认为的风险是字典值是一个可变项,如果缓存在redis中,会存在幻读的可能性。这确实是有可能发生的事,不过相对来说,字典项是一个无限接近于常量的概念,修改的次数也会很少,即使真的发生修改,并且发生在导出时,那这时确实有可能一部分是历史字典,一部分是新字典,但是再重新导出一次就可以解决这个问题,我个人认为这个业务可接受延迟问题。
2、3两项问题合并起来考量的话,我认为jeecg为字典加redis缓存是目前来说最好的处理办法,同时也可以防止数据库的崩溃,相较而言,让业务重试一次的代价就会显得更能接受。
另外经过我个人排查,我认为此处代码的核心问题在List转String[]的开销是主要原因,次要原因则是,分割字符串与hashmap读取差异,两者共同造成了本次问题。
非常感谢你的回复,我说下具体的场景: 如果是这种字典是可以加缓存的,确实像你说的变动不是很频繁 @Dict(dicCode = "yn") 但是这种字典表的情况会产生大量字符串分割的问题: @Dict(dictTable = "domain", dicText = "domain", dicCode = "id") 比如我有域名表和IP表,域名有3万数据,IP有2万数据,如果导出的时候想要域名和IP对应,就会产生大量的字符串操作的开销
补充一下,我追了一下AutoPOI的源码,AutoPOI的导出逻辑关于字典是这样的: 1,加载实体所有@Excel实体
综上所述,个人推断你的问题不是出现在AutoPOI导出上。
版本号:
V3.7.0
问题描述:
当使用字典表进行翻译时,如果字典表中有几万条数据,要导出的数据也有几万条,那么就会产生上亿次字典表替换操作,字典表加缓存也是不合适的,可能数据随时会发生变化,调试发现主要耗时都在这里:
原有逻辑是按下划线分割字典的key和value,这里替换成HashMap<String,String>之后会大幅提升性能,而且解决了字符串中存在_的问题 AutoPoiDictMapServiceI.java:
AutoPoiDictMapConfig.java:
org.jeecgframework.poi.excel.imports.base.ImportBaseService#addEntityToMap
org.jeecgframework.poi.excel.export.base.ExportBase#multiReplaceValueByHashMap
org.jeecgframework.poi.excel.imports.CellValueServer#replaceValueHashMap
错误截图:
优化前3万数据,2万字典表,导出超时: 优化后导出7秒: