Как формируется GUID? Программирование - Практика программирования

«Коллеги, есть идеи, как получить последнюю созданную характеристику? Реквизиты полностью идентичны(код, наименование, и т.п.).»© «Насколько я знаю, ссылка не обеспечивает последовательность, а только уникальность.»© «Я сделал по Максимум(Ссылка). Но, чета, мне кажется, это неправильно.»© «Слышал что в ГУИд содержится как раз время создания и по всей логике вещей сортировка по ссылке должна сортировать по моменту создания объекта»© Сколько раз вы слышали такие фразы? На удивление я не обнаружил информации по этой теме, пришлось разбираться самому… Начнем издалека…

Что такое GUID или уникальный идентификатор объекта? GUID (Globally Unique Identifier) - статический уникальный 128-битный идентификатор. Его главная особенность - уникальность, которая позволяет создавать расширяемые сервисы и приложения без опасения конфликтов, вызванных совпадением идентификаторов. Хотя уникальность каждого отдельного GUID не гарантируется, общее количество уникальных ключей настолько велико (2128 или 3,4028?1038), что вероятность того, что в мире будут независимо сгенерированы два совпадающих ключа, крайне мала. GUID состоит из четырех частей разделенных символом тире и содержащих в сумме 32 символа, которые являются шестнадцатеричным представлением 16 байт (128 бит). Т.е. два символа в GUID (октет) – это один байт в шестнадцатеричном виде. Пример GUID: b0d4ce5d-2757-4699-948c-cfa72ba94f86 [1]

Почему используется guid, а не простой auto-increment(indentity)? Для использования гуидов есть 2 причины: - хотим чтобы база данных или какой-нибудь другой сервер(кластер) не имел централизованного управления генерацией ключей - нужно избавиться от проблемы создания одинакового идентификатора на разных рабочих серверах Такие проблемы обычно возникают в распределенной среде исполнения, а кластер серверов позиционируется как распределенный и желательно полностью избежать единой точки выдачи уникальных ключей. Если ваша система не имеет таких требований, вам не нужен UUID. [1] [2]

В чем разница между uuid и guid? UUID это термин из стандарта rfc4122, который опубликует всемирная организация стандартизации eitf. Грубо говоря GUID это то что получилось на практике у Microsoft. Теория различается с практикой так же, как и XML с HTML. [1] [2]

Из чего состоит guid? Определяется типом: - Random: Just use the system’s random-number generator to create a 128-bit number. - Time-based: Create a GUID based on the current time. - Hardware-based: Make a GUID with certain portions based on hardware features, such as the MAC address of a network card. - Content-based (MD5 or SHA-1 hash of data): Create a GUID based on a hash of the file contents. Files with the same contents will get the same GUID. [1]

Как определить версию GUID? Версия гуида определяется в старшем байте 7 октета. b0:d4:ce:5d-27:57-46:99-94:8c-cf:a7:2b:a9:4f:86 [1]

Почему нельзя упорядочить по ссылке, если в ней содержится дата создания? Как уже было описано, guid изначально был придуман для РАСПРЕДЕЛЕННЫХ систем, в которых ПРОБЛЕМА УНИКАЛЬНОСТИ идентификаторов решена полным ОТКАЗОМ ОТ АВТОИНКРЕМЕНТА в пользу СЛУЧАЙНЫХ чисел и специальных техник. GUIDы случайны и неповторяемы по определению и в этом его достоинство и недостаток. Например, в предопределенных элементах и произвольных идентификаторах используется Random GUIDs (Version 4). В «типизированных» же Time-Based GUIDs (Version 1).

Используются разные стандарты? Да, но когда индексам БД приходится работать со случайными значениями ключей(см. B-Tree Insertion) возникают проблемы. [1] [2]

То есть для ссылок может создаваться Random GUID? Только для предопределенных элементов и вручную созданных гуидов.

ГУИДВидНоменклатуры = Новый УникальныйИдентификатор(); ВидНоменклатурыСсылка = Справочники.ВидыНоменклатуры.ПолучитьСсылку(ГУИДВидНоменклатуры); ВидНоменклатурыОбъект = Справочники.ВидыНоменклатуры.СоздатьЭлемент(); ВидНоменклатурыОбъект.УстановитьСсылкуНового(ВидНоменклатурыСсылка); ВидНоменклатурыОбъект.Наименование = «тест»; ВидНоменклатурыОбъект.Записать(); Результат: Ссылка Код Предопределенный Наименование 4ad76228-517f-4496-aa6c-eef36d3de35a 000000001 истина Товар ←- Random UUID (version 3) 01d3ff0d-cc37-4863-adef-72d3b0dbf08a 000000002 истина Продукция 623bca27-dffd-4391-b233-20ca170549d4 000000010 ложь тест 769e3f33-50d7-11e7-bcda-94de807c3939 000000005 ложь 1 ←- Time-based UUID (version 1) 769e3f34-50d7-11e7-bcda-94de807c3939 000000006 ложь 2 769e3f35-50d7-11e7-bcda-94de807c3939 000000007 ложь 3

Первые три - random based, вторые три - time-based. И все-таки? Random UUIDs вызывают деградацию операций вставки. У таких гуидов индексы получаются плохо кластеризованы, дерево поиска максимально широкое. Для обхода этого недостатка был придуман COMB Guid - Combined Guid for the combination of a timestamp. Поэтому когда используюся Time-Based GUIDs для первичных ключей, они получаются более сгруппированными, но никак не последовательными. «Механизм генерации ссылок обеспечивает только их уникальность. Возрастающая последовательность при их генерации не обеспечивается.» © БГ [1]

Но у гуидов есть же последовательность? Что-то там про МоментВремени? Да сколько можно? Нет у гуидов последовательности! Кто первый запросил - тому и выдается пул. А когда уж сеанс его исчерпает - зависит от него самого. Читаем подробнее про эксперимент с МоментомВремени. infostart.ru/public/84177/ Можно ли вытащить время из гуида? Можно. Но не нужно. bdb62d89-cede-11e4-b12b-d4ae52b5e909 Алгоритм: дата содержится в первых символах, bdb62d89-cede-11e4 которые нужно переставить задом наперед: 11e4-cede-bdb62d89 первый символ отбрасываем, убираем «лишние» знаки «-»(тире) интервал в десятых долях микросекунд (HEX) получается равным: интервал16= 1E4CEDEBDB62D89 переводим его в десяничный интервал интервал10 = HexToDec(интервал16); в результате получаем: интервал10 = 136 461 344 788 852 105 находим интервал в секундах: интервалСек = интервал10 / 10 000 000; Делаем сдвиг даты от 15.10.1582 г. + 13 646 134 478 + сдвиг на часовой пояс (Московское время) от «мирового времени» (GMT) = 20.03.2015 16:54:38 [1] [2] [3] Почему части времени идут «задом-наперед»? «Так сложилось» ;) Например потому что guid'ы появились задолго до того, как до них добрались руки ietf и баз данных. Или потому что платформа написана на C, а не на Java, а как мы знаем из асемблера архитектура x86 имеет little-endian byte order. Или, как говорит википедия, использовалось 2 варианта: для передачи по сети «on-wire» «network» (big-endian) byte order, а для хранения «native» (little-endian) byte order. В любом случая я не знаю как там было и можно только догадываться. [1] [2] [3] [4] А последние две части что значат? bdb62d89-cede-11e4-b12b-d4ae52b5e909 Счетчик «уникальности» и физический MAC-адрес. Почему нельзя использовать время из GUID? Во-первых, гуид может быть случайным, а не основаным на времени. Во-вторых, гуиды выдаются пулом по 32 штуки для каждого сеанса. В-третьих, гуид случаен по своему стандарту и время в нем это лишь способ сгруппировать первичные ключи для уменьшения ширины В-дерева и ускорения операций вставки в кластерный индекс! [1] [2] [3] Почему используется «перевернутый» формат UUID внутри 1с? <Объект не найден> (273:a97b00191785092e11e36c5fb319c416) Не знаю. [1] Есть же спецификация? Есть. bdb62d89-cede-11e4-b12b-d4ae52b5e909 Layout 0 1 2 3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | time_low | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | time_mid | time_hi_and_version | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |clk_seq_hi_res | clk_seq_low | node (0-1) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | node (2-5) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Bit mask FFFFFFFF-0000-0000-0000-000000000000 time_low 00000000-FFFF-0000-0000-000000000000 time_mid 00000000-0000-F000-0000-000000000000 version 00000000-0000-0FFF-0000-000000000000 time_hi 00000000-0000-0000-C000-000000000000 variant 00000000-0000-0000-3FFF-000000000000 clock_seq 00000000-0000-0000-0000-FFFFFFFFFFFF node Byte order Field Data Type Octet Note # time_low unsigned 32 0-3 The low field of the bit integer timestamp time_mid unsigned 16 4-5 The middle field of the bit integer timestamp time_hi_and_version unsigned 16 6-7 The high field of the bit integer timestamp multiplexed with the version number clock_seq_hi_and_rese unsigned 8 8 The high field of the rved bit integer clock sequence multiplexed with the variant clock_seq_low unsigned 8 9 The low field of the bit integer clock sequence node unsigned 48 10-15 The spatially unique bit integer node identifier Расшифровываю: Timestamp - это 60-битное число, содержащее количество 100-наносекундных интервалов с 15 октября 1582 г. Часть low обнуляется каждый 2^32 / 10^7 / 3600 ~ 1 час, часть mid каждые 7 лет, часть hi сами представляете. Version - старшие 4 бита в седьмом октете, содержат тип гуида. 0x0001 1 time-based version 0x0010 2 DCE Security version (POSIX UIDs) 0x0011 3 name-based version (MD5 hashing) 0x0100 4 randomly generated version 0x0101 5 name-based version (SHA-1 hashing) Clock Sequence - используется чтобы избежать появления дубликатов, когда часы переводятся назад или меняется идентификатор узла. Если предыдущее значение счетчика известно - то увеличивается на единицу, иначе берется случайное число. Node - содержит физический MAC-адрес сервера. Дада, проверьте ipconfig /all ;) Примеры? Есть их у меня. Мы же «программисты», накодим функции: