Различия
Здесь показаны различия между двумя версиями данной страницы.
— |
common_all:priemyraboty:guid [2017/06/19 11:15] (текущий) alexander создано |
||
---|---|---|---|
Строка 1: | Строка 1: | ||
+ | |||
+ | Как формируется GUID? | ||
+ | Программирование - Практика программирования | ||
+ | |||
+ | "Коллеги, есть идеи, как получить последнюю созданную характеристику? Реквизиты полностью идентичны(код, наименование, и т.п.)."(c) "Насколько я знаю, ссылка не обеспечивает последовательность, а только уникальность."(c) "Я сделал по Максимум(Ссылка). Но, чета, мне кажется, это неправильно."(c) "Слышал что в ГУИд содержится как раз время создания и по всей логике вещей сортировка по ссылке должна сортировать по моменту создания объекта"(c) Сколько раз вы слышали такие фразы? На удивление я не обнаружил информации по этой теме, пришлось разбираться самому... | ||
+ | Начнем издалека... | ||
+ | |||
+ | Что такое 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 для первичных ключей, они получаются более сгруппированными, но никак не последовательными. "Механизм генерации ссылок обеспечивает только их уникальность. Возрастающая последовательность при их генерации не обеспечивается." (c) БГ | ||
+ | [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 ;) | ||
+ | |||
+ | Примеры? Есть их у меня. | ||
+ | Мы же "программисты", накодим функции: |