我需要插入约150米的记录到Xodus数据库使用xodus-dnq在一批。基于示例,我实现了以下方法:
XdModel.registerNodes(
XDTrip
)
val store = StaticStoreContainer.init(
dbFolder = File(target),
environmentName = "trips"
)
initMetaData(XdModel.hierarchy, store)
store.use { store ->
store.persistentStore.use {
// TripLoader(File(src)) returns a stream with roughly 150M elements
TripLoader(File(src)).forEach { databaseTrip ->
store.transactional {
XDTrip.new {
id = databaseTrip.id
start = databaseTrip.start.epochSecond
end = databaseTrip.end.epochSecond
}
}
}
}
}它工作得很好,但会泄漏内存。大概我需要手动提交/刷新/持久化事务吗?
根据另一项建议,我对此进行了重构,以便在事务中运行较小的批:
XdModel.registerNodes(
XDTrip,
XDPosition,
XDPositionSource
)
val store = StaticStoreContainer.init(
dbFolder = File(target),
environmentName = "trips"
)
initMetaData(XdModel.hierarchy, store)
store.use {
it.use { store ->
Sequence { TripLoader(File(src)).iterator() }.chunked(100).forEachIndexed { index, csvChunk ->
store.transactional {
println("Chunk $index")
csvChunk.forEach { csvTrip ->
XDTrip.new {
id = csvTrip.id
start = csvTrip.start.epochSecond
end = csvTrip.end.epochSecond
// ...
}
}
}
}
}
}然而,这仍然会泄漏内存。
我分析了内存,发现jetbrains.exodus.core.dataStructures.ConcurrentLongObjectCache占用了堆的大部分部分:
由“"jetbrains.exodus.core.dataStructures.ConcurrentLongObjectCache”@ 0x4c0481d58“加载的
的一个实例占45,075,952 (80.24%)字节。内存是在“"jetbrains.exodus.core.dataStructures.ConcurrentLongObjectCache$CacheEntry[]”@ 0x4c0481d58“加载的一个sun.misc.Launcher$AppClassLoader实例中积累的。
关键词jetbrains.exodus.core.dataStructures.ConcurrentLongObjectCache sun.misc.Launcher$AppClassLoader @ 0x4c0481d58 jetbrains.exodus.core.dataStructures.ConcurrentLongObjectCache$CacheEntry[]
当程序运行时,我可以看到磁盘上的数据库大小是如何增加的,所以我不知道为什么缓存会在这里填满。
发布于 2020-04-17 11:59:07
用批处理大量操作是一种推荐的方法。如果使用Kotlin序列,则有windowed扩展函数。所以你的代码就像:
TripLoader(File(src)).windowed(1000) { trips ->
store.transactional {
trips.forEach { databaseTrip ->
XDTrip.new {
id = databaseTrip.id
start = databaseTrip.start.epochSecond
end = databaseTrip.end.epochSecond
}
}
}实际上,如果您在运行时或整个操作中做了一些事情,消耗了大量时间,那么最好深入一点,使用低级别的api。代码将变得更加复杂,但运行速度会快一倍。
例如,如果您认为数据是一致的,并且不需要检查所有约束、关系和其他,您可以使用以下内容:
val type = XdTrip.entityType
TripLoader(File(src)).windowed(1000) { trips ->
persistentStore.executeInExclusiveTransaction { txn ->
trips.forEach { databaseTrip ->
txn.newEntity(type).also {
it.setProperty("id", databaseTrip.id)
...
}
}
}窗口大小应根据导入的数据进行检查。在原始数据结构的情况下,它可以增加。
https://stackoverflow.com/questions/61267052
复制相似问题