データ分析の分野では、データベースは私たちの強力な助けとなります。クエリ時間を受け入れるだけでなく、それに基づいてさらに分析を行うこともできます。したがって、データベースにデータを挿入する必要があります。実際のアプリケーションでは、数千万、あるいはそれ以上の量のデータが頻繁に発生します。素早く挿入する方法がなければ、効果がなく、多くの時間がかかります。 アリババの天地ビッグデータアルゴリズムコンテスト(人気音楽のトレンド予測)に参加したとき、このような問題に遭遇しました。データベースクエリと挿入を最適化する前は、多くの時間を無駄にしていました。最適化前は、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 を応援していただければ幸いです。 以下もご興味があるかもしれません:
|
>>: Ubuntu 18.04 Linux システムに JDK と Mysql をインストールする方法
による写真に示されている効果を例に挙げてみましょう。明らかに、「次へ」というテキストを水平方向だけで...
1. 仮想マシン(物理マシン)をインストールする仮想マシンまたは物理マシンにインストールできます。 ...
MySQL はリレーショナル データベース管理システムです。リレーショナル データベースは、すべて...
今日のレスポンシブ レイアウトの要件では、サイズを自動的に調整できる多くの要素で高さと幅の適応を実現...
最近、プロジェクトで選択クエリを使用する際に、未使用の主キー ID を除外するために not in ...
Kubernetes は、基本認証、トークン認証、CA 認証の 3 種類の認証をサポートしています。...
目次範囲グローバルスコープ関数のスコープもし、スイッチ、のために、その間ブロックスコープスコープチェ...
目次1. HBuilderXビジュアルインターフェースを通じて2. vue-cliコマンドで実行する...
この記事では、例を使用して、MySQL ストアド プロシージャで複数の値を返す方法について説明します...
モバイル アプリを開発する場合、Web サイトが特定の高さまでスクロールしたときにコンテンツの一部を...
目次インストールの前提条件ステップ1: システムの残りを確認してクリアし、Dockerの依存関係をイ...
MySQL ユーザーと権限MySQL には、MySQL と呼ばれるシステムに付属するデータベースがあ...
目次序文こんにちは世界画像 境界線の半径を設定する実ピクセルを設定する外部CSSをインポートttfフ...
【著者】 Liu Bo: Ctrip テクニカル サポート センターのシニア データベース マネージ...
最初のステップ組み込みのパッケージ管理機能で一度削除する yum 削除 nodejs npm -y ...