単一の 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 Workstation 15 Pro に Ubuntu 1804 をインストールするチュートリアル (画像とテキスト付き)

このメモはインストール チュートリアルです。実用的な意味はありません。記録のためだけに書いています。...

Vue の計算プロパティとリスナーの使用の概要

1. 計算プロパティとリスナー1.1 計算プロパティ <!DOCTYPE html> &...

CocosCreatorでクールなレーダーチャートを描く方法

目次序文プレビュー文章グラフィックコンポーネントプロパティ機能グリッドを描く軸角度を計算するスケール...

Docker のコンテナ データ ボリュームの概要

目次Dockerコンテナのデータ量データボリュームの使用方法1: コマンド-vを使用して直接マウント...

Vueフロントエンドパッケージングの詳細なプロセス

目次1. パッケージ化コマンドを追加する2. パッケージ化されたコードを実行する3. パッケージ化し...

HTMLは角丸四角形を簡単に実装します

質問: div+css と配置を使用して角丸四角形を実現するにはどうすればよいですか?ソリューション...

Vue スキャフォールディングでのレンダリングを理解する

Vue スキャフォールディングでは、エントリ ファイル main.js の新しい Vue コードに、...

Linux 名前空間ユーザーの詳細な説明

ユーザー名前空間は Linux 3.8 で追加された新しい名前空間で、ユーザー ID やグループ I...

Win10 の Linux サブシステムを有効にする方法を説明します (詳細な画像とテキスト付き)

今日は、Windows 10 で Linux サブシステムを有効にする方法を紹介します。早速、手順を...

値の転送を実現するために、2つの同じレベルのコンポーネントをVueで作成します。

Vue コンポーネントは接続されているため、コンポーネント間で値を渡す必要があるのは避けられません...

UbuntuでMySQLデータベースファイルディレクトリを変更する方法

序文同社の Ubuntu サーバーは、さまざまなシステムのディレクトリを異なる論理パーティションに配...

ウェブサイトをより高く、よりデザイン的に見せる方法

「ウェブサイトを高級感のあるものにするにはどうすればいいでしょうか? それともデザイン重視にすればい...

Raspberry PiにDockerをインストールする方法

Raspberry Pi は ARM アーキテクチャをベースとしているため、Docker のインスト...

Linuxは、単一のIPをバインドするためにデュアルネットワークカードを実装するためにボンドを使用します。サンプルコード

ネットワークの高可用性を実現するには、複数のネットワーク カードを仮想ネットワーク カードにバインド...

MySql8.023 インストール プロセスの詳細なグラフィック説明 (初回インストール)

まず、MySQL公式サイトからインストールパッケージをダウンロードします。MySQLはオープンソース...