обновление ПЕРВИЧНОГО ключа
Wisky
Дата: 17.04.2018 21:33:01
Пишу в этот раздел, т.к мне кажется эта проблема не столько привязана к БД, как к алгоритмированию. Сомневаюсь что моя проблема уникальна.
Есть таблица словаря с тремя полями (ID, CODE, VALUE).
При первоначальной инсталляции сортировка по ID и Value совпадает.
(16,123,АРБУЗ)
(32,123,БАНАН)
(48,123,ВИНОГРАД)
(64,123,ГРУША)
(80,123,ДЫНЯ)
Значение ID прорежено, т.к. ожидалась потребность редко вставлять значения. Сверху падает новая версия словаря, которая сопоставляется с текущей по CODE. Надо обеспечить, что после обновления sort by ID и sort by VALUE будут совпадать, при этом нужно минимизировать количество замен ID, т.к. на них ссылается таблица с полмиллиардом записей.
Wisky
Дата: 17.04.2018 21:41:17
До чего я додумала:
1) определили список новых и обновляемых данных;
2) высчитали ID_L и ID_R текущего значения в старом словаре, если АРБУЗ переименовали в АНАНАС, то 16 попадает в диапазон 0-32, его трогать не надо, а если АРБУЗ переименовали в ВОДЯНАЯ ЯГОДА, то 16 не попадает в диапазон 48-64, следовательно надо переставлять.
Никанор Кузьмич
Дата: 17.04.2018 22:48:50
Wisky
Дата: 17.04.2018 23:34:15
1) Сформировать откорректированную временную таблицу отсортированную по NAME
2) Определить наибольший непрерывный список записей (ВЕРНЫЙ БЛОК), там где сортировки по старому ID и новому NAME совпадают. Блок верных значений делит справочник на три части (НАЧАЛЬНЫЙ БЛОК)+(ВЕРНЫЙ БЛОК)+(КОНЕЧНЫЙ БЛОК)
3) Переставить (сменить ID) последнее значение НАЧАЛЬНОГО БЛОКА на верное место (в середину)
4) Проверить следующее значение на совпадение сортировок и двигаться к началу
5) повторять такую же процедуру для КОНЕЧНОГО БЛОКА
6) в случае если вставка невозможна (нет свободного ID) - критическая ошибка
miksoft
Дата: 18.04.2018 00:09:37
Wisky |
---|
если АРБУЗ переименовали в ВОДЯНАЯ ЯГОДА, то 16 не попадает в диапазон 48-64, следовательно надо переставлять. |
И следом перелопачивать полмиллиарда записей, чтобы заменить ссылку на справочник?
Это не выглядит хорошей идеей.
Dima T
Дата: 18.04.2018 07:21:08
Если это MSSQL то там на связях с нужной таблицей можно задать CASCADE UPDATE, но обязательно на всех связях таблицы. Тогда просто меняешь ID в исходной таблице, а дальше само поменяется. Но это самое плохое решение из всех возможных.
По-хорошему ID менять не надо, т.к. на то он и абстрактный ключ чтобы не нести никакой смысловой нагрузки. Не надо в него вкладывать смысл "ID справочника из другого источника", надо просто добавить поле "ID справочника из другого источника" и в нем меняй.
Wisky
Дата: 19.04.2018 00:34:23
Изменения PK не моя пререгатива. Но то что сортировка по ID совпадает с VALUE наверное удобно, если эта сортировка требуется постоянно, а VALUE длинное. Изменение происходит крайне редко. Например справочник стран.
На текущий момент я рассматриваю такой вариант.
Сформировать временную таблицу или коллекцию id_new, id_old,name_new, status ("новая", "измена","без измен") отсортированную по name_new . Для записей "верно" id_new заполнено. Проверяю последовательно записи в статусе "Измена" на условие id_old between id_new_l and id_new_r. Если верно то id_new=id_old иначе оставить пустым. Затем проставляю пустые id_new.
Никанор Кузьмич
Дата: 19.04.2018 01:30:15
Изначальная задача у вас какая? Пока вопрос выглядит как "хочу левой ногой почесать правое ухо, до какой длины ногти стричь?"
Dima T
Дата: 19.04.2018 07:23:43
Wisky |
---|
Изменения PK не моя пререгатива. Но то что сортировка по ID совпадает с VALUE наверное удобно, если эта сортировка требуется постоянно, а VALUE длинное. Изменение происходит крайне редко. Например справочник стран. |
ИМХО увольнять надо за такое.
Wisky |
---|
На текущий момент я рассматриваю такой вариант. Сформировать временную таблицу или коллекцию id_new, id_old,name_new, status ("новая", "измена","без измен") отсортированную по name_new . Для записей "верно" id_new заполнено. Проверяю последовательно записи в статусе "Измена" на условие id_old between id_new_l and id_new_r. Если верно то id_new=id_old иначе оставить пустым. Затем проставляю пустые id_new. |
В процессе замены учти такую ситуацию:
id_old = 2 id_new = 5 и есть записи с id_old = 5
т.е. поменяв ID с 2 на 5 ты не сможешь понять где новые 5, а где старые.
Cane Cat Fisher
Дата: 19.04.2018 13:02:40
Wisky |
---|
Но то что сортировка по ID совпадает с VALUE наверное удобно, если эта сортировка требуется постоянно, а VALUE длинное |
Если уж действительно встал вопрос производительности при сортировке по строке, и хочется заменить ее сортировкой по int, то можно добавить еще одно поле "ORDER_NUM" int, перезаполнять его по порядку каждый раз при изменении VALUE (раз уж это событие такое редкое), и использовать для сортировки.
Хотя я почему-то сомневаюсь, что эта проблема с производительностью реальна. Меня терзают смутные сомнения. Скажите, а вы вообще ORDER BY используете? Или делаете запрос без ORDER BY, подметили, что порядок строк обычно соответствует ID, и теперь ради сохранения этого призрачного эффекта затеяли вот это все?