Вы хотите, чтобы в одном человеке сочетались несочетаемые и даже взаимоисключающие вещи. В результате получите недоспециалиста во всех областях с хорошо подвешенным языком («и швец, и жнец, и на дуде игрец»).
Судя по тексту вакансии Вам нужны три разных человека:
Backend Engineer (Python разработчик инфраструктуры и API для интеграции моделей)
Machine Learning Engineer (специалист по RAG, агентам и пайплайнам на базе LLM)
Applied Scientist (исследователь, улучшающий качество моделей и архитектуры)
Я не поленился сходить на сайт https://gptunnel.ru/, заблудился там, и вижу, что остро необходим еще и Product Designer.
А если вам еще нужен и лидер (хотя мне кажется, что он уже есть), то ищите еще и Project Manager.
Понятно, что бюджет ограничен. Кого-то можно взять на ограниченный срок, не сразу или по совместительству. А может быть он у вас уже и есть, просто хотелось сразу всего и побольше от нового кандидата.
Вот это хотелки у работодателя! От души посмеялся! Интересно, чем заняты остальные 30-50 сотрудников помимо креативной рекламы, если столько хотят взвалить на одного человека? И кто клюнет на такую вакансию? Должно быть, такой же великий комбинатор. Чувство меры иногда полезно.
В свете того, что Китай собирается удорожать доступ к своим LLM, бизнес-идея агрегатора с оплатой по мере использования может действительно взлететь. Пожелаю ему удачи!
Таблица курсов валют. Дата, Валюта, Курс.Объясните здесь смысл поля id?
Валюта российский рубль имела обозначение RUR, а с 1998 года стала RUB. И это не единственный такой пример. Не существует в природе гарантированно неизменных и уникальных натуральных ключей. Например, известны дубликаты ИНН, MAC-адресов. А ключ для связи таблиц (поле id) изменяться не должен.
Каждая таблица ОБЯЗАНА иметь created_at и updated_at Не обязана. Должна быть целесообразность. Не надо категорических суждений.
Та же таблица курсов валют. Ее можно хоть всю передавать, хоть загрузить из интернетов.
В этом случае будет только актуальная таблица. А если в целях аудита понадобится посмотреть или вставить в расчеты ошибочные исторические данные?
Я бы посоветовал: используйте uuid7 для id, если база не требует экстремальной производительности.
Я уже устал опровергать взятый с потолка миф, что UUIDv7 якобы снижает производительность по сравнению с целочисленными ID.
С внешними ключами это еще та морока, не забыть словить какой нибудь каскадный update или delete.
Никаких update или delete с ключами происходить не должно. Ключи должны быть вечными и неизменными. Значения атрибутов и связей могут изменяться с течением времени - для этого есть поля valid_from и valid_to (или их синонимы start_date и end_date).
Внешних ключей (и других ограничений) не должно быть только у таблиц, куда загружаются сырые данные, чтобы загрузка происходила без помех. Потом эти данные всё равно нужно валидировать, прежде чем использовать.
Миграция - слишком громкое слово. Достаточно только заменить прежнюю функцию генерации UUID на uuidv7(). Это возможно всегда, быстро и без побочных эффектов. Ни столбец с типом данных UUID, ни прежние UUID трогать не надо. В одном столбце с типом данных UUID мирно уживаются UUID разных версий. По мере роста количества свежих UUIDv7 скорость работы БД будет увеличиваться.
В-третьих, работает - не трогай.
Значит, еще не припекло. Когда БД начнет с трудом ворочаться, тронете.
Джойны по UUIDv7 и по числовым ID работают одинаково быстро. Сравнение происходит уже по небольшому количеству старших битов UUIDv7, а не по всем 128 битам.
Числовые ID занимают меньше места только на первый взгляд. Ведь при слиянии данных из нескольких таблиц (систем-источников) приходится дублировать данные - теперь уже с новыми уникальными ключами, так как числовые ID совершенно разных записей из разных источников часто совпадают.
В целом статья мне понравилась, но ее нужно "полировать".
-- Распределённая система / микросервисы:
id UUID PRIMARY KEY
DEFAULT gen_random_uuid() -- v4
-- Или генерируйте UUIDv7 на стороне приложения
После появления встроенной функции uuidv7() в PostgreSQL не осталось ни одного разумного аргумента в пользу UUIDv4. Заранее отвечаю тем, кто боится раскрыть дату и время генерации UUIDv7, - функция uuidv7() позволяет исказить эту дату путем смещения значения таймстемпа даже не на дни, а на тысячелетия, причем очень удобным и безопасным способом.
Совершенно непонятно, зачем в случае микросервисов нужно генерировать UUIDv7 на стороне приложения, если есть такая замечательная встроенная функция uuidv7() в PostgreSQL, формирующая таймстемп с точностью 250 наносекунд.
В случае распределенной системы удобно иметь два ключа в записи: один генерится на клиенте (для сверки), а второй на сервере (для лучшей монотонности ключей, первичный ключ) - функцией uuidv7(). Об этом упоминается в RFC 9562:
Applications using a monolithic database may find using database-generated UUIDs (as opposed to client-generated UUIDs) provides the best UUID monotonicity. In addition to UUIDs, additional identifiers MAY be used to ensure integrity and feedback.
Проблема в клиентуре: соискатели не станут тратить еще много часов в сутки на второй сервис, а работодатели тоже не захотят платить второму сервису. Вся клиентура стекается на один сервис. Там соискатели имеют самый широкий выбор работодателей, а работодатели - самый широкий выбор соискателей. Поэтому значимый второй сервис не возникнет, даже если его можно сделать за копейки.
Трудоустройство должно быть организованным рынком, как, например, финансы, где практически все торги внутри страны сосредоточены на одной национальной фондовой бирже. Национальная фондовая биржа - это не бюрократический государственный сервис, но и не частная монополия (в отличие от HH). Ее строго контролируют с одной стороны брокеры (они ее акционеры), а с другой - центральный банк или другой государственный финансовый регулятор. Но к такому строгому, но не забюрократизированному регулированию финансов государства пришли не сразу, а через череду ужасных финансовых кризисов.
В России государство просто закрывает глаза на безобразия дикого рынка труда в IT, ведь техноолигархов всё устраивает - у них тысячи соискателей на одну вакансию. Да и IT отрасль сложная - кто из госчиновников понимает, как ее регулировать?
Есть целый ТК РФ на эту тему, который даже соблюдается обычно.
Это как сталинская конституция - на бумаге всё выглядело просто замечательно. И соблюдалось! Правда, с реальной жизнью это никак не соприкасалось
Да, нужна конкуренция, причём даже не обязательно зарубежная.
Импортозамещенная? Среди аккредитованных компаний? С исключением реального сильнейшего конкурента? В общем, выхолощенная
Есть же дипломы
Я про стандарты отношений между работодателем/рекрутером и кандидатом. Сейчас это не регулируется ничем, кроме благих пожеланий не дискриминировать некоторые категории граждан. В большинстве случаев кандидат "покупает кота в мешке". "Оффер" может скрывать "подводные камни". Реальный отбор кандидатов далеко не всегда делается в истинных интересах работодателя, особенно в крупных и государственных компаниях. Про такую дикость, как отбор по гороскопу, уже упоминали. А есть еще фаворитизм, заемный труд и другие неприглядные практики. Бессрочный трудовой договор в реальности таковым не является (у работодателя масса способов вынудить работника уволиться), и лучше бы это признать в ТК, чтобы заранее защитить интересы сторон соответствующими стимулами и компенсациями
Здесь нужны организационные решения, а не технические, потому что технические решения могут оказаться неверными, да HH и не будет их внедрять - его всё устраивает.
Чего на самом деле не хватает:
Отраслевые стандарты, выработанные с участием всех заинтересованных сторон (не только крупных компаний и вообще не только работодателей, но и, например, заслуженных профессионалов в IT) и подкрепленные законодательством
Пристальное внимание Федеральной антимонопольной службы к проблеме и реабилитация LinkedIn как главного конкурента HH
Реформа трудового законодательства исходя из доктрины, что прием на работу и дальнейшие трудовые отношения - это не частное дело работодателя и кандидата, не традиция, не "дикий рынок" (с правом сильного, непрозрачностью и т.д.), а сфера общественного интереса (но не объект для бюрократизации - я против госсервиса и против госоценки кандидатов). Здесь полезно присмотрется к проверенному позитивному зарубежному опыту (без слепого копирования)
Абсолютно "секурно". Если Вас смущают крики в интернетах про разглашение даты создания записи, то встроенная в PostgreSQL 18 функция генерации UUIDv7 позволяет произвольным образом исказить эту дату - можно сдвинуть значение таймстемпа на любую технически допустимую величину.
по моему опыту лучше когда в пк зашито максимум данных, включая информацию о типе, чтоб всегда заранее знать к какой таблице он принадлежит, а не искать его среди сотен или тысяч
А как же принцип единственной ответственности? Его ведь не зря придумали. Да, он из области ООП, но подходит и для других областей. Как только Вы пытаетесь совместить функцию идентификации еще с чем-то, то функция идентификации сразу начинает страдать. Вот, например, изменится классификация типов или таблицу разобьют на две, и что тогда Вы будете делать? Разработчики RFC 9562 обсуждали, но намеренно исключили из UUID сегменты "тип", "таблица" и вообще любые сегменты с бизнес-данными. Их всегда можно включить в другой столбец, объект JSON и т.п.
Когда вообще может понадобиться искать таблицу, к которой принадлежит UUID? Разве UUID падает с неба, а не берется из заранее известного источника? Если возникает такая проблема, то значит, есть проблема с архитектурой данных. И нужно исправлять архитектуру данных, а не пытаться сделать из первичного ключа универсальный костыль.
Если, например, у Вас несколько однотипных таблиц финансовых инструментов (акции, облигации, опционы) с отличающимся набором столбцов, и Вы ищете финансовый инструмент в нескольких таблицах, то правильнее сделать нормализацию, вынося специфические столбцы тех или иных финансовых инструментов в отдельные связанные таблицы, а одинаковые столбцы объединить в общей таблице.
"Рекомендации", на которые Вы ссылаетесь, содержат также следующее положение:
Implementations that choose to leverage an embedded node id SHOULD utilize UUIDv8.
То есть, это не UUIDv7, а UUIDv8,и Вы не должны описывать свои идентификаторы как UUIDv7 и записывать номер версии 7 в сами идентификаторы (если не докажете, что это абсолютно необходимо). Если же Вы так делаете, то это вообще не UUID, потому что нарушается стандарт RFC 9562. И это не случайная ошибка стандарта, а осознанный выбор разработчиков стандарта, которые специально обсуждали этот момент.
А что касается UUIDv8, то это маргинаньная версия, о которой RFC 9562 говорит следующее:
UUIDv8 provides a format for experimental or vendor-specific use cases. The only requirement is that the variant and version bits MUST be set as defined in Sections 4.1 and 4.2. UUIDv8's uniqueness will be implementation specific and MUST NOT be assumed.
То есть, разработчики стандарта снимают с себя всякую ответственность за такие эксперименты. Таким образом, Ваша цитата - это не "рекомендации", а наоборот, предостережение - не надо так делать! _____________________________
Я прочитал статью по Вашей ссылке. Так вот, судя по этой статье Вы нарушаете еще одно требование RFC 9562 о генерации UUIDv7 предпочтительно в БД:
Applications using a monolithic database may find using database-generated UUIDs (as opposed to client-generated UUIDs) provides the best UUID monotonicity. In addition to UUIDs, additional identifiers MAY be used to ensure integrity and feedback.
И у Вас в статье в качестве первичного ключа используется чудовищный франкенштейн - составной ключ из псевдо-UUIDv7 и recno («естественный» порядковый номер записи в рамках пакета). Хотя вся мотивация разработки UUID заключалась именно в том, что они в чистом виде должны использоваться в качестве первичного ключа. Цитирую RFC 9562:
Modern applications have a need to create and utilize UUIDs as the primary identifier for a variety of different items in complex computational systems, including but not limited to database keys...
Есть реализации uuiv7, где длина случайной части 0 бит, т.е. просто счетчик там.
Такие якобы "реализации" UUIDv7 вообще не являются UUID, потому что не соответствуют стандарту RFC 9562.
А так да, лучше всю свободную часть случайной величиной заполнить. И использование части ее в своих целях (например, для хранения идентификатора узла или типа процесса) не противоречит стандарту, т.к. снаружи все равно получающийся идентификатор остается v7 как есть.
На самом деле это противоречит стандарту RFC 9562. Поэтому это не UUIDv7 и вообще не UUID, а просто какой-то самодельный идентификатор.
В случае многоузловой реализации в структуру UUID рекомендуется добавить значение идентификатора узла (или воркера). Это необходимо для гарантии уникальности UUID, созданных на разных узлах в один момент времени.
То, что Вы рекомендуете, является грубым и ничем не оправданным нарушением положений RFC 9562, описывающих UUIDv7. Уникальность UUIDv7, созданных на разных узлах в одну и ту же миллисекунду, а в PostgreSQL - в интервале 250 наносекунд, (ещё попробуйте попасть в этот интервал и добиться такого совпадения!!!) в полной мере обеспечивается рандомной частью достаточной длины.
Ещё одним важным моментом является то, что последовательно сгенерированные UUID v7, имеющие близкие временные метки, теоретически более уязвимы к атакам перебором.
Ничего подобного.
Даже в самом худшем случае в некоторых реализациях (при использовании длинного счетчика) длина случайной части минимум 32 бита. Угадать счетчик не получится, так как он в нормальных реализациях инициализируется случайным числом каждую миллисекунду.
В PostgreSQL длина случайной части 62 бита. Последовательно перебирать 62 бита - занятие совершенно бесперспективное.
Пользуйтесь встроенной функцией генерации UUIDv7 в PostgreSQL 18, и у вас никогда не будет проблем.
Вот эти мифы, не имеющие ничего общего с действительностью:
Больший размер UUIDv7 (16 байт) якобы "снижает эффективность хранения". Загадочный параметр. Если имеется в виду скорость CRUD операций, то в PostgreSQL для UUIDv7 она такая же, как у автоинкремента (подтверждается бенчмарками, а не сомнительным теоретизированием). Если имеется в виду объем БД, то при использовании UUIDv7 устраняется необходимость в поле таймстемпа created_at, а также устраняется необходимость в замене ключей и, соответственно, в промежуточных таблицах при интеграции данных из нескольких источников. То есть, с использованием UUIDv7 объем БД может даже уменьшиться по сравнению с автоинкрементом
Якобы при использовании UUIDv7 имеется "повышенная сложность реализации, требующая поддержки со стороны библиотек и фреймворков". Это совершенно устаревшие сведения. Все ведущие СУБД и языки программирования уже реализовали встроенные функции генерации UUIDv7 (PostgreSQL и даже SQL Server, правда, без толковой документации), или имеют их в стандартных библиотеках (Python) или в самых популярных библиотеках (Golang, Rust). Для Java тоже есть, но я особо не интересовался
Упорядоченность на основе времени якобы раскрывает информацию о моменте создания объекта. Если неумело пользоваться, то раскрывает. Но в PostgreSQL и в Percona Server for MySQL значение таймстемпа в UUIDv7 можно сдвинуть хоть на несколько тысячелетий вперед (и до 1970 года назад)
Упорядоченность на основе времени якобы требует синхронизации системных часов между инстансами для сохранения корректной последовательности. Разные инстансы синхронизируется не между собой, а с мировым временем (по протоколу NTP и др.). Если инстансы находятся очень далеко друг от друга, то задержку сигнала можно компенсировать сдвигом значения таймстемпа. Если все же последовательность незначительно нарушается, то это никак не влияет на эффективность индексов и скорость работы БД
Якобы структура UUIDv7 менее случайна по сравнению с UUID v4, что может быть недостатком в сценариях, где критична полная непредсказуемость идентификаторов. Хакер, предсказавший значение UUIDv7 для строго по RFC 9562 реализованной функции генерации UUIDv7 (в PostgreSQL, Python, Rust и др.), получит нобелевку и золотой бюст на родине героя. Такое предсказание просто невозможно. И, кстати, таймстемп заметно уменьшает и без того нулевые шансы правильного предсказания. А использование UUIDv7, как и UUIDv4 для контроля доступа и других криптоцелей запрещено стандартом RFC 9562
Ключевым преимуществом UUID якобы стала независимо и гарантировано уникальная генерация идентификаторов в любой точке системы без централизованной координации. Часто можно столкнуться с ошибочными мнениями, что UUIDv7 нужны для распределенных систем, а для одного сервера лучше автоинкремент. Но генерировать UUIDv7 можно и на одном сервере, и UUIDv7 первоначально планировались именно для этого, а не для распределенных систем и генерации на клиенте (это лишь дополнительный бонус). UUIDv4 использовались для объединения данных из нескольких таблиц без необходимости замены ключей, но сильно замедляли работу БД. UUIDv7 разрабатывались с той же целью, но должны были и обеспечили скорость обработки данных как у автоинкремента
Про якобы "минусы" UUIDv7 тоже много чего наврали - понадергали мифов из интернета. В корпоративном блоге уж могли бы делать проверку фактов перед публикацией. Хотя про ужасы натуральных ключей местами хорошо написано - чувствуется выстраданная боль системных аналитиков. Правда, про замену ключей при интеграции систем-источников как-то забыли упомянуть.
Остается ощущение чрезмерно избыточного количества разных типов идентификаторов в сообщении (id, message_id и log_id). Я совершенно уверен, что можно было бы обойтись только message_id (UUIDv7), а процедура разрешения конфликтов при этом была бы вообще не нужна.
Я хочу напомнить, что таймстемп в UUIDv7 - это по сути Всемирное координированное время (UTC), не зависящее от часового пояса, но только отсчитываемое не от 0 года, а от 1970 года в миллисекундах. В каких бы точках планеты не находились участники переписки, у них на часах устройства одно и то же время UTC. Поэтому не нужна никакая синхронизация часов участников - сейчас все компьютеры и телефоны синхронизированы с UTC достаточно точно для мессенджера. Максимальная погрешность в 100 миллисекунд воспринимается человеком как мгновение.
Если сообщения отсортировываются в интерфейсе по message_id (UUIDv7), то это значит, что они отсортированы по моменту отправки. Если сообщение пришло со значительной задержкой, то оно встанет в середину беседы, и его можно выделять как непрочитанное, пока пользователь не уберет его с экрана.
Насколько я понял, процедура разрешения конфликтов полагается на то же самое время UTC отправки сообщения. То есть результат (последовательность сообщений) точно такой же, как и при сортировке по message_id (UUIDv7).
Вы хотите, чтобы в одном человеке сочетались несочетаемые и даже взаимоисключающие вещи. В результате получите недоспециалиста во всех областях с хорошо подвешенным языком («и швец, и жнец, и на дуде игрец»).
Судя по тексту вакансии Вам нужны три разных человека:
Backend Engineer (Python разработчик инфраструктуры и API для интеграции моделей)
Machine Learning Engineer (специалист по RAG, агентам и пайплайнам на базе LLM)
Applied Scientist (исследователь, улучшающий качество моделей и архитектуры)
Я не поленился сходить на сайт https://gptunnel.ru/, заблудился там, и вижу, что остро необходим еще и Product Designer.
А если вам еще нужен и лидер (хотя мне кажется, что он уже есть), то ищите еще и Project Manager.
Понятно, что бюджет ограничен. Кого-то можно взять на ограниченный срок, не сразу или по совместительству. А может быть он у вас уже и есть, просто хотелось сразу всего и побольше от нового кандидата.
Вот это хотелки у работодателя! От души посмеялся! Интересно, чем заняты остальные 30-50 сотрудников помимо креативной рекламы, если столько хотят взвалить на одного человека? И кто клюнет на такую вакансию? Должно быть, такой же великий комбинатор. Чувство меры иногда полезно.
В свете того, что Китай собирается удорожать доступ к своим LLM, бизнес-идея агрегатора с оплатой по мере использования может действительно взлететь. Пожелаю ему удачи!
Это неудачное правило. Тот, кто присылает данные, может изменить свой классификатор, и что тогда делать?
Валюта российский рубль имела обозначение RUR, а с 1998 года стала RUB. И это не единственный такой пример. Не существует в природе гарантированно неизменных и уникальных натуральных ключей. Например, известны дубликаты ИНН, MAC-адресов. А ключ для связи таблиц (поле id) изменяться не должен.
В этом случае будет только актуальная таблица. А если в целях аудита понадобится посмотреть или вставить в расчеты ошибочные исторические данные?
Я уже устал опровергать взятый с потолка миф, что UUIDv7 якобы снижает производительность по сравнению с целочисленными ID.
Никаких update или delete с ключами происходить не должно. Ключи должны быть вечными и неизменными. Значения атрибутов и связей могут изменяться с течением времени - для этого есть поля valid_from и valid_to (или их синонимы start_date и end_date).
Внешних ключей (и других ограничений) не должно быть только у таблиц, куда загружаются сырые данные, чтобы загрузка происходила без помех. Потом эти данные всё равно нужно валидировать, прежде чем использовать.
Для старых версий PostgreSQL рекомендую расширение pg_uuidv7.
Миграция - слишком громкое слово. Достаточно только заменить прежнюю функцию генерации UUID на uuidv7(). Это возможно всегда, быстро и без побочных эффектов. Ни столбец с типом данных UUID, ни прежние UUID трогать не надо. В одном столбце с типом данных UUID мирно уживаются UUID разных версий. По мере роста количества свежих UUIDv7 скорость работы БД будет увеличиваться.
Значит, еще не припекло. Когда БД начнет с трудом ворочаться, тронете.
Это не так.
Джойны по UUIDv7 и по числовым ID работают одинаково быстро. Сравнение происходит уже по небольшому количеству старших битов UUIDv7, а не по всем 128 битам.
Числовые ID занимают меньше места только на первый взгляд. Ведь при слиянии данных из нескольких таблиц (систем-источников) приходится дублировать данные - теперь уже с новыми уникальными ключами, так как числовые ID совершенно разных записей из разных источников часто совпадают.
В целом статья мне понравилась, но ее нужно "полировать".
После появления встроенной функции uuidv7() в PostgreSQL не осталось ни одного разумного аргумента в пользу UUIDv4. Заранее отвечаю тем, кто боится раскрыть дату и время генерации UUIDv7, - функция uuidv7() позволяет исказить эту дату путем смещения значения таймстемпа даже не на дни, а на тысячелетия, причем очень удобным и безопасным способом.
Совершенно непонятно, зачем в случае микросервисов нужно генерировать UUIDv7 на стороне приложения, если есть такая замечательная встроенная функция uuidv7() в PostgreSQL, формирующая таймстемп с точностью 250 наносекунд.
В случае распределенной системы удобно иметь два ключа в записи: один генерится на клиенте (для сверки), а второй на сервере (для лучшей монотонности ключей, первичный ключ) - функцией uuidv7(). Об этом упоминается в RFC 9562:
Проблема в клиентуре: соискатели не станут тратить еще много часов в сутки на второй сервис, а работодатели тоже не захотят платить второму сервису. Вся клиентура стекается на один сервис. Там соискатели имеют самый широкий выбор работодателей, а работодатели - самый широкий выбор соискателей. Поэтому значимый второй сервис не возникнет, даже если его можно сделать за копейки.
Трудоустройство должно быть организованным рынком, как, например, финансы, где практически все торги внутри страны сосредоточены на одной национальной фондовой бирже. Национальная фондовая биржа - это не бюрократический государственный сервис, но и не частная монополия (в отличие от HH). Ее строго контролируют с одной стороны брокеры (они ее акционеры), а с другой - центральный банк или другой государственный финансовый регулятор. Но к такому строгому, но не забюрократизированному регулированию финансов государства пришли не сразу, а через череду ужасных финансовых кризисов.
В России государство просто закрывает глаза на безобразия дикого рынка труда в IT, ведь техноолигархов всё устраивает - у них тысячи соискателей на одну вакансию. Да и IT отрасль сложная - кто из госчиновников понимает, как ее регулировать?
Это как сталинская конституция - на бумаге всё выглядело просто замечательно. И соблюдалось! Правда, с реальной жизнью это никак не соприкасалось
Импортозамещенная? Среди аккредитованных компаний? С исключением реального сильнейшего конкурента? В общем, выхолощенная
Я про стандарты отношений между работодателем/рекрутером и кандидатом. Сейчас это не регулируется ничем, кроме благих пожеланий не дискриминировать некоторые категории граждан. В большинстве случаев кандидат "покупает кота в мешке". "Оффер" может скрывать "подводные камни". Реальный отбор кандидатов далеко не всегда делается в истинных интересах работодателя, особенно в крупных и государственных компаниях. Про такую дикость, как отбор по гороскопу, уже упоминали. А есть еще фаворитизм, заемный труд и другие неприглядные практики. Бессрочный трудовой договор в реальности таковым не является (у работодателя масса способов вынудить работника уволиться), и лучше бы это признать в ТК, чтобы заранее защитить интересы сторон соответствующими стимулами и компенсациями
Здесь нужны организационные решения, а не технические, потому что технические решения могут оказаться неверными, да HH и не будет их внедрять - его всё устраивает.
Чего на самом деле не хватает:
Отраслевые стандарты, выработанные с участием всех заинтересованных сторон (не только крупных компаний и вообще не только работодателей, но и, например, заслуженных профессионалов в IT) и подкрепленные законодательством
Пристальное внимание Федеральной антимонопольной службы к проблеме и реабилитация LinkedIn как главного конкурента HH
Реформа трудового законодательства исходя из доктрины, что прием на работу и дальнейшие трудовые отношения - это не частное дело работодателя и кандидата, не традиция, не "дикий рынок" (с правом сильного, непрозрачностью и т.д.), а сфера общественного интереса (но не объект для бюрократизации - я против госсервиса и против госоценки кандидатов). Здесь полезно присмотрется к проверенному позитивному зарубежному опыту (без слепого копирования)
Может ли поднять человека? Какой статический потолок?
Удастся разъединить. Просто изначально добавьте тот же столбец с идентификатором компании - рядом со столбцом UUIDv7
Абсолютно "секурно". Если Вас смущают крики в интернетах про разглашение даты создания записи, то встроенная в PostgreSQL 18 функция генерации UUIDv7 позволяет произвольным образом исказить эту дату - можно сдвинуть значение таймстемпа на любую технически допустимую величину.
А как же принцип единственной ответственности? Его ведь не зря придумали. Да, он из области ООП, но подходит и для других областей. Как только Вы пытаетесь совместить функцию идентификации еще с чем-то, то функция идентификации сразу начинает страдать. Вот, например, изменится классификация типов или таблицу разобьют на две, и что тогда Вы будете делать? Разработчики RFC 9562 обсуждали, но намеренно исключили из UUID сегменты "тип", "таблица" и вообще любые сегменты с бизнес-данными. Их всегда можно включить в другой столбец, объект JSON и т.п.
Когда вообще может понадобиться искать таблицу, к которой принадлежит UUID? Разве UUID падает с неба, а не берется из заранее известного источника? Если возникает такая проблема, то значит, есть проблема с архитектурой данных. И нужно исправлять архитектуру данных, а не пытаться сделать из первичного ключа универсальный костыль.
Если, например, у Вас несколько однотипных таблиц финансовых инструментов (акции, облигации, опционы) с отличающимся набором столбцов, и Вы ищете финансовый инструмент в нескольких таблицах, то правильнее сделать нормализацию, вынося специфические столбцы тех или иных финансовых инструментов в отдельные связанные таблицы, а одинаковые столбцы объединить в общей таблице.
"Рекомендации", на которые Вы ссылаетесь, содержат также следующее положение:
То есть, это не UUIDv7, а UUIDv8, и Вы не должны описывать свои идентификаторы как UUIDv7 и записывать номер версии 7 в сами идентификаторы (если не докажете, что это абсолютно необходимо). Если же Вы так делаете, то это вообще не UUID, потому что нарушается стандарт RFC 9562. И это не случайная ошибка стандарта, а осознанный выбор разработчиков стандарта, которые специально обсуждали этот момент.
А что касается UUIDv8, то это маргинаньная версия, о которой RFC 9562 говорит следующее:
То есть, разработчики стандарта снимают с себя всякую ответственность за такие эксперименты. Таким образом, Ваша цитата - это не "рекомендации", а наоборот, предостережение - не надо так делать!
_____________________________
Я прочитал статью по Вашей ссылке. Так вот, судя по этой статье Вы нарушаете еще одно требование RFC 9562 о генерации UUIDv7 предпочтительно в БД:
И у Вас в статье в качестве первичного ключа используется чудовищный франкенштейн - составной ключ из псевдо-UUIDv7 и recno («естественный» порядковый номер записи в рамках пакета). Хотя вся мотивация разработки UUID заключалась именно в том, что они в чистом виде должны использоваться в качестве первичного ключа. Цитирую RFC 9562:
_____________________________
Что касается старых версий PostgreSQL, то там для генерации UUIDv7 может использоваться какое-нибудь из имеющихся расширений.
Такие якобы "реализации" UUIDv7 вообще не являются UUID, потому что не соответствуют стандарту RFC 9562.
На самом деле это противоречит стандарту RFC 9562. Поэтому это не UUIDv7 и вообще не UUID, а просто какой-то самодельный идентификатор.
То, что Вы рекомендуете, является грубым и ничем не оправданным нарушением положений RFC 9562, описывающих UUIDv7. Уникальность UUIDv7, созданных на разных узлах в одну и ту же миллисекунду, а в PostgreSQL - в интервале 250 наносекунд, (ещё попробуйте попасть в этот интервал и добиться такого совпадения!!!) в полной мере обеспечивается рандомной частью достаточной длины.
Ничего подобного.
Даже в самом худшем случае в некоторых реализациях (при использовании длинного счетчика) длина случайной части минимум 32 бита. Угадать счетчик не получится, так как он в нормальных реализациях инициализируется случайным числом каждую миллисекунду.
В PostgreSQL длина случайной части 62 бита. Последовательно перебирать 62 бита - занятие совершенно бесперспективное.
Пользуйтесь встроенной функцией генерации UUIDv7 в PostgreSQL 18, и у вас никогда не будет проблем.
Вот эти мифы, не имеющие ничего общего с действительностью:
Больший размер UUIDv7 (16 байт) якобы "снижает эффективность хранения". Загадочный параметр. Если имеется в виду скорость CRUD операций, то в PostgreSQL для UUIDv7 она такая же, как у автоинкремента (подтверждается бенчмарками, а не сомнительным теоретизированием). Если имеется в виду объем БД, то при использовании UUIDv7 устраняется необходимость в поле таймстемпа created_at, а также устраняется необходимость в замене ключей и, соответственно, в промежуточных таблицах при интеграции данных из нескольких источников. То есть, с использованием UUIDv7 объем БД может даже уменьшиться по сравнению с автоинкрементом
Якобы при использовании UUIDv7 имеется "повышенная сложность реализации, требующая поддержки со стороны библиотек и фреймворков". Это совершенно устаревшие сведения. Все ведущие СУБД и языки программирования уже реализовали встроенные функции генерации UUIDv7 (PostgreSQL и даже SQL Server, правда, без толковой документации), или имеют их в стандартных библиотеках (Python) или в самых популярных библиотеках (Golang, Rust). Для Java тоже есть, но я особо не интересовался
Упорядоченность на основе времени якобы раскрывает информацию о моменте создания объекта. Если неумело пользоваться, то раскрывает. Но в PostgreSQL и в Percona Server for MySQL значение таймстемпа в UUIDv7 можно сдвинуть хоть на несколько тысячелетий вперед (и до 1970 года назад)
Упорядоченность на основе времени якобы требует синхронизации системных часов между инстансами для сохранения корректной последовательности. Разные инстансы синхронизируется не между собой, а с мировым временем (по протоколу NTP и др.). Если инстансы находятся очень далеко друг от друга, то задержку сигнала можно компенсировать сдвигом значения таймстемпа. Если все же последовательность незначительно нарушается, то это никак не влияет на эффективность индексов и скорость работы БД
Якобы структура UUIDv7 менее случайна по сравнению с UUID v4, что может быть недостатком в сценариях, где критична полная непредсказуемость идентификаторов. Хакер, предсказавший значение UUIDv7 для строго по RFC 9562 реализованной функции генерации UUIDv7 (в PostgreSQL, Python, Rust и др.), получит нобелевку и золотой бюст на родине героя. Такое предсказание просто невозможно. И, кстати, таймстемп заметно уменьшает и без того нулевые шансы правильного предсказания. А использование UUIDv7, как и UUIDv4 для контроля доступа и других криптоцелей запрещено стандартом RFC 9562
Ключевым преимуществом UUID якобы стала независимо и гарантировано уникальная генерация идентификаторов в любой точке системы без централизованной координации. Часто можно столкнуться с ошибочными мнениями, что UUIDv7 нужны для распределенных систем, а для одного сервера лучше автоинкремент. Но генерировать UUIDv7 можно и на одном сервере, и UUIDv7 первоначально планировались именно для этого, а не для распределенных систем и генерации на клиенте (это лишь дополнительный бонус). UUIDv4 использовались для объединения данных из нескольких таблиц без необходимости замены ключей, но сильно замедляли работу БД. UUIDv7 разрабатывались с той же целью, но должны были и обеспечили скорость обработки данных как у автоинкремента
Про якобы "минусы" UUIDv7 тоже много чего наврали - понадергали мифов из интернета. В корпоративном блоге уж могли бы делать проверку фактов перед публикацией. Хотя про ужасы натуральных ключей местами хорошо написано - чувствуется выстраданная боль системных аналитиков. Правда, про замену ключей при интеграции систем-источников как-то забыли упомянуть.
Вы забыли это: https://docs.python.org/3/library/uuid.html#uuid.uuid7
Остается ощущение чрезмерно избыточного количества разных типов идентификаторов в сообщении (id, message_id и log_id). Я совершенно уверен, что можно было бы обойтись только message_id (UUIDv7), а процедура разрешения конфликтов при этом была бы вообще не нужна.
Я хочу напомнить, что таймстемп в UUIDv7 - это по сути Всемирное координированное время (UTC), не зависящее от часового пояса, но только отсчитываемое не от 0 года, а от 1970 года в миллисекундах. В каких бы точках планеты не находились участники переписки, у них на часах устройства одно и то же время UTC. Поэтому не нужна никакая синхронизация часов участников - сейчас все компьютеры и телефоны синхронизированы с UTC достаточно точно для мессенджера. Максимальная погрешность в 100 миллисекунд воспринимается человеком как мгновение.
Если сообщения отсортировываются в интерфейсе по message_id (UUIDv7), то это значит, что они отсортированы по моменту отправки. Если сообщение пришло со значительной задержкой, то оно встанет в середину беседы, и его можно выделять как непрочитанное, пока пользователь не уберет его с экрана.
Насколько я понял, процедура разрешения конфликтов полагается на то же самое время UTC отправки сообщения. То есть результат (последовательность сообщений) точно такой же, как и при сортировке по message_id (UUIDv7).