我正在使用this API从中检索大约24.000个项目。
首先,我从here获取项目列表(警告,慢速浏览器可能会崩溃)。
然后我遍历所有项目并找到每个项目的所有信息。类似的东西:
https://api.guildwars2.com/v2/items/itemidhere
并将信息插入MySQL数据库。
PD:真正的问题在下面的这一行之后开始。
我试图找到从这些链接获取信息并插入信息的最快方法。为此我正在使用:
-GSON库(控制JSON的最简单,最快捷的方式)
-HikariCP(用于数据库连接池)
-Threads(如果有24个线程,每个线程会处理1000个项目)
我做了一些测试,以下是收集和插入24.000项的结果:
-Threads:50
-DB池大小:10
- 时间:644秒
-Threads:100
-DB池大小:10
- 时间:607秒
-Threads:250
-DB池大小:15
- 时间:662秒
-Threads:500
-DB池大小:20
- 时间:689秒
我知道这里最慢的是网络
我的电脑和互联网都不慢:
-300mb / s互联网
-Intel 5820k
-16GB DDR4
所以剩下的可能是代码实现......
HikariConfig config = new HikariConfig();
config.setDriverClassName("com.mysql.jdbc.Driver");
config.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
config.setUsername("root");
config.setPassword("none");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
config.setMaximumPoolSize(depending on case);
Core.ds = new HikariDataSource(config);
这是数据库连接池的设置。我使用Cyclic屏障启动线程:
final CyclicBarrier _threadGate = new CyclicBarrier(depends on case);
ArrayList<Thread> _threadList = new ArrayList<>();
然后
_threadList.add(new Thread() {
@Override
public void run() {
try {
_threadGate.await();
//Parsing happens a bit later
这里我遍历所有列表并从url获取信息(我跳过变量声明):
_id = _itemList.get(i);
_stringUrl = "https://api.guildwars2.com/v2/items/" + _id;
_responseText = new URL(_stringUrl);
_requestUrl = (HttpURLConnection) _responseText.openConnection();
_requestUrl.connect();
_requestStatus = _requestUrl.getResponseCode();
if(_requestStatus == 200){
_jsonParser = new JsonParser();
_rootElement = _jsonParser.parse(new InputStreamReader((InputStream) _requestUrl.getContent(), "UTF-8"));
_rootObject = _rootElement.getAsJsonObject();
来自_rootObject
进行大量解析并检查json是否退出等等......最后插入......
以下是在主类中处理完所有内容后启动线程的方法:
for (int i = 0; i < _threadList.size(); i++) {
_threadList.get(i).start();
}
INFO:here关于为什么我没有使用更大的池大小。
我不明白的是:
- 为什么如果有更多的线程,结果会更慢
- 我的意思是,cmon也许网络很慢,但是很少有请求可以填满300mb / s?
- 实现更好的代码会使这更快吗?
我实际上是这样看的:
- 更多主题 - &gt;互联网速度较慢,这使得拉动信息变慢
- 较大的泳池大小 - &gt;由于许多连接而插入较慢
- 更多线程和小连接池 - &gt;插入排队和停滞的
-few线程和小连接池 - &gt;慢拉信息
更新
池中的经典连接,1个连接/池,结果较慢,比较慢30秒
在CyclicBarrier上执行ExecutorService,结果慢了10秒。
答案 0 :(得分:0)
(“评论”的问题太多了。)
我很困惑 - 你正在“检索数据”而你正在“插入”它。我们应该关注哪一方?你控制哪一方?
您每秒只能插入30-40行?那太可悲了。
让我们关注你如何在MySQL表中执行INSERTs
。请提供SHOW CREATE TABLE
- 我需要查看引擎和索引以及其他内容。请提供一些关于INSERTs
的线索 - 一次一行vs批次(这里改进10倍)?顺序与随机PRIMARY KEY
?桌子有多大? buffer_pool有多大?什么版本的MySQL(较新的版本有一些额外的技巧)?
线程之间存在一些争用,因此“太多”线程实际上可以减慢活动速度。但我认为这是次要问题。
消耗306Mb / s的百分之几?