1

新しいデータベース設計へのかなり大規模なデータベースの移行に取り組んでいます。既存の構造には、異なるストアで表される同じデータの複数のテーブルがありました。

例えば:

`store1_tickets`
--------------------
| id    | customer |
--------------------
|     1 |       29 |
--------------------

`store2_tickets`
--------------------
| id    | customer |
--------------------
|     1 |       54 |
--------------------

現在、次のような表に統合しています。

`tickets`
----------------------------------------
| id    | legacy_id | store | customer |
----------------------------------------
|     1 |         1 |     1 |       29 |
|     2 |         1 |     2 |       54 |
----------------------------------------

このパターンは、いくつかのコンポーネント (顧客、ベンダー、予定など) で繰り返されます。

ETL を INSERT ステートメントに変換する (PHP) スクリプトを作成しています。データを変換している間、新しいチケット ID の現在の合計を保持する必要があります。INSERT ステートメントの後、UPDATE ステートメントを作成して、他のテーブルの対応する ID を変更しています (テーブルの番号を付け直した後customerに、テーブルのフィールドを変更するなど) 。ticketscustomers

UPDATE を (すべての INSERT の後に) 実行して、customer1 を 54 に変更し、54 に達したらそれcustomerを 243 に変更するなど、一種のカスケードを実行させることを恐れています。

ID を正しく修正するにはどうすればよいですか? チケット テーブルは、実際には複数列の auto_increment として使用するため、従来の ID を保持する唯一のテーブルです (各ストアには、表示目的で独自のインクリメント チケット ID が必要です)。複雑なのは、相互に参照するテーブルが非常に多いため、スクリプト内で ID を完全に更新するのが非常に複雑になるためです。

これに対するより良いアプローチ、または更新のカスケードを防ぐ方法はありますか? 私はほとんどの場合id、非常に高い数 (レコード数のために少なくとも 100k である必要があります) でオフを開始し、すべてが完了したら、すべての ID をその値だけ減らすことができます。

4

1 に答える 1

0

私が提案した「高い ID から始める」方法を採用することにしました。

私のスクリプトは次のようになります(実際のコードから非常に単純化されています)。

<?php
    /* Temp ID to add to each legacy ID
       This MUST be MUCH GREATER than any record counts combined can possibly reach
       In my case, all rows in my existing 7 tables (per data type)
       totalled about ~350,000, so I rounded up generously to be safe
    */
    define('TEMP_ID', 400000);

    // Whole process repeated for each store, and numerous types of data
    $query = $db->query('SELECT * FROM store1_tickets');

    // Insert statement
    $insert_sql = 'INSERT INTO tickets SET id = %1$d, legacy_id = %2$d,
        store = 1, customer = %3$d;';

    // Update for other tables linked to this ID
    $update_sql = 'UPDATE logs SET ticket = %1$d WHERE ticket = %2$d;'."\n";
    $update_sql.= 'UPDATE appointments SET ticket = %1$d WHERE ticket = %2$d;';

    // Counter (kept for going between sessions for large datasets)
    $ticket_id = 0;

    while($row = $db->fetch_row($query)){

        /* Insert with temp IDs for references to legacy data
           Note how the legacy id itself is stored un-touched, we are
           just worried about links to other tables
        */
        $sql .= sprintf($insert_sql, ++$ticket_id, $row['id'],
            $row['customer'] + TEMP_ID);

        /* Now I store an update for the tables linked to this ticket
           to update to the new ID from the old (with temp added)
        */
        $patch .= sprintf($update_sql, $ticket_id, $row['id'] + TEMP_ID);

     }

?>

次に、すべてを実行し$sqlて生データを入力し、$patchステートメントを実行してすべてのリンクを修正します。

これらのクエリ (.sql ファイルに保存され、バッチ スクリプトを使用してダンプされます) をすべて実行したら、全体的な「クリーンアップ」クエリをいくつか実行して、必要な場所で ID を減らします。

UPDATE logs SET ticket = ticket - 400000 WHERE ticket > 400000;
UPDATE appointments SET ticket = ticket - 400000 WHERE ticket > 400000;
UPDATE tickets SET customer = customer - 400000 WHERE customer > 400000;

これは、数百のテーブルからの 100MB を超える MySQL データでうまく機能しました。実際のクエリを実行するにはかなりの時間がかかりました (すばらしいスクリプトBigDumpをお勧めします)。

于 2013-10-17T15:10:52.783 に答える