如何在临时本地存储中存储数百万个条目
How to store millions of entries in temporary local storage
我正在做一项将数百万条数据从一个数据库迁移到另一个数据库的工作。在第一个数据库中,我有两个不同的 tables(我可以将其作为我下载的文本文件访问 - 我无法正确访问数据库)
(1) Cities - 其中每一行都是一个 City 对象,实例变量由制表符分隔(例如 id name population
)
(2) CitiesToTopics - 其中每一行都是一个城市 ID 和一个相应的主题(例如 id topic
)。这不是每行唯一的。所以,2行可以共享一个id,意味着对应的城市有2个话题[topic1, topic2].
在此迁移中,我将创建一个名为 City 的新 POJO,其中包含
public class City {
private long id;
private String name;
private long population;
private List<String> topics;
// removed getters and setters
}
并将这些城市添加到我的新数据库中。
我想先查询 CitiesToTopics table 并创建一个
HashMap<String, List<String>> citiesToTopics
映射每个 id -> List[topic]。
然后,查询第二个 table,对于每一行,获取 id 并执行
List<String> topics = citiesToTopics.get(id)
然后创建 City(id, name, population, topics)
.
除了 CitiesToTopics 中有 26 多万个城市和大约 1.5 亿个条目外,这一切都很好。因此,当我尝试 运行 程序时,我不断收到内存错误或 GC 错误。我已经升级到 fastutil hashmap,但我得到的是 "A fatal error has been detected by the Java Runtime Environment"。我不能真正使用外部数据库来存放我的临时 citiesToTopics,因为 SQLite 可以做大约 950 inserts/sec,这在我的例子中意味着需要大约 2 天才能 运行。有没有更好的方法来处理这么多数据,尤其是当它实际上只是确保每个城市获得其适当主题的临时方法时?
提前致谢,
编辑: 必要的按摩——这就是我需要创建临时数据结构的原因——取一条包含 id topic
作为字符串的行,拆分\t
的行并将其放入地图中。然后,取一条包含 id name population
的行,用 \t
分割,创建一个新的 JSONObject
,它将是 {"Id": "97987987", "name": "Boston","Population":“673,184”,"Topics":["summer","winter"]}。
您可以做的是:
- 将两个文件按id排序。例如,在 linux 上,您可以使用
cat file | sort -k1 > sorted_file
(未测试)之类的东西,它可能会在合理的时间内完成此操作(较大的文件需要几个小时,但不会天)
- 以同步方式遍历一次城市和主题文件,现在您知道所有记录都已排序,并以 N 个城市为一批次填充新数据库。您不需要比批处理大小更多的内存。
@assylias 是对的:按 ID 对城市文件进行排序,然后按城市 ID 对 citiesToTopics 进行排序。要点是对这些文件进行排序。在那种情况下,您不需要在处理之前将整个文件拉入内存或其他任何地方,并且您的程序将使用很少的内存,不超过新结构中的一个对象,每个文件只使用一行。
例如,您的程序可以有两个嵌套循环(在伪代码中):
nextCityToTopic = CityToTopicsFile.readFirstLine
for each city in citiesFile {
city = citiesFile.readNextLine
newJsonStructure = createNewforCity
curCityId = city.id
do {
if nextCityToTopic.cityId == nextCityToTopic.cityId {
add Topic into newJsonStructure
nextCityToTopic = CityToTopicsFile.readNextLine
} else {
insert newJsonStructure into database
break
}
} while CityToTopicsFile.hasMoreLines
}
P.S。实际上,这是对@assylias post 的评论。抱歉,它很大-所以我只是添加为答案。
我正在做一项将数百万条数据从一个数据库迁移到另一个数据库的工作。在第一个数据库中,我有两个不同的 tables(我可以将其作为我下载的文本文件访问 - 我无法正确访问数据库)
(1) Cities - 其中每一行都是一个 City 对象,实例变量由制表符分隔(例如 id name population
)
(2) CitiesToTopics - 其中每一行都是一个城市 ID 和一个相应的主题(例如 id topic
)。这不是每行唯一的。所以,2行可以共享一个id,意味着对应的城市有2个话题[topic1, topic2].
在此迁移中,我将创建一个名为 City 的新 POJO,其中包含
public class City {
private long id;
private String name;
private long population;
private List<String> topics;
// removed getters and setters
}
并将这些城市添加到我的新数据库中。
我想先查询 CitiesToTopics table 并创建一个
HashMap<String, List<String>> citiesToTopics
映射每个 id -> List[topic]。
然后,查询第二个 table,对于每一行,获取 id 并执行
List<String> topics = citiesToTopics.get(id)
然后创建 City(id, name, population, topics)
.
除了 CitiesToTopics 中有 26 多万个城市和大约 1.5 亿个条目外,这一切都很好。因此,当我尝试 运行 程序时,我不断收到内存错误或 GC 错误。我已经升级到 fastutil hashmap,但我得到的是 "A fatal error has been detected by the Java Runtime Environment"。我不能真正使用外部数据库来存放我的临时 citiesToTopics,因为 SQLite 可以做大约 950 inserts/sec,这在我的例子中意味着需要大约 2 天才能 运行。有没有更好的方法来处理这么多数据,尤其是当它实际上只是确保每个城市获得其适当主题的临时方法时?
提前致谢,
编辑: 必要的按摩——这就是我需要创建临时数据结构的原因——取一条包含 id topic
作为字符串的行,拆分\t
的行并将其放入地图中。然后,取一条包含 id name population
的行,用 \t
分割,创建一个新的 JSONObject
,它将是 {"Id": "97987987", "name": "Boston","Population":“673,184”,"Topics":["summer","winter"]}。
您可以做的是:
- 将两个文件按id排序。例如,在 linux 上,您可以使用
cat file | sort -k1 > sorted_file
(未测试)之类的东西,它可能会在合理的时间内完成此操作(较大的文件需要几个小时,但不会天) - 以同步方式遍历一次城市和主题文件,现在您知道所有记录都已排序,并以 N 个城市为一批次填充新数据库。您不需要比批处理大小更多的内存。
@assylias 是对的:按 ID 对城市文件进行排序,然后按城市 ID 对 citiesToTopics 进行排序。要点是对这些文件进行排序。在那种情况下,您不需要在处理之前将整个文件拉入内存或其他任何地方,并且您的程序将使用很少的内存,不超过新结构中的一个对象,每个文件只使用一行。
例如,您的程序可以有两个嵌套循环(在伪代码中):
nextCityToTopic = CityToTopicsFile.readFirstLine
for each city in citiesFile {
city = citiesFile.readNextLine
newJsonStructure = createNewforCity
curCityId = city.id
do {
if nextCityToTopic.cityId == nextCityToTopic.cityId {
add Topic into newJsonStructure
nextCityToTopic = CityToTopicsFile.readNextLine
} else {
insert newJsonStructure into database
break
}
} while CityToTopicsFile.hasMoreLines
}
P.S。实际上,这是对@assylias post 的评论。抱歉,它很大-所以我只是添加为答案。