単一の MySQL テーブルで数千万のデータを処理するアイデアを共有する

単一の MySQL テーブルで数千万のデータを処理するアイデアを共有する

プロジェクトの背景

処理中、今朝はフィールド A を更新する必要があります。午後には、クローラー チームが仕様または画像のクロールを完了し、画像と仕様フィールドを更新する必要があります。単一のテーブルで数千万ページのディープ ページ フリップが行われるため、処理速度はますます遅くなります。

db.tb から a、b、c を選択 制限 10000 オフセット 9000000

しかし、時間は限られています。この問題を解決するより良い方法はあるでしょうか?

改善案

深くページをめくることなくデータを更新する方法はありますか?
はい、自動増分ID列を使用します

データ特性を観察する

この単一のテーブルには、自動増分 ID 列があり、主キーです。データのクエリと更新を行う理想的な方法は、インデックス列に基づいています。

id=9999999 の db.tb から a、b、c を選択します。
db.tb を更新し、a=x、id=9999999 に設定します。

マルチプロセス

各プロセスは特定の ID 範囲内でデータを処理するため、深いページ フリップが回避され、複数のプロセスが同時にデータを処理できるようになります。
データクエリ速度が向上すると、データ処理速度も向上します。
参考までに私が書いたタスク割り当て関数は次のとおりです。

定義ミッションハンドラー(すべてのミッション、ワーカーミッションサイズ):
    「」
    タスク リストは、タスクの合計数と各ワーカーのタスク数に基づいて計算されます。タスク リストの要素は (タスク開始 ID、タスク終了 ID) です。
    例: タスクの総数は 100 で、各ワーカーのタスク数は 40 です。この場合、タスク リストは次のようになります: [(1, 40), (41, 80), (81, 100)]
    :param all_missions: ミッションの総数 :param worker_mission_size: 各ワーカーの最大ミッション数 :return: [(start_id, end_id), (start_id, end_id), ...]
    「」
    ワーカーミッションID = []
    現在のID = 0
    current_id <= all_missions の場合:
        start_id = all_missions if current_id + 1 >= all_missions それ以外の場合は current_id + 1
        end_id = all_missions、if current_id + worker_mission_size >= all_missions、そうでない場合は current_id + worker_mission_size
        start_id == end_idの場合:
            ワーカーミッションID[-1][1] == 開始IDの場合:
                壊す
        ワーカーミッションIDを追加します((開始ID、終了ID))
        現在のID += ワーカーミッションサイズ

    ワーカーミッションIDを返す

単一のテーブル ID の最大値が 100 で、各プロセスで 20 個の ID を処理すると仮定すると、タスク リストは次のようになります。

>>> ミッションハンドラ(100, 40)
[(1, 40), (41, 80), (81, 100)]

それで、
プロセス 1 は、ID が 1 から 40 までのデータのみを処理する必要があります。
プロセス 2 では、ID が 41 から 80 までのデータのみを処理する必要があります。
プロセス 3 では、ID が 81 から 100 までのデータのみを処理する必要があります。

並行.futures から ProcessPoolExecutor をインポートします


main() を定義します:
    # 自動増分 ID の最大値 max_id = 30000000
    # 単一のワーカーによって処理されるデータ量 worker_mission_size = 1000000
    # 複数のプロセスを使用してミッションを処理する = mission_handler(max_id, worker_mission_size)
    労働者 = []
    実行者 = ProcessPoolExecutor()
    idxの場合、enumerate(missions)のミッション:
        start_id、end_id = ミッション
        ワーカー.append(executor.submit(データハンドラー、開始ID、終了ID、idx))


データハンドラを定義します(開始ID、終了ID、ワーカーID):
    合格

アイデアの要約

  1. 深いページめくりを避け、自動増分IDを使用してデータとデータを照会する
  2. 複数のプロセスを使用してデータを処理する

データ処理スキル

後続処理のために、成功した処理と失敗した処理のデータIDを記録する

# 処理ステータスを記録するために別のテーブルを使用します insert into db.tb_handle_status(row_id, success) values ​​(999, 0);

プログラムが異常終了するのを防ぐために、ループ内で例外キャプチャが実行されます。

データハンドラを定義します(開始ID、終了ID、ワーカーID):
    #データ接続 conn、カーソル = mysql()
    現在のID = 開始ID
        試す:
            current_id <= end_id の場合:
                試す:
                    # TODO データ処理コードパス

                except 例外を e として:
                    # TODOレコード処理結果# データは次のcurrent_id += 1に移動する
                    続く
                それ以外:
                    # 例外なし、次のデータの処理を続行 current_id += 1
        except 例外を e として:
            'worker_id({}): result({})'.format(worker_id, False) を返します。
        ついに:
            # データベースリソースの解放 cursor.close()
            接続を閉じる()

        'worker_id({}): result({})' を返します。format(worker_id, True)

可能な限りバッチ送信を使用してデータベースデータを更新する

sql = """db.tb を更新し、a=%s、b=%s を設定します (ID=%s の場合)"""
値 = [
            ('a_value', 'b_value', 9999)、
            ('a_value'、'b_value'、9998)、
            ...
         ]
# ネットワーク IO とロック取得頻度を削減するためのバッチ送信 cursor.executemany(sql, values)

上記は、単一のMySQLテーブルで数千万のデータを処理するアイデアの詳細な内容です。単一のMySQLテーブルで数千万のデータを処理することの詳細については、123WORDPRESS.COMの他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • 数千万のデータを含む MySQL テーブルを最適化するにはどうすればよいでしょうか?
  • 数千万データを持つMySQLテーブルを最適化する実践記録

<<:  ラベルタグの使用時に発生する問題の分析と解決策

>>:  iframe でページを開く方法

推薦する

VMware 仮想マシンの 3 つの接続方法の例の分析

NATこのようにして、仮想マシンのネットワーク カードはホストの VMnet8 に接続されます。この...

div が隠しテキストを超え、div 部分の向こうの CSS コードを隠します

隠れる前に:隠れた後: CS: ...コードをコピーコードは次のとおりです。オーバーフロー:非表示;...

JavaScript関数の使い方の詳細な説明

目次1. 関数を宣言する2. 関数の呼び出し3. 関数パラメータ4. 関数の戻り値5. 議論の使用6...

Nginx リクエスト制限の設定方法

Nginx は、多くの優れた機能を備えた強力で高性能な Web およびリバース プロキシ サーバーで...

VMwareがLinuxシステムをインストールして起動した後に黒い画面が表示される問題を解決する

1. 設置環境1. HUAWEI mate x CPU i5 82500u、8g メモリ、独立グラフ...

canvas.toDataURL image/png エラー処理方法の推奨

問題の背景:再生中のビデオのスクリーンショットを撮る必要があります。ビデオはビデオタグを使用して再生...

html5 の新しいメソッドを使用して JavaScript で要素クラス名を操作する方法の詳細な説明

目次1. classList属性2. 実用化以前の JavaScript では、最初にクラス属性を取...

Centos6.5 で MySQL 5.7.19 をインストールして設定する方法

Centos6.5にmysql5.7.19をインストールするための詳細な手順は次のとおりです。 1....

vuex名前空間の使用

目次Vuex は単一の状態ツリーを使用するため、すべてのアプリケーション状態が比較的大きなオブジェク...

Vuex データの永続性を実装するためのアイデアとコード

vuexとはvuex: vue.js専用に開発された状態管理ツールで、すべてのコンポーネントの状態を...

ローカルストレージにブール型の値を保存する際の落とし穴を解決する

LocalStorageはブール値を保存します今日、ブール値データを保存するために localsto...

Dockerを使用してLaravelおよびVueプロジェクトの開発環境を構築する詳細な説明

この記事では、Docker で構築された Laravel および Vue プロジェクトの開発環境を紹...

Dockerでrabbitmqをデプロイする際に発生した2つの問題

1. 背景DockerでRabbitMQをデプロイする際に、次の2つの問題が発生します。問題1: ス...

Ubuntu MySQL バージョンが 5.7 にアップグレードされました

数日前、図書館はサーバー(Ubuntu 14.04)にセキュリティ上の脆弱性があり、時間通りに修復さ...

Vueはカウンターのシンプルな生成を実装します

この記事では、Vueカウンターの簡単な実装コードを例として紹介します。具体的な内容は以下のとおりです...