2016-01-21 30 views
1

我使用this API從中檢索了大約24000個項目。從API中檢索數據的最快方法

所以首先我從here(警告,緩慢的瀏覽器可能會崩潰)採取項目列表。

然後我遍歷所有項目,並找到每個項目的所有信息。喜歡的東西:

https://api.guildwars2.com/v2/items/itemidhere

和刀片的信息到MySQL數據庫。

PD:真正的問題出現在下面的這一行之後。


我試圖找到最快的方式從這些鏈接獲取信息並插入它。對於這個我使用:

-GSON庫
-HikariCP(數據庫連接池)
-threads(最簡單快捷的控制方式JSON)(每個線程需要的1000個項目護理,如果有24個線程)

我做了一些測試,這裏是收集和插入24.000項目的結果:

-threads:50
-DB游泳池大小:10
- 時間:644秒

-threads:100
-DB池尺寸:10
-Time:607秒

-threads:250
-DB池尺寸:15
-Time:662秒

- 主題:500
-DB游泳池大小:20
- 時間:689秒

我知道這裏最慢的就是網絡。
我的電腦和互聯網的arent慢:
-300mb/s的網絡
enter image description here
-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); 

這是數據庫連接池的設置。通過所有的列表

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(); 

而從​​做了很多解析和檢查,如果json退出等等等等......並在最後插入...

這裏是我開始線程一切都在主類處理後:

for (int i = 0; i < _threadList.size(); i++) { 
     _threadList.get(i).start(); 
    } 

信息:here約你爲什麼不我用更大的池大小。

什麼,我不明白的是:
- 爲什麼,如果有多個線程的結果是慢
-I平均,CMON也許網絡速度慢,但是,很少有人要求可以填補300MB/s的?
- 是否會實現更好的代碼使其更快?

我真正看到它像這樣:
- 更多線程 - >互聯網速度較慢,這使得拉動信息慢。
-bigger池大小 - >慢插入由於許多連接
- 更多線程和小連接池 - >插入排隊並停止
-few線程和小連接池 - >慢拉信息

更新
- 通過彙集,1個連接/池進行經典連接,結果比較慢,比如慢30秒
- 通過CyclicBarrier執行ExecutorService,結果減慢10秒。

+1

當你完成它們後,你是否關閉了連接?你是一次一件或一批地保管這些物品嗎?批量將是更快的方式來插入它們 – rj93

+0

更多的線程=更多Taskswitches。所以有一個「Peek」,更多的線程使它變得更糟。有人建議,作爲一條經驗法則,不要爲一個並行任務使用比CPU內核多的線程。我個人不知道這是否合理。另外我會推薦一個ExecutorService而不是ArrayList Fildor

+0

@Fildor試着用ExecutorService executor = Executors.newFixedThreadPool(some pools);但仍然是相同的結果,實際上它可能會減慢5-10秒 – Alpha2k

回答

0

(問題太多了「的評論。)

我很困惑 - 你是‘檢索數據’和你‘插入’吧。我們應該關注哪一方面?你有什麼控制權?

您每秒只能插入30-40行?這是可悲的。

讓我們專注於如何將INSERTs加入到MySQL表中。請提供SHOW CREATE TABLE - 我需要查看引擎和索引以及其他內容。請提供一些關於INSERTs的線索 - 一行一行,一批一批(這裏改進10倍)?順序與隨機PRIMARY KEY?桌子有多大? buffer_pool有多大?什麼版本的MySQL(新版本有一些額外的技巧)?

線程之間存在一些爭用,所以「太多」線程實際上可能會減慢活動速度。但我認爲這是次要問題。

306Mb/s的百分比是多少?

相關問題