我目前正在我们基于休眠的应用程序中进行性能和内存调整,以进行大批量/批量导入。我们基本上是在导入一个包含产品数据的 CSV 文件,其中一些产品是新的(插入)和一些存在(更新)。
我现在的重点是选择一种策略来找出要更新哪些实体以及要插入哪些实体,而无需对 CSV 文件中的每一行进行检查(如果存在则选择)。
我目前的做法是这样的:
- 构建数据库内所有对象的哈希图。
- 遍历 CSV 并使用 hashmap 来决定是更新还是插入。
这种方法效果很好,测试证明它比对每一行进行这样的单个 IF EXISTS 检查要快很多。
如果数据库中有很多实体,我担心的是内存大小。
现在我考虑使用上述方法的轻微变化,我想知道意见。基本上我想做的是对多行进行多批 IF EXISTS 检查(例如SELECT FROM table where sku IN (sku1, sku2, sku3)
)
这是一些伪代码:
1. Database contains: db{sku1, sku2,sku3,sku5}
2. file contains: file {sku1, sku2, sku3, sku6}
3. Expected result:
updates: {sku1, sku2, sku3}
inserts{sku6}
4. Algorithm
have a map to keep database entities which need updates
updatemap {}
now iterate over the file in e.g. batches of 2 rows (for demo purposes)
1st iteration: foreach (select where sku IN (sku1, sku2) limit 2) as elem
-> updatemap.add(elem) -> elem is asumed to be a persistent entity here
-> myDAO.update(elem) -> executes Spring's getHibernateTemplate().update() under the hood
-> updatemap contents after 1st loop {sku1, sku2}
2nd iteration: foreach (select where sku IN (sku3, sku6) limit) 2 as elem
-> updatemap.add(elem)
-> myDAO.update(elem)
-> updatemap contents after 3nd loop {sku1, sku2, sku3}
顺便说一句:我也已经假设像(if i % 30 == 0) session.flush; session.clear();
现在我们知道所有更新的元素。所有不在 updatemap 中的 skus 基本上都是插入,我们可以使用简单的集合算术来确定这些
文件 {sku1, sku2, sku3, sku6} - updatemap {sku1, sku2, sku3} = newinserts {sku6}
现在我们可以继续插入剩余的 CSV 行。
结论 我的假设是,由于文件内容的分块,我可以限制使用的内存量。与最初的方法相比,我有更多的 SELECT 语句,但如果数据库中已经有数千个实体,我可以更好地控制内存使用。
您对此有何想法?还有哪些其他有效的方法可以找出要更新哪些实体以及要批量插入哪些实体?