Максимальное значение столбца идентификатора в SQLite DB

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

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

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

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

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

Ответ 1

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

Ответ 2

ИДЕНТИФИКАЦИЯ на самом деле не является надлежащим способом автоматического увеличения в SQLite. Это потребует, чтобы вы увеличивали уровень приложения. В оболочке SQLite попробуйте:

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

Вы увидите, что id просто null. 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 никогда не будет повторно использоваться как id. В любом случае, если вы используете PRIMARY KEY (с дополнительным AUTOINCREMENT) и закончите идентификаторы, SQLite должен сбой работать с SQLITE_FULL, а не для переноса.

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

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

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