Comments 9
Есть нюанс: использование кэша повышает производительность, но ценой потери строгой последовательности. При сбое или перезагрузке БД все кэшированные, но не использованные значения теряются, образуя «дырки» в нумерации. Также каждый SEQUENCE требует места в системном каталоге. Следовательно, если требуется гарантированная непрерывность последовательности ключей — что критично для аудита, борьбы с мошенничеством или соблюдения таких норм, как законы о кассовых аппаратах, — кэшированное решение не подходит.
Sequence не гарантирует непрерывности. Если не ошибаюсь то гарантировать непрерывность практически невозможно. Либо возможно но гарантировано угробит производительность.
Если нужен аудит то пишут в конце записи хеш, который вычисляют из прядущего хеша и данных записи. Таким образом нельзя внести изменения в данные.
Про якобы "минусы" UUIDv7 тоже много чего наврали - понадергали мифов из интернета. В корпоративном блоге уж могли бы делать проверку фактов перед публикацией. Хотя про ужасы натуральных ключей местами хорошо написано - чувствуется выстраданная боль системных аналитиков. Правда, про замену ключей при интеграции систем-источников как-то забыли упомянуть.
Упоминаемые недостатки (размер, сложность, предсказуемость) действительно не являются приговором. В статье подсвечиваются риски того, что может быть. Спорить можно только о вероятности появления этого риска. Укажите, пожалуйста, на конкретное утверждение, которое, по вашему мнению, неверно в принципе и такого "не может быть никогда" - мы с благодарностью изучим этот вопрос, возможно и нам это принесет новые знания.
Хотелось бы передать многообразие ключей и причины их появления, поэтому про интеграцию систем и эффективность потоков данных, как раз следующий DWH уровень.
Вот эти мифы, не имеющие ничего общего с действительностью:
Больший размер 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 разрабатывались с той же целью, но должны были и обеспечили скорость обработки данных как у автоинкремента
Этот пример это и показывает. Помимо того, что любой SEQUENCE не гарантирует непрерывность числового ряда. Например, при откате транзакции полученное значение теряется безвозвратно. Но даже в "идеальном мире" — без единого отката — использование CASHE - основная причина разрывов.
И кстати ваш пример с user-name, payments, date в приципе не правильный.
Даже если предположить что user-name строго уникальный, payments сам по себе не может быть уникальным.
Если вы 5 раз заплатили по 1 рублю, то все платежи «одинаковые» вам все равно вернут вам деньги с первого платежи или с последнего.
Поэтом здесь не может быть первичного ключа. Даже если вы впихнете поле id Integer Primary Key, это будет “row id” а не первичный ключ в смысле реляционной теории и бизнес-логики.
Я вообще не знаю как тут можно прикрутить первичный ключ и зачем он тут нужен.
С учетом того, что бизнес-процесс был изначально устроен так, что по одному клиенту мог проводиться только один платеж в день выбор ключа PRIMARY KEY (client_name, payment_date) очевиден. И при возврате вернется именно тот платеж, который был совершен в эту дату этим клиентом.
Бизнес процессы имеют тенденцию меняться. И понятно что не может вот требования один платеж от одного клиента в реальной жизни. Задача изначально была типа сферического коня в вакууме. Если нужна задача для иллюстрации: берите классику: студенты, преподаватели, курсы и оценки. Тогда не придётся придумывать несуществующие ограничения там где их нет
Мне кажется лучше даже не начинать проек с sql базой. За кажущейся легкостью в начале потом настает час расплаты и много боли. Лучше юзать самую простую бд типа ключ значение и хорошо думать как все индексировать на лету. UUID - dense id связи, roaring bitmap и т.д. "Отшардировать" потом будет тоже проще
Ключи в базах данных: больше чем просто идентификатор