単一の 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 でページを開く方法

推薦する

HTML はテキストの外側に省略記号を表示します...テキストオーバーフローによって実装されます

div または span に同時に CSS を適用する必要があります。コードをコピーコードは次のとお...

Alibaba Cloud OSS アクセス権設定(RAM 権限制御)実装

シナリオmyBuket の static/material/ ディレクトリなど、Alibaba Cl...

MySQL が重複データを挿入するのを防ぐ 3 つの方法

新しいテーブルを作成する テーブル「人」を作成します( `id` int NOT NULL COMM...

Vue Nativeを使用したモバイルアプリケーションの構築プロセスの完全な記録

目次序文Vue Nativeの機能宣言的レンダリング双方向バインディングVue.js エコシステムの...

mysql5.6.8 ソースコードのインストールプロセス

カーネル: [root@opop ~]# cat /etc/centos-release CentO...

Linux パーティションまたは論理ボリュームにファイルシステムを作成する方法

序文システムにファイル システムを作成し、それを永続的または非永続的にマウントする方法を学習します。...

JDBC-idea で mysql をインポートして java jar パッケージに接続する (mac)

序文1. この記事ではMySQL 8.0バージョンを使用していますバージョン5.0と比較すると、パッ...

CentOS7 64でのMySQL5.6.40の詳細なインストール手順

CentOS7 64でのMySQL5.6.40のインストール手順1) 以前にインストールしたMySQ...

MySQLの結合クエリ、ユニオンクエリ、サブクエリの原理と使用例の詳細な説明

この記事では、例を使用して、MySQL の結合クエリ、結合クエリ、サブクエリの原理と使用方法を説明し...

CSS3 でクールなスライス画像カルーセル効果を実現

今日は、CSS を使用してクールな画像カルーセル コンポーネントを作成する方法を学びます。その原理は...

MySQL SQL ステートメント分析とクエリ最適化の詳細な説明

パフォーマンスの問題のあるSQL文を取得する方法1. ユーザーからのフィードバックを通じてパフォーマ...

モバイル端末での Vue2.x Picker のグローバル呼び出し実装

目次ピッカーコンポーネントとはピッカーコンポーネントの問題解決オプションの説明解決ディレクトリ部門P...

VueのVuexの4つの補助機能について

目次1. 補助機能2. 例1. mapState と mapGetters 2. mapMutati...

ウェブページ読み込み時に左右にジャンプする原因の分析と解決

最近、ウェブサイトを設計するときにこの問題に遭遇しています。メンバーセンターを設計し、コンテンツを ...

mysql5.7 ユーザー権限の作成、ユーザーの削除、権限の取り消し

1. ユーザーを作成します。注文: 'password' によって識別される ...