繁体   English   中英

从API检索数据的最快方法

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM