単一の 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 で Nginx+KeepAlived クラスタ デュアルアクティブ アーキテクチャを展開する際の問題と解決策

序文負荷分散には nginx を使用します。アーキテクチャのフロントエンドまたは中間層として、トラフ...

ブルートフォース攻撃を防ぐためのシェルスクリプト設定

シェルスクリプトはアクセス制御を設定し、複数回のログイン失敗後にIPをブロックしてSSHのブルートフ...

Vueはタブ切り替えの虫眼鏡効果を実装します

この記事では、タブ切り替えの虫眼鏡効果を実現するためのVueの具体的なコードを例として紹介します。具...

Docker のタイムゾーンの問題とデータ移行の問題

最新のソリューション: -v /usr/share/zoneinfo/Asia/Shanghai:/...

Windows 環境に mysql-8.0.11-winx64 をインストールする際に発生する問題を解決する

MySQL インストール パッケージをダウンロードします。mysql-8.0.11-winx64 を...

MySQLとOracleの違いを簡単に説明してください

1. Oracle は大規模データベースですが、MySQL は小規模から中規模のデータベースです。O...

Vue のフィルターの適用シナリオの詳細な説明

filterは通常、特定の値をフィルターするために使用されます。たとえば、フィールドが空だが、フロン...

docker を使用して crownblog プロジェクトを Alibaba Cloud にデプロイする方法

フロントエンドプロジェクトのパッケージ化.env.productionを見つけて、自分のIPまたはド...

Linux ipcsコマンドの使用

1. コマンドの紹介ipcs コマンドは、Linux のプロセス間通信機能の状態を報告するために使用...

Nginx は rtmp ライブ サーバーの実装コードを構築します

1. nginxソースディレクトリに新しいrtmpディレクトリを作成し、git clone http...

mysql5.7 以降で my.ini を設定するための詳細な手順

Windows 64 ビット版 MySQL 5.7 以降の解凍パッケージにデータディレクトリ、my-...

自動的にフォーカスを取得する要素入力ボックスの実装

最近のプロジェクトでフォームを作成するときに、コメント ボックスまで自動的にスクロールし、コメント ...

JPQLに基づく純粋なSQL文方式の詳細な説明

JPQL は Java Persistence Query Language の略です。 Java ...

Vue はブラウザのパスワード記憶機能を無効にするサンプル コードを実装します

情報を探すインターネットで見つかったいくつかの方法: autocomplete="off&...

クリック範囲を拡大する入力チェックボックスを実装する方法

XML/HTML コードコンテンツをクリップボードにコピー< div style = &quo...