[英]Fastest way to retrieve data from API
我正在使用此 API从中检索大约24.000个项目。
因此,我首先从此处获取项目列表(警告,缓慢的浏览器可能会崩溃)。
然后,我遍历所有项目并找到每个项目的所有信息。 就像是:
https://api.guildwars2.com/v2/items/itemidhere
然后将信息插入MySQL数据库。
PD:真正的问题在下面的这一行之后开始。
我试图找到最快的方法来获取这些链接中的信息并将其插入。 为此,我正在使用:
-GSON库(控制JSON的最简单最快的方法)
-HikariCP(用于数据库连接池)
-线程(如果有24个线程,则每个线程可处理1000个项目)
我做了一些测试,这是收集和插入24.000件商品的结果:
线程数:50
-DB池大小:10
-时间:644秒
线程数:100
-DB池大小:10
-时间:607秒
线程数:250
-DB池大小:15
-时间:662秒
线程数:500
-DB池大小:20
-时间:689秒
我知道这里最慢的是网络。
我的计算机和互联网速度缓慢:
-300mb / s网路
-英特尔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);
这是数据库连接池的设置。 我从循环障碍开始线程:
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();
}
信息: 这里关于我为什么不使用更大的游泳池。
我不明白的是:
-为什么如果有更多线程,结果会更慢
-我的意思是,也许网络速度很慢,但是很少有请求可以达到300mb / s?
-实施更好的代码可以使速度更快吗?
我实际上是这样看的:
-更多线程->互联网速度较慢,这会使信息获取速度变慢。
-更大的池大小->由于许多连接,插入速度较慢
-更多的线程和小的连接池->插入队列并停滞
-少量线程和小型连接池->缓慢拉取信息
更新
-通过池尝试经典连接,每个连接1个连接,结果变慢,例如变慢30秒
-在CyclicBarrier上尝试了ExecutorService,结果慢了10秒。
(有关“评论”的问题太多。)
我很困惑-您正在“检索数据”,而您正在“插入”数据。 我们应该关注哪一边? 您控制哪一侧?
您每秒只能插入30-40行? 那太可悲了。
让我们专注于如何对MySQL表进行INSERTs
。 请提供SHOW CREATE TABLE
我需要查看Engine和索引以及其他内容。 请提供有关INSERTs
一些线索-一次一行与批量一次(此处提高10倍)? 顺序PRIMARY KEY
随机PRIMARY KEY
? 桌子多大? buffer_pool有多大? 什么版本的MySQL(较新的版本有一些额外的技巧)?
线程之间存在某些争用,因此“太多”线程实际上会减慢活动速度。 但是我认为这是次要问题。
306Mb / s消耗了百分之几?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.