2013-10-12 1 views
1

Я работаю над довольно большой миграцией базы данных в новый дизайн базы данных. Существующая структура имела несколько таблиц для тех же данных, которые были представлены для разных магазинов.MySQL ID Rolling

Например:

`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 | 
---------------------------------------- 

Эта картина повторяется в течение нескольких компонентов (клиентов, поставщиков, назначения ...).

Я делаю сценарий (PHP), чтобы делать ETL в операторы INSERT. Он должен поддерживать общее количество новых идентификаторов билетов при преобразовании данных. После заявления INSERT, творю оператор UPDATE, чтобы изменить соответствующие идентификаторы в других таблицах (например, изменение customer поля в таблице tickets раз я заново пронумеровали customers таблицу.

Я боюсь запуска обновления (после всех вставок) и с его делает вид каскада, где она изменяет customer 1 в 54, а затем, когда он достигает customer 54, изменяя, что в 243, и так далее.

Как я могу правильно ли фиксировать идентификаторы? Таблица билетов является единственной, в которой сохранен старый идентификатор, так как я фактически буду использовать это как многостолбцовый auto_increment (каждый магазин должен иметь свой собственный инкрементный идентификатор билета для целей показа). сложность заключается в том, что существует так много таблиц, которые ссылаются друг на друга, так что это значительно усложняет обновление любых идентификаторов в скрипте.

Есть ли какой-нибудь лучший подход к этому, или каким-либо образом предотвратить переключение UPDATE из каскада? Я почти думаю, что что-то вроде запуска id с действительно большим числом (должно быть по крайней мере 100k из-за количества записей), а затем после того, как все будет сказано и сделано, я мог бы уменьшить все идентификаторы по этому значению.

ответ

0

Я решил пойти с предложенным мной методом «начать с высокого идентификатора».

Мой сценарий выглядит примерно так (SUPER упрощен от реального кода).

<?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 и сбрасываются с использованием пакетного сценария), я запускаю несколько общих «очищающих» запросов, чтобы уменьшить количество идентификаторов, когда нужно.

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; 

Это прекрасно работало для меня с более чем 100 МБ данных MySQL из нескольких сотен таблиц. Взял довольно много времени, чтобы запустить фактические запросы (я рекомендую удивительный скрипт BigDump), но, похоже, все хорошо выглядит до сих пор.

+1

Попробуйте другой подход; дать каждому магазину номер, и каждый «тип вещи» (билет, клиент и т. д.) другой идентификатор. Таким образом, у вас есть шаблон 21xxxxxx (магазин 2, тип: 1, который является клиентом), а затем 22xxxxxx (магазин 2, тип: 2, который является билетом). –

+0

Хм, это звучит немного сложнее, чем необходимо. В моем случае я просто увеличивал/уменьшал все свои константы.Я не боюсь, что идентификаторы клиентов смешиваются с идентификаторами билетов и т. Д., Это было скорее предотвращение повторения итераций запросов UPDATE от перезаписывания ранее записанных записей UPDATE, что привело к постоянному изменению идентификаторов. В моем примере выше, если я повторил клиентов 0-50, я бы изменил клиента с 0 по 25 (новый идентификатор), но тогда мой цикл достиг 25 и изменит его, чтобы сказать новый идентификатор 49 и так далее. Используя большое количество, я гарантирую, что мой цикл никогда не догоняет новые идентификаторы. – Demonslay335