Стратегии для обработки неавтоинкрементных идентификаторов - PullRequest
1 голос
/ 28 июня 2011

Кто-то недавно предложил мне удалить таблицу автоматического увеличения, используемую исключительно для хранения идентификаторов. Я еще не пошел с этим, я просто исследую, действительно ли это лучшее решение, чем то, что у меня сейчас . Это оставило бы меня с таким столом:

create table tag_translations (
  tag_id int not null,
  language_id int not null,
  tag_name varchar(255),
  primary key (tag_id, language_id)
);

Я собираюсь иметь дубликаты для tag_id, хранящие переводы тега на другие языки.

При добавлении новых тегов мне нужно отказаться от автоматического увеличения тега_id и вместо этого назначить новые идентификаторы вручную. Если это не просто перевод существующего тега, идентификатор должен быть уникальным для новой партии переведенных вставок.

Может ли кто-нибудь объяснить мне простым языком, как это обычно делается? Я думал об этом, но это, кажется, не чище, чем мой предыдущий подход, если у меня есть правильное мышление. Вот то, что я предполагаю, что процесс:

  • Выберите tag_id из tag_translations
  • Выберите наибольшее число в наборе результатов + 1
  • Создать новый запрос (для вставки)
  • Определите некоторую дополнительную стратегию для обеспечения того, чтобы идентификаторы для новых записей tag_id никогда не дублировались, когда теги создаются в более или менее одинаковую микросекунду

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

1 Ответ

2 голосов
/ 28 июня 2011

Для генерации новых идентификаторов тегов есть лучший вариант, чем select max(tag_id) + 1.Вы можете имитировать последовательности / генераторы в MySQL с помощью одного поля и использовать возможность last_insert_id() для получения аргумента.Последовательность создает последовательность:

create table tag_id_seq (id int not null default 0);
insert into tag_id_seq values (0);

После создания последовательности вы можете получить из нее следующий идентификатор с двумя инструкциями, подобными следующим:

update tag_id_seq set id = last_insert_id(id + 1);
select last_insert_id();

last_insert_id() зависит от соединенияТаким образом, первый оператор в основном служит для захвата значения только для соединения, которое его выполнило, а также для обновления последовательности.Второе утверждение просто возвращает значение.Если бы 2 разных соединения выполняли оператор обновления очень близко друг к другу, они оба по-прежнему имели бы разные идентификаторы, скрытые в last_insert_id().

Вы можете заключить это в функцию, в которую вы передаете просто имя последовательностизатем вызывайте его всякий раз, когда вы действительно создаете новый тег.Это будет работать намного лучше, чем ваша таблица tags с единственным столбцом auto_increment.

Вместо того, чтобы начинать с 0 со следующим идентификатором 1, вы можете поднять его даже с текущимиспользуемые идентификаторы:

update tag_id_seq set id = (select coalesc(max(tag_id),0) from tag_translations);

Существуют также варианты оператора update:

  • Некоторым нравится, когда поле id представляет собой следующий идентификатор, а нечем то, что было дано последним идентификатором.В этом случае вы начинаете id как 1 вместо 0, если это новая последовательность, и используете set id = last_insert_id(id) + 1 (с добавлением снаружи).
  • Кроме того, некоторые обстоятельства требуют 'резервируя несколько новых идентификаторов, а не 1 за один раз.В этом случае вы добавите столько, сколько вам нужно.Основываясь на вышеуказанном варианте, предположим, что последовательность имеет значение 11, что означает, что последний полученный id был 10, а 11 - следующий идентификатор.Если вам нужно 7 новых идентификаторов, вы должны использовать set id = last_insert_id(id) + 7.11 извлекается с select last_insert_id(), что означает, что вы будете использовать идентификаторы 11 до 17 (включительно).Последовательность будет обновлена ​​до 18, следующий идентификатор, который будет получен.

Последовательности имеют преимущества во многих обстоятельствах, а вот некоторые:

  • Составключи не могут содержать столбец auto_increment, но вам все равно нужен способ генерирования идентификаторов.
  • Важной особенностью этого стиля выполнения последовательностей в MySQL является поле.Это означает, что вы можете иметь поле, содержащее текущее / следующее значение последовательности почти в любом месте.

    Например, вместо десятков таблиц, по 1 для каждой последовательности, вы можете создать таблицу последовательностей с 1 столбцом для имени последовательности и 1 столбцом для поля текущего / следующего значения.Десятки строк в 1 таблице намного аккуратнее:

    create table sequences (
      seqname varchar(50) primary key,
      id int not null default 0);
    

    (И если таблица InnoDB, вместо блокировки таблицы используется блокировка на уровне строк.)

  • auto_increment в InnoDB может вести себя не так, как вам нравится.При запуске он делает эквивалент select max(id)+1 для сброса счетчика.Это может привести к перемотке и повторному использованию идентификаторов, которые использовались ранее.

...