Можно ли полагаться на автоматически увеличивающийся первичный ключ в вашей базе данных?

StackOverflow https://stackoverflow.com/questions/845402

Вопрос

В моем нынешнем приложении Rails я разрешаю конфликты планирования путем сортировки моделей по "created_at" поле.Однако я понял, что при вставке нескольких моделей из формы, которая позволяет это, все created_at времена точно такие же!

Это скорее вопрос лучших практик программирования:Может ли ваше приложение полагаться на ваш столбец ID в вашей базе данных, который увеличивается все больше и больше с каждым INSERT чтобы получить их порядок создания?Другими словами, могу ли я отсортировать группу строк, которые я извлекаю из своей базы данных, по их столбцу ID и быть уверенным, что это точная сортировка, основанная на порядке создания?И является ли это хорошей практикой в моем приложении?

Это было полезно?

Решение

Это зависит от поставщика вашей базы данных.

MySQL, я полагаю, абсолютно точно заказывает ключи автоматического увеличения.SQL Server Я не знаю наверняка, работает он или нет, но я верю, что работает.

Где вы столкнетесь с проблемами, так это с базами данных, которые не поддерживают эту функциональность, в первую очередь Oracle, которая использует последовательности, которые примерно, но не абсолютно упорядочены.

Альтернативой может быть переход к созданному времени, а затем к идентификатору.

Другие советы

Сгенерированные идентификационные номера будут уникальными.Независимо от того, используете ли вы Последовательности, как в PostgreSQL и Oracle, или вы используете другой механизм, такой как автоматическое увеличение MySQL.

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

Поэтому вам не следует использовать сгенерированное поле id для подобной задачи, чтобы не полагаться на детали реализации базы данных.

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

INSERT INTO A (data, created) VALUES (smething, DATE())
UPDATE A SET data=something, updated=DATE()

Я полагаю, что ответ на ваш вопрос - да...если я читаю между строк, я думаю, вы обеспокоены тем, что система может повторно использовать идентификационные номера, которые "отсутствуют" в последовательности, и поэтому, если вы использовали 1,2,3,5,6,7 в качестве идентификационных номеров, во всех известных мне реализациях следующий идентификационный номер всегда будет 8 (или, возможно, выше), но я не знаю ни одной базы данных, которая пыталась бы выяснить, что идентификатор записи # 4 отсутствует, поэтому попытайтесь повторно использовать этот идентификационный номер.

Хотя я лучше всего знаком с SQL Server, я не понимаю, зачем любому поставщику, пытающемуся заполнить пробелы в последовательности, думать о накладных расходах на ведение этого списка неиспользуемых идентификаторов, в отличие от того, чтобы просто всегда отслеживать последний использованный номер I и добавлять 1.

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

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

Для установки времени создания вы можете просто использовать значение по умолчанию, подобное этому

CREATE TABLE foo (
  id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL;
  created TIMESTAMP NOT NULL DEFAULT NOW();
  updated TIMESTAMP;
  PRIMARY KEY(id);
) engine=InnoDB; ## whatever :P

Теперь это позаботится о времени создания.что касается времени обновления, я бы предложил триггер AFTER UPDATE, подобный этому (конечно, вы можете сделать это в отдельном запросе, но триггер, на мой взгляд, является лучшим решением - более прозрачным):

DELIMITER $$
CREATE TRIGGER foo_a_upd AFTER UPDATE ON foo
FOR EACH ROW BEGIN
  SET NEW.updated = NOW();
END;
$$
DELIMITER ;

И это должно сработать.

Редактировать:Горе мне.По глупости я не уточнил, что это для mysql, могут быть некоторые различия в именах функций (а именно, 'NOW') и другие мелкие нюансы.

Одно предостережение к ответу EJB:

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

FWIW, я обычно использую order by ID как эффективную версию order by created_at.Это дешевле в том смысле, что не требует добавления индекса к полю datetime (которое больше и, следовательно, медленнее, чем простой целочисленный индекс первичного ключа), гарантированно будет отличаться, и меня действительно не волнует, если несколько строк, которые были добавлены примерно в одно и то же время, будут отсортированы в каком-то немного другом порядке.

Вероятно, это зависит от движка DB.Я бы проверил, как ваша база данных реализует последовательности, и если нет документированных проблем, то я бы решил положиться на ID.

Например. Последовательность Postgresql это нормально, если вы не играете с параметрами кэша последовательностей.

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

Мой совет - полагаться на идентификаторы, сгенерированные последовательностью, и продвигать свой проект вперед.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top