単一の 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 テーブル マークアップ チュートリアル (14): テーブル ヘッダー

<br />HTML 言語では、タグを使用してテーブルにタイトルを自動的に追加できます。...

カスタム変数を使用した MySQL クエリの最適化

目次並べ替えクエリの最適化変更されたばかりのデータ行を繰り返し取得しないようにする遅延ロードされた結...

JS は複数のタブを切り替えるカルーセルを実装します

カルーセルアニメーションは、ページの外観とインタラクティブなパフォーマンスを向上させることができます...

MySql の集計関数に条件式を追加する方法

MySQL のフィルタリングのタイミングは、集計関数で使用される where 条件と having ...

MySQL でストアド プロシージャを作成し、データ テーブルに新しいフィールドを追加する方法の分析

この記事では、例を使用して、MySQL でストアド プロシージャを作成し、データ テーブルに新しいフ...

Windows Server 2016 に MySQL 5.7.19 の解凍バージョンをインストールするための詳細なチュートリアル

MySQL 5.7.19 winx64 解凍版のインストールチュートリアルを収録しています。具体的な...

HTMLボタンを中央に配置する方法

HTML ボタン自体を中央に配置するにはどうすればよいでしょうか? このアイデアは簡単に見つかります...

js の通常形式の日付と時刻に 0 を自動的に追加する 2 つのソリューション

目次背景解決策1アイデア:コード:解決策2アイデア:要約する参照する背景日付と時間をフォーマットする...

vsftp を使用して Linux で FTP サーバーを構築する (パラメータの説明付き)

導入この章では、主に Linux で FTP サーバーを構築するプロセスを紹介します。習得すべき重要...

Vue3 のリアクティブ関数 toRef 関数 ref 関数の紹介

目次リアクティブ機能使用法: toRef 関数 (理解するだけ)使用法: ref関数レスポンシブデー...

フラッシュプラグインを使用してPCのカメラを呼び出し、TMLページに埋め込む方法

序文この記事を書いた主な理由は、チームリーダーが、ブラウザを使用してコンピューターのカメラを呼び出し...

Linux テキスト検索コマンド find の詳細な使用方法

find コマンドは主にディレクトリやファイルを検索するために使用され、一致のために複数のパラメータ...

MySQLインデックスの詳細

1. インデックスの原則インデックスは、列内の特定の値を持つ行をすばやく見つけるために使用されます。...

コードをセマンティックにする HTML のヒント

HTML のセマンティクスはありふれた問題のようです。Google で検索すると、セマンティクスに関...

HTML に画像が存在しない場合にデフォルトの画像を表示する方法の例

画像リンク <img src="" /> jsを使用してURLが有効...