Максимальное значение столбца идентичности в БД SQLite - PullRequest
11 голосов
/ 13 июня 2009

У меня чисто академический вопрос о базах данных SQLite.

Я использую SQLite.net для использования базы данных в моем проекте WinForm, и когда я настраивал новую таблицу, я задумался о максимальных значениях столбца ID.

Я использую IDENTITY для моего [ID] столбца, который в соответствии с SQLite.net DataType Mappings эквивалентен DbType.Int64. Я обычно начинаю свои столбцы идентификаторов с нуля (с этой строкой в ​​качестве тестовой записи) и получаю автоприращение базы данных.

Максимальное значение (Int64.MaxValue) составляет 9 223 372 036 854 775 807. Для моих целей я никогда даже не поцарапаю поверхность при достижении этого максимума, но что происходит в базе данных, которая это делает? Пытаясь прочитать об этом, я обнаружил, что DB2, по-видимому, «оборачивает» значение в отрицательное значение (-9,223,372,036,854,775,807) и увеличивает его оттуда до тех пор, пока база данных не сможет вставить строки, поскольку столбец ID должен быть уникальным.

Это то, что происходит в SQLite и / или других движках баз данных?

Ответы [ 4 ]

24 голосов
/ 13 июня 2009

Я сомневаюсь, что кто-нибудь знает наверняка, потому что, если бы вставлялся миллион строк в секунду, потребовалось бы около 292 471 года, чтобы достичь точки риска оборачивания - и базы данных были вокруг крошечной доли того времени (на самом деле, как и Homo Sapiens; -).

7 голосов
/ 13 июня 2009

IDENTITY на самом деле не является правильным способом автоматического увеличения в SQLite. Это потребует от вас увеличения на уровне приложения. В оболочке SQLite попробуйте:

create table bar (id IDENTITY, name VARCHAR);
insert into bar (name) values ("John");
select * from bar;

Вы увидите, что id просто нулевой. SQLite не придает особого значения IDENTITY, поэтому в основном это обычный (нетипизированный) столбец.

С другой стороны, если вы делаете:

create table baz (id INTEGER PRIMARY KEY, name VARCHAR);
insert into baz (name) values ("John");
select * from baz;

это будет 1, как я думаю, вы ожидаете.

Обратите внимание, что также существует INTEGER PRIMARY KEY AUTOINCREMENT. Основное отличие состоит в том, что AUTOINCREMENT гарантирует, что ключи никогда не будут повторно использоваться. Так что, если вы удалите Джона, 1 никогда не будет повторно использоваться как идентификатор. В любом случае, если вы используете PRIMARY KEY (с необязательным AUTOINCREMENT) и не используете идентификаторы, предполагается, что SQLite завершится с ошибкой SQLITE_FULL, а не обтеканием.

Используя IDENTITY, вы открываете (вероятно, не относящуюся к делу) вероятность того, что ваше приложение будет неправильно обернуто, если база данных была когда-либо заполнена. Это вполне возможно, потому что столбцы IDENTITY в SQLite могут содержать любое значение (включая отрицательные целые числа). Снова попробуйте:

insert into bar VALUES ("What the hell", "Bill");
insert into bar VALUES (-9, "Mary");

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

3 голосов
/ 17 сентября 2010

В документации на http://www.sqlite.org/autoinc.html указано, что ROWID попытается найти неиспользуемое значение путем рандомизации, как только оно достигнет своего максимального числа.

Для AUTOINCREMENT произойдет сбой с SQLITE_FULL при всех попытках вставить в эту таблицу, если в таблице было максимальное значение:

Если в таблице ранее содержалась строка с наибольшим возможным ROWID, новые INSERT не допускаются, и любая попытка вставить новую строку завершится неудачно с ошибкой SQLITE_FULL.

Это необходимо, поскольку AUTOINCREMENT гарантирует монотонное увеличение идентификатора.

1 голос
/ 13 июня 2009

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

Что касается того, что на самом деле произойдет, то совершенно неясно, как база данных справится с этим. Проблема возникает в момент фактического СОЗДАНИЯ идентификатора, который слишком велик для поля, поскольку маловероятно, что механизм внутренне использует тип данных более 64 бит. В этот момент можно только догадываться ... внутренний язык, используемый для разработки движка, может вырваться, число может молча обернуться и просто вызвать нарушение первичного ключа (при условии, что существует конфликтующий идентификатор), мир может прийти к конец из-за переполнения и т. д.

Но прагматично, Алекс прав. Теоретический предел числа строк, участвующих здесь (при условии, что это один-ID для каждой строки, а не какие-либо личность мошенника вставки проделки) будет в основном делают ситуацию спорным, так как к тому времени, что вы, вероятно, можете войти, что многие строки в даже колоссальный уровень вставки мы все равно умрем, так что это не имеет значения:)

...