MySql クイック挿入数千万の大規模データの例

MySql クイック挿入数千万の大規模データの例

データ分析の分野では、データベースは私たちの強力な助けとなります。クエリ時間を受け入れるだけでなく、それに基づいてさらに分析を行うこともできます。したがって、データベースにデータを挿入する必要があります。実際のアプリケーションでは、数千万、あるいはそれ以上の量のデータが頻繁に発生します。素早く挿入する方法がなければ、効果がなく、多くの時間がかかります。

アリババの天地ビッグデータアルゴリズムコンテスト(人気音楽のトレンド予測)に参加したとき、このような問題に遭遇しました。データベースクエリと挿入を最適化する前は、多くの時間を無駄にしていました。最適化前は、1500万のデータ項目を挿入するだけで(最も基本的な1つずつの挿入を使用)、信じられないほどの12時間もかかっていました。これにより、データベースの挿入とクエリ操作を最適化して効率を向上させる方法についても考えるようになりました。

継続的な最適化の過程で、パフォーマンスが大幅に向上しました。データベースから26,000曲以上のダウンロード数、再生数、お気に入り数を時系列で照会・集計する処理において、クエリ生成操作速度が推定40時間から1時間強に短縮されました。データベース挿入に関しては、パフォーマンスが大幅に向上しました。新しいデータセットでテストしたところ、20 分間で 5,490 万件を超えるデータが挿入されました。以下に私の考えを述べさせてください。

最適化プロセスは 2 つのステップに分かれています。最初のステップは、実験的な静的リーダーを使用して CSV ファイルからデータを読み取ることです。データが一定量に達すると、データベース プログラムへのマルチスレッド挿入が開始されます。2 番目のステップは、MySQL バッチ挿入操作を使用することです。

最初のステップは、ファイルを読み取り、マルチスレッドの挿入を開始することです

ここで、ある量に到達するかどうかは考慮すべき問題です。私の実験では、この量として 100W を使い始めましたが、新たな問題が発生し、Java ヒープ メモリがオーバーフローしたため、最終的に 10W が標準として使用されました。

もちろん、お好みに応じて他の量でも構いません。

java.io.BufferedReader をインポートします。
java.io.FileNotFoundException をインポートします。
java.io.FileReader をインポートします。
java.io.IOException をインポートします。
java.util.ArrayList をインポートします。
java.util.List をインポートします。
 
preprocess.ImportDataBase をインポートします。
 
パブリッククラスMuiltThreadImportDB {
 
 /**
  * 大容量ファイルとストレージの Java マルチスレッド読み取り * 
  * @param 引数
  */
 プライベート静的int m_record = 99999;
 プライベート静的 BufferedReader br = null;
 プライベートArrayList<String>リスト;
 プライベート静的int m_thread = 0;
 静的{
 試す {
  br = 新しいバッファリーダー(
  新しいファイルリーダー(
  "E:/tianci/IJCAI15 Data/data_format1/user_log_format1.csv"),8192);
 
 } キャッチ (FileNotFoundException e) {
  e.printStackTrace();
 }
 試す {
  br.readLine(); // CSV ヘッダーを削除
 } キャッチ (IOException e) {
  e.printStackTrace();
 }
 }
 
 パブリックボイド開始() {
 文字列;
 整数カウント = 0;
 リスト = 新しいArrayList<String>(m_record + 1);
 同期 (br) {
  試す {
 ((line = br.readLine()) != null) の場合 {
  カウント < m_record) {
 リストに行を追加します。
 カウント++;
  } それ以外 {
 リストに行を追加します。
 カウント = 0;
 スレッド t1 = new Thread(new MultiThread(list),Integer.toString(m_thread++));
 t1.開始();
 リスト = 新しいArrayList<String>(m_record + 1);
  }
 }
 
 if (リスト != null) {
  スレッド t1 = new Thread(new MultiThread(list),Integer.toString(m_thread++));
  t1.開始();
 }
  } キャッチ (IOException e) {
 e.printStackTrace();
  }
 }
 }
 
 パブリック静的voidメイン(String[] args) {
 新しい MuiltThreadImportDB().start();
 } 
}

2番目のステップは、マルチスレッドを使用してデータをバッチで挿入することです。

クラス MultiThread は Runnable を実装します {
 プライベートArrayList<String>リスト;
 
 パブリックマルチスレッド(ArrayList<String>リスト) {
 this.list = リスト;
 }
 
 パブリックボイド実行() {
 試す {
  ImportDataBase を挿入 = 新しい ImportDataBase(リスト);
  挿入を開始します。
 } キャッチ (FileNotFoundException e) {
  e.printStackTrace();
 }
 このリストを表示します。
 }
 
 パブリック void display(List<String> リスト) {
 // for (文字列 str : リスト) {
 // System.out.println(str);
 // }
 System.out.print(Thread.currentThread().getName() + " :");
 System.out.println(リストのサイズ());
 }
 
}

バッチ操作では、MySQL の prepareStatement クラスが使用され、もちろん statement クラスのバッチ操作も使用されますが、パフォーマンスは前者ほど良くありません。前者は毎秒 10,000 以上の挿入速度に達することができますが、後者は 2,000 以上しか達しません。

パブリック int insertUserBehaviour(ArrayList<String> sqls) は SQLException をスローします {
 
 文字列 sql = "user_behaviour_log に挿入 (user_id、item_id、cat_id、merchant_id、brand_id、time_stamp、action_type)"
 + " 値(?,?,?,?,?,?,?)";
 事前ステートメント = conn.prepareStatement(sql);
 (int i = 0; i < sqls.size(); i++) の場合 {
  UserLog ログ = 新しい UserLog(sqls.get(i));
  プレStmt.setString(1, log.getUser_id());
  プレStmt.setString(2, log.getItem_id());
  プリステージ.setString(3, log.getCat_id());
  事前Stmt.setString(4, log.getMerchant_id());
  preStmt.setString(5, log.getBrand_id());
  タイムスタンプを6に設定します。
  アクションタイプをログに記録します。
  preStmt.addBatch();
  ((i + 1) % 10000 == 0) の場合 {
 preStmt.executeBatch();
 conn.commit();
 preStmt.clearBatch();
  }
 }
 preStmt.executeBatch();
 conn.commit();
 1 を返します。
 }

もちろん、さまざまな MySQL ストレージ エンジンである InnoDB と MyISM でも実験しました。実験結果では、InnoDB の方が高速 (約 3 倍) であることが示されましたが、これは MySQL の新しいバージョンに関係している可能性があります。著者の MySQL バージョンは 5.6 です。

最後に、大量データでの挿入速度を向上させる方法をまとめます。

Java コードの場合は、マルチスレッド挿入とバッチ送信を使用します。

データベースに関しては、テーブル構造を確立するときにインデックスを使用しないでください。そうしないと、挿入プロセス中にインデックス B+ ツリーを維持する必要があります。ストレージ エンジンを変更します。通常、デフォルトは InnoDB です (新しいバージョンではデフォルトを使用できますが、古いバージョンでは必要な場合があります)。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • インデックスを使用して数千万のデータを持つ MySQL のクエリ速度を最適化する
  • MySQLループは数千万のデータを挿入する
  • 数千万のMySQLデータ量を素早くページ分割する方法
  • MySQL で大量のデータ (数千万) を素早く削除するためのいくつかの実用的なソリューションの詳細な説明
  • MySQL 数千万のビッグデータに対するSQLクエリ最適化の知識ポイントのまとめ
  • MySQLで数千万のテストデータを素早く作成する方法
  • MySQL数千万の大規模データに対する30のSQLクエリ最適化テクニックの詳細な説明
  • 数千万のデータを扱うMySQLのページングクエリのパフォーマンスを最適化する
  • 数千万ページ分のMySQL高速ページングを最適化する方法
  • MySQLデータベースの数千万件のデータクエリとストレージの詳細な説明

<<:  Reactでプロキシを有効にする2つの実用的な方法

>>:  Ubuntu 18.04 Linux システムに JDK と Mysql をインストールする方法

推薦する

Windows SSHサーバーを簡単に構築するためのいくつかの手順

ここで言及されている SSH は Security Shell と呼ばれます。Linux をよく使用...

JSのバイナリファミリーについての簡単な説明

目次概要ブロブBlob の動作BLOB ダウンロード ファイルブロブ画像のローカル表示BLOB ファ...

Vue3.0 でページング コンポーネントを手動でカプセル化する方法

この記事では、vue3.0の手動カプセル化ページングコンポーネントの具体的なコードを参考までに紹介し...

MySQLのkillがスレッドをkillできない理由

目次背景問題の説明原因分析シミュレーションする総括する背景日常の使用において、MySQL で個別また...

Vue の一般的な問題と解決策の概要 (推奨)

Vue に限定されず、他の種類の SPA プロジェクトにも当てはまる問題がいくつかあります。 1....

Vue3+Element+Tsは、フォームの基本的な検索リセットやその他の機能を実装します

Vue2 の記述スタイルから Vue3 の形式に切り替えると、記述スタイルとコード構造にいくつかの変...

ブラウザでのjsのイベントループイベントキューの詳細な説明

目次序文スタックと2つのキューを理解する実行プロセス簡単な例より難しい例要約する序文以下の内容はブラ...

HTML で自動ページジャンプを実現する 5 つの方法

前回の記事では、HTML ページが 3 秒後に自動的にジャンプする一般的な 3 つの方法を紹介しまし...

vue-amap のインストールと使用手順

以前、Amap API を非同期にロードする方法を紹介しました。今回は、vue-amap の使用方法...

JavaScript 関数呼び出しの典型的なサンプルコード

目次JavaScript 関数呼び出しの典型的な例JS関数の定義と呼び出し方法要約するJavaScr...

MySQL でスロークエリを有効にする方法の例

序文スロー クエリ ログは、MySQL で非常に重要な機能です。MySQL のスロー クエリ ログ機...

CentOS6.9 での MySQL 5.7.17 のインストールと設定のチュートリアル

CentOS6.9はMysql5.7をインストールします。参考までに、詳細は次のとおりです。 1. ...

MySQL トランザクション分離レベルの詳細

serializableシリアル化(問題なし)トランザクションは順次実行する必要があります。前のトラ...

IE8対応のボーダー半径処理方法

canisue (http://caniuse.com/#search=border-radius)...

ウェブデザインの概要

<br />1998年に最初の個人ページが誕生してから2008年の今日まで、デザイン業界...