Есть ли какой-либо вред в сбросе автоинкремента? - PullRequest
6 голосов
/ 21 января 2010

У меня 100 миллионов строк, и оно становится слишком большим. Я вижу много пробелов. (поскольку я удаляю, добавляю, удаляю, добавляю.)

Я хочу заполнить эти пробелы автоинкрементом. Если я сброслю его ... есть ли харМ?

Если я сделаю это, заполнит ли это пробелы?

mysql> ALTER TABLE tbl AUTO_INCREMENT = 1;

Ответы [ 6 ]

9 голосов
/ 21 января 2010

Потенциально очень опасно, потому что вы можете снова получить номер, который уже используется.

То, что вы предлагаете, - это сброс последовательности до 1 снова. Он просто выдаст 1,2,3,4,5,6,7, .. и т. Д., Независимо от того, находятся эти числа в пробеле или нет.

Обновление: Согласно ответу Мартина, из-за опасностей MySQL даже не позволит вам сделать это. Сброс счетчика будет по крайней мере до текущего значения + 1.

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

Если число становится слишком большим, переключитесь на больший тип данных (bigint должно быть много).

6 голосов
/ 21 января 2010

FWIW ... В соответствии с MySQL документами , применяющими

ALTER TABLE tbl AUTO_INCREMENT = 1

, где tbl содержит существующие данные, не должно иметь никакого эффекта:

Чтобы изменить значение Счетчик AUTO_INCREMENT будет использоваться для новые строки, сделайте это:

ALTER TABLE t2 AUTO_INCREMENT = значение;

Вы не можете сбросить счетчик на значение меньше или равно любому уже были использованы. Для MyISAM, если значение меньше или равно максимальное значение в настоящее время в Столбец AUTO_INCREMENT, значение сброс к текущему максимуму плюс один. Для InnoDB, если значение меньше текущее максимальное значение в столбец, ошибка не возникает и текущее значение последовательности не изменяется.

Я провел небольшой тест, который подтвердил это для таблицы MyISAM.

Так что ответы на ваши вопросы таковы: не навреди, и нет, это не заполнит пробелы. Как говорили другие респонденты: изменение типа данных выглядит наименее болезненным выбором.

5 голосов
/ 21 января 2010

Скорее всего, вы ничего не получите от этого, и вы можете легко испортить ваше приложение, перезаписав строки, так как вы собираетесь сбросить счетчик для идентификаторов. (Другими словами, в следующий раз, когда вы вставите строку, она перезапишет строку с идентификатором 1, а затем 2 и т. Д.) Что вы получите от заполнения пробелов? Если число становится слишком большим, просто измените его на большее число (например, BIGINT).


Редактировать: Я исправлен. Он ничего не будет делать, что подтверждает мою точку зрения о том, что вы должны просто изменить тип столбца на более большой целочисленный тип. Максимально возможное значение для BIGINT составляет 2 ^ 64, то есть за 18 квинтиллион . Если на данный момент у вас есть только 100 миллионов строк, это должно быть много в обозримом будущем.

2 голосов
/ 21 января 2010

Я согласен с musicfreak ... Максимальное значение для целого числа (int(10)) составляет 4 294 967 295 (без знака грубого). Если вам нужно подняться еще выше, переключение на BIGINT приведет к 18,446,744,073,709,551,615.

1 голос
/ 21 января 2010

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

Вы можете сделать много простоя? Если да, я могу придумать два варианта:

  1. Сбросить / перезагрузить данные. Вы можете сделать это, чтобы не сохранить идентификационные номера. Например, вы можете использовать SELECT ... INTO для копирования данных без идентификаторов в новую таблицу с идентичным DDL. Затем вы удаляете старую таблицу и переименовываете новую таблицу в старое имя. В зависимости от объема данных это может занять заметное время (и временное дисковое пространство).

  2. Вы можете создать небольшую программу для выдачи операторов UPDATE для изменения идентификаторов. Если вы позволите этому работать медленно, это будет «дефрагментировать» ваши идентификаторы с течением времени. Затем вы можете временно остановить вставки (всего минуту или две), обновить последние идентификаторы и перезапустить его. После обновления последних идентификаторов вы можете изменить значение AUTO_INCREMENT на следующее число, и ваша дыра исчезнет. Это не должно вызывать никакого реального простоя (по крайней мере, на InnoDB), но это может занять довольно много времени в зависимости от того, насколько агрессивна ваша программа.

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

0 голосов
/ 21 января 2010

Действительно ли имеет значение наличие пробелов?

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

Тебе действительно нужен суррогатный ключ? В зависимости от данных (вы не упомянули схему) вы можете найти естественный ключ.

...