Зачем нужен автоинкремент?

6yrop

если не учитывать вопросы производительности.
У большинства сущностей, если подумать, есть свой естественный идентификатор, его и надо использовать в качестве первичного ключа. Там где его нет нужно использовать guid (это не хуже, а иногда даже более подходит для предметной области).
А проблемы с автоинкрементом есть:
не работает SqlCommandBuilder
не работает DataSet.Merge
P.S. производительность хуйня , время девелоперов дороже

Dasar

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

6yrop

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

Marinavo_0507

Концепция монотонно возрастающего номера записи полезна, если некоторый процесс иногда просматривает таблицу в поисках нового.
Для этого такие номера есть в NNTP и IMAP, например.

bastii

а разве есть ограничения на то как часто можно генерировать guid?
если в цикле генерировать гуиды, то они как-раз и получаются прибавлением 1
причем, думается, что на одной машине, в одну секунду может быть создано огромное кол-во гуидов (т.е. в 128 битах мак адрес и текущее время не все биты съедают)

Ivan8209

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

bastii

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

Dasar

на одной машине (сетевухе) можно генерировать 1guid в 100 наносекунд, т.к. в guid-ах время измеряется в сотнях наносекунд.
Соответственно если гуиды генерить чаще, то не гарантируется уникальность guid-ов.
> т.е. в 128 битах мак адрес и текущее время не все биты съедают
Разве в guid-ах есть свободные биты?

Dasar

> если некоторый процесс иногда просматривает таблицу в поисках нового.
Почему тогда не просто доп. индекс по времени создания?
Зачем это обязательно должно затрагивать первичный ключ?

Ivan8209

Это к тому, что ответы и более обоснованы.
---
...Я работаю антинаучным аферистом...

Ivan8209

А зачем дополнительный индекс, когда и без него можно?
---
...Я работаю дзен-бульдозеристом...

Marinavo_0507

А разве autoincrement-поле всегда обязано быть первичным ключом?
> Почему тогда не просто доп. индекс по времени создания?
С каким разрешением нужно определять время для этого?
Как защитимся от перевода часов назад?
Зачем решать эти проблемы, когда достаточно автоинкремента?

bastii

маза провести эксперимент: в цикле наделать кучу гуидов и посмотреть

Marinavo_0507

> маза провести эксперимент: в цикле наделать кучу гуидов и посмотреть
Microsoft way

Dasar

> маза провести эксперимент: в цикле наделать кучу гуидов и посмотреть
Насколько я помню, функция CreateNewGuid - ждет эти самые 100 наносекунд.

Dasar

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

Dasar

> разве autoincrement-поле всегда обязано быть первичным ключом?
не обязательно, но такие решения редко встречаются
> С каким разрешением нужно определять время для этого?
> Как защитимся от перевода часов назад?
в общем случае, никак
> Зачем решать эти проблемы, когда достаточно автоинкремента?
просто время более честное решение - так ,например, в рамках указанной тобой задачи - если бы записи имели одиннаковый id/время, то это не страшно.
Соответственно может быть, когда создается одномоментно толпа записей - им более правильно ставить один и тот же id/момент времени.
потому что автоинкремент приносить свои проблемы (например, проблему синхронизацию и хранения счетчика).

bastii

а сколько в секунде будет 100 наносекунд?

Dasar

10 в 7-ой

Marinavo_0507

> не обязательно, но такие решения редко встречаются
Это мешает выбрать тебе правильное решение?
> в общем случае, никак
аминь

Dasar

> Это мешает выбрать тебе правильное решение?
В конкретном случае - нет.
Если же вопрос стоит о том, что стоит рекомендовать, или что стоит попробовать заюзать в первую очередь - то, это конечно, guid, т.к. у него меньше потенциальных проблем.

bastii

где правда?
что показывают эксперименты:
10^7 гуидов генерируется
за 2.7-2.8 сек с помощью UuidCreate и
за 0.7-0.9 сек с помощью UuidCreateSequential
CoCreateGuid реализована через UuidCreate
еще интересная инфа из MSDN:

For security reasons, it is often desirable to keep ethernet/token ring addresses on networks from becoming available outside a company or organization. In Windows XP/2000, the UuidCreate function generates a UUID that cannot be traced to the ethernet/token ring address of the computer on which it was generated. It also cannot be associated with other UUIDs created on the same computer. If you do not need this level of security, your application can use the UuidCreateSequential function, which behaves exactly as the UuidCreate function does on all other versions of the operating system.
и
Note The UuidCreateSequential function tends to be slightly faster than the UuidCreate function. When the performance of the generation of a UUID is a significant consideration, the UuidCreateSequential function may be used.

bastii

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

Dasar

Они разные - потому что после генерации (на основе mac-а и времени) - они шифруются.
Для того, чтобы было сложнее отследить на каком комьютере был сгенерен конкретный UUID.

bastii

про 100нс ты похоже прав, хотя быстро не удалось найти этому явного описания в MSDN

Marinavo_0507

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

Dasar

> Очень полезное свойство для первичного ключа в таблице.
что не так?
я же не зря говорил - про "длинные" ссылки.
Длинные ссылки могут в том числе и "убегать" довольно далеко от места своей генерации.
Грубо говоря, ты создал сообщение или файл - назначил ему UUID, а потом оправил это сообщение/файл, а потом через месяц у тебя дома маскишоу устраивают.
Тебе это надо?

Dasar

Если генерить гуиды быстрее, чем за 100 наносекунд, то как быть с уникальностью в следующем сценарии:
за 5 секунд генерим гуидов на 10 лет вперед,
форматируем комп,
ставим новую систему и опять генерим гуиды.
Как гуиды при второй генерации узнают, что они уже вторичны по отношении к первым? И надо генерить какие-то другие гуиды?

vall

эти guid и uuid - OSF DCE compatible Universally Unique Identifier одно и тоже?

Marinavo_0507

> Длинные ссылки могут в том числе и "убегать" довольно далеко от места своей генерации.
Если адрес компьютера зашифрован, то guid не может быть такой ссылкой - как узнать, на каком компьютере искать объект?
А если мы компьютер (и базу, и таблицу в ней) уже знаем, то serial number, сгенерированный на нём, тоже будет ссылкой.

Dasar

да

6yrop

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

Dasar

> Если адрес компьютера зашифрован, то guid не может быть такой ссылкой - как узнать, на каком компьютере искать объект?
Если это тебе надо - то может это лучше сделать честно?
Зачем завязываться на какие-то побочные эффекты?
Сгенери для каждого компьютера GUID, пропиши для каждого такого GUID-а - ip-ы, и пользуй эту таблицу.
Этим ты себе снимешь кучу головной боли - например, смена железу у компьютера, наличие нескольких или отсутствие сетевых карточек и т.д.

Marinavo_0507

> Сгенери для каждого компьютера GUID, пропиши для каждого такого GUID-а - ip-ы, и пользуй эту таблицу.
Маски-шоу тоже посмотрят в эту таблицу.

Dasar

дык, но это уже твои проблемы. Это уже на твоей совести будет защита этой таблицы от вражеского ока.

6yrop

Очень производительное расходование ресурсов при генерации первичного ключа в таблице.
выше было написано, что за 1 с генерится 3 мил guid-ов, пусть одна запись в базе занимает 20 байт, и пусть время генерации занимает 1% производительности компьютера, получаем скорость заполнения базы 0.6Мб/с, в час более 2Tб

Marinavo_0507

> пусть одна запись в базе занимает 20 байт
а что в эти 20 байт поместится-то, кроме первичного ключа?

6yrop

ну я так для худшей оценки взял

Marinavo_0507

> Это уже на твоей совести будет защита этой таблицы от вражеского ока.
Так вот, лучше не оставлять никаких ссылок.
А если нужно, то нужно учитывать, что сложность - враг безопасности.

Dasar

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

bastii

Если генерить гуиды быстрее, чем за 100 наносекунд, то как быть с уникальностью в следующем сценарии:
за 5 секунд генерим гуидов на 10 лет вперед,
форматируем комп,
ставим новую систему и опять генерим гуиды.
Как гуиды при второй генерации узнают, что они уже вторичны по отношении к первым? И надо генерить какие-то другие гуиды?
есть варианты:
если надо быстро, но "редко", то можно организовать пул гуидов
второй вариант, это к 128 битам гуида добавить еще 32 бита
теперь "расширенный гуид" 160 бит, который строим следующим образом:
если для получения гуида не надо ждать 100нс, то сразу получаем гуид и дополгяем нулями остальные биты до 160 бит
если для получения гуида нужно ждать, то берем предыдущий "расширенный гуид" и увеличиваем на 1 число, которое сидит в добавленных 32 битах
просто, я думал, что эти "32 бита" уже зашиты гуиде

Dasar

> если для получения гуида нужно ждать, то берем предыдущий "расширенный гуид" и увеличиваем на 1 число, которое сидит в добавленных 32 битах
Где хранить этот счетчик?
Как быть если мы успели за это время, например, перегрузиться в другую ОС?
или воспользовались другим экземпляром библиотеки, которая тоже генерит UUID-ы?

Dasar

> если надо быстро, но "редко", то можно организовать пул гуидов
Это можно сделать на прикладном уровне.

bastii

а UuidCreateSequential дает такой список
620e539c-7f9a-11d9-ac04-0030847890e7
620e539d-7f9a-11d9-ac04-0030847890e7
620e539e-7f9a-11d9-ac04-0030847890e7
620e539f-7f9a-11d9-ac04-0030847890e7
620e53a0-7f9a-11d9-ac04-0030847890e7
620e53a1-7f9a-11d9-ac04-0030847890e7
620e53a2-7f9a-11d9-ac04-0030847890e7
620e53a3-7f9a-11d9-ac04-0030847890e7
620e53a4-7f9a-11d9-ac04-0030847890e7
620e53a5-7f9a-11d9-ac04-0030847890e7
620e53a6-7f9a-11d9-ac04-0030847890e7
620e53a7-7f9a-11d9-ac04-0030847890e7
620e53a8-7f9a-11d9-ac04-0030847890e7
620e53a9-7f9a-11d9-ac04-0030847890e7
620e53aa-7f9a-11d9-ac04-0030847890e7
620e53ab-7f9a-11d9-ac04-0030847890e7
620e53ac-7f9a-11d9-ac04-0030847890e7
620e53ad-7f9a-11d9-ac04-0030847890e7
620e53ae-7f9a-11d9-ac04-0030847890e7
620e53af-7f9a-11d9-ac04-0030847890e7
620e53b0-7f9a-11d9-ac04-0030847890e7
620e53b1-7f9a-11d9-ac04-0030847890e7
620e53b2-7f9a-11d9-ac04-0030847890e7
620e53b3-7f9a-11d9-ac04-0030847890e7
угадайте какой к меня МАС?

evgen5555

C:\Documents and Settings\Говно>nbtstat -a 

HACKERS:
Адрес IP узла: [172.16.33.18] Код области: []

Таблица NetBIOS-имен удаленных компьютеров

Имя Тип Состояние
----------------------------------------------------
DIMICH <00> Уникальный Зарегистрирован
HACKERS <00> Группа Зарегистрирован
DIMICH <20> Уникальный Зарегистрирован

Адрес платы (MAC) = 00-30-84-78-90-E7

Хуле тут гадать?

vall

libuuid пожет генерировать и по time/mac , но только если об этом попросить, а так она из /dev/urandom генерирует - авось не совпадёт

rosali

Я вот не пойму, а что автоинкримент гарантирует, что возрастать будет именно на единицу? Если нет, и он гарантирует только уникальность, то проблемы с синхронизацией исчезают. Тогда этот самый автоинкримент - самый лучший способ попросить СУБД сделать то, что нам нужно удобным для нее способом...

bastii

620e53b3-7f9a-11d9-ac04-0030847890e7

Marinavo_0507

> Я вот не пойму, а что автоинкримент гарантирует, что возрастать будет именно на единицу?
Нет, это и невозможно в присутствии конкурентных транзакций с возможностью отката.
> Тогда этот самый автоинкримент - самый лучший способ попросить СУБД сделать то, что нам нужно удобным для нее способом...
Дык.

vall

понекрофильствуем.
http://rsdn.ru/article/mag/200301/GUIDEcology.xml
Экология Программирования
Борьба с исчерпанием глобальных ресурсов
Автор: Антон Злыгостев
The RSDN Group
Опубликовано: 21.02.2003
Исправлено: 28.03.2003
Версия текста: {5DCEB4BA-2DCC-4de3-AB06-EED88875A68F}
В последнее время наметилась одна очень нехорошая тенденция: многие разработчики совершенно безответственно относятся к тому, как их приложения используют ресурсы. Да, я понимаю все аргументы, связанные с быстрым ростом производительности аппаратуры и стоимости оптимизации приложений. Кроме того, многие авторитеты последовательно призывают к своевременному освобождению ресурсов, занятых приложением, а также к минимизации ресурсов, используемых одновременно.
Я терпеливо следил за дискуссиями на эту тему, пока один ужасающий факт не привлек мое внимание.
Дело в том, что, когда речь заходит о ресурсах в применении к программированию, обычно подразумеваются локальные ресурсы компьютера, на котором выполняются приложения. И, в большинстве случаев, это восполнимые ресурсы, которые еще и занимаются только на время работы приложения.
Но, как я недавно понял, существует один важный ресурс, который, во-первых, является глобальным, а во-вторых, совершенно невосполнимым!
Я говорю о глобально уникальных идентификаторах, или UUID (также известных как GUID, CLSID, IID и др.). Как следует из документации, каждое обращение к функции WinAPI UuidCreate возвращает уникальный идентификатор! Более того, этот способ настоятельно рекомендуется к применению всякий раз, как в приложении нужно что-либо уникальное. Но ведь очевидно, что все эти идентификаторы берутся из конечного набора! И каждый вызов UuidCreate уменьшает, таким образом, количество идентификаторов, доступных всем приложениям! Стоит также заметить, что не существует никакого способа сдать использованный идентификатор обратно, когда он больше не нужен.
Самое ужасное в том, что исчерпание этого ресурса мгновенно парализует работу всех приложений, которые его используют. К несчастью, их список включает не только поделки, слепленные на коленке полуграмотными подростками. Такие серьезные продукты, как MS SQL Server, используют GUID для идентификации транзакций. На их основе работают многие сервисы, стабильность которых определяет комфорт, а иногда и жизнь людей.
Я не против использования этой технологии вообще. Но многие программисты игнорируют те строки документации по функции CoCreateGuid, в которых рекомендуется использовать ее для получения постоянных идентификаторов в распределенной вычислительной среде:
Use the CoCreateGuid function when you need an absolutely unique number that you will use as a persistent identifier in a distributed environment.
Я вижу несколько решений данной проблемы. Скорее всего, идеально было бы сделать функцию UuidCreate платной. Даже цены в 1 доллар за 1000 GUID было бы достаточно для того, чтобы разработчики задумались о количестве идентификаторов, потребляемых их приложениями. Но пока этот сервис остается бесплатным, я призываю программистов всего мира прекратить безответственную практику использования глобально уникальных идентификаторов для короткоживущих объектов, а также для настольных приложений, в которых можно использовать альтернативные методики получения уникальных идентификаторов (например, последовательности целых чисел).
Я также собираюсь обратиться к компании Microsoft c требованием реализовать функцию UuidDestroy, которая позволит возвращать обратно ставшие ненужными уникальные идентификаторы (я даже боюсь представить это бесчисленное множество уже безвозвратно утерянных GUID!).
Если вы поддерживаете эту акцию, то напишите, пожалуйста, письмо в штаб-квартиру Microsoft в Редмонде по следующему адресу:
Microsoft Corporation
One Microsoft Way
Redmond, WA 98052-6399
USA
я плакалъ.

rid2000

Если с базой работают "несколько" приложений... Не бегать или искать самому максимум...
И второе: например вы добавили 1000 записей с полями 1-1000... затем удалили какие-нибудь (или хоть все инкремент остается (следущая ставка будет 1001)... Это гарантирует уникальность во времени (до переполнения)...

bastii

http://rsdn.ru/article/mag/200301/GUIDEcology.xml
это что шутка такая?

IvanK

вот и я тоже не просек этой фишки

daru

Так должно быть понятнее...

Блин, до чего дожил: собственным ботам приходится азы объяснять
Оставить комментарий
Имя или ник:
Комментарий: