UUID (Universally Unique Identifier) – це стандарт ідентифікації елементів у розробці програмного забезпечення. Це як id auto increment (1,2,3,4…), але UUID це текстовий унікальний 36-символьний ідентифікатор, у форматі 8-4-4-4-12, наприклад – “550e8400-e29b-41d4-a716-446655440000”. На зараз найпопулярніший UUID версії 4, нещодавно з’явився UUID версії 7, але ми будемо говорити про 4 версію.
Якщо говорити про “що краще, UUID чи id auto increment”, тут хочу сказати, що переваг більше саме у UUID. Найголовніша перевага UUID – це глобальна унікальність, тобто кожний згенерований UUID в один і той же час в різних системах, буде унікальний. Це особливо важливо в розподілених системах, де записи можуть створюватися в різних базах даних одночасно. І коли наступить момент міграції даних з однієї бази даних в іншу, UUID збереже свою унікальність, тоді як auto increment значення скоріш за все, викличе конфлікти і потребуватиме додаткової обробки, під час злиття даних.
Також хочеться відмітити про безпеку при використанні UUID, бо auto increment часто передбачувані, оскільки вони йдуть послідовно. Така передбачуваність може бути загрозою у безпеці, оскільки зловмисники можуть спробувати вгадати або вивести ідентифікатори інших записів. UUID, навпаки, проектуються як випадкові та непередбачувані значення, що робить їх безпечнішими за умовчанням.
Якщо говорити про недоліки UUID, можу виділити такі:
1. Через великий розмір UUID може знизитися продуктивність операцій вставки та індексування. Це особливо помітно в базах даних з великою кількістю записів.
2. UUID важче читати та запам’ятовувати людині, а отже це може ускладнювати роботу з даними вручну, зокрема при відладці (дебагінг) або аналізі.
3. Є мізерна ймовірність повторення UUID, ця ймовірність складає 1 до 2^122 (це приблизно 1 до 5.3×10^36). На практиці це означає, що навіть при генерації мільярдів UUID в секунду ймовірність колізії залишається настільки малою, що їй можна знехтувати.
Як же генерувати ці UUID ідентифікатори? Якщо казати про програмування JAVA, тут все просто, є стандартний клас “java.util.UUID”. Щоб згенерувати UUID значення в JAVA, достатньо запустити наприклад, такий код:
import java.util.UUID; public class Test { public static void main(String[] args) { UUID uuid = UUID.randomUUID(); System.out.println(uuid); } }
В базі даних Oracle (ми говоримо зараз про версію 19, а це остання зі стабільних версій), нема вбудованого функціонала для генерації UUID значень. В БД Oracle версії 19 є свій механізм для генерації унікальних ідентифікаторів, і це функція sys_guid() – 32 символьний унікальний ідентифікатор в рамках однієї бази даних Oracle, тобто sys_guid() не глобально унікальний, а унікальний лише в рамках БД. Щоб згенерувати sys_guid() значення в БД Oracle, достатньо запустити наприклад, такий код:
SELECT sys_guid() FROM dual;
sys_guid() у плані безпеки в рази краще ніж id auto increment і я би використовував краще sys_guid() значення для ідентифікація рядка в таблиці. Але що ж робити якщо треба додавати записи в БД Oracle з глобальною унікальністю? В ідеалі програмувати логіку на JAVA, і робити вставку в базу даних зі сторони JAVA, де ми можемо легко генерувати UUID значення.
Але я вам хочу показати, як можна виконувати JAVA код в БД Oracle, звичайним SQL запитом і таким чином генерувати UUID значення за рахунок JAVA, знаходячись в БД. Зараз в БД Oracle створимо “java source” на основі JAVA класа “java.util.UUID, а далі на основі створеного “java source”, створимо звичайну функцію яка викличе JAVA метод randomUUID. Виконаємо такий код в БД Oracle (хочу сказати, що для виконання цього коду, треба спеціальні привілеї, але це вже інша історія):
create or replace and compile java source named "RandomUUID" as public class RandomUUID { public static String create() { return java.util.UUID.randomUUID().toString(); } } / create or replace function RandomUUID return varchar2 as language java name 'RandomUUID.create() return java.lang.String'; /
Після створення функції RandomUUID, її можна викликати звичайним SQL запитом, ось так:
SELECT randomUUID() AS uuid FROM dual;
Мінус в такому підході, коли ми використовуємо тільки базу даних, при вставці багато даних, ми програємо у часі.
Давайте протестуємо, за скільки часу відпрацьовую стандартний sys_guid() та створена наша функція randomUUID().
DECLARE v_guid VARCHAR2(36); BEGIN FOR i IN 1..100000 LOOP v_guid := sys_guid(); -- v_guid := randomUUID(); END LOOP; END; /
Тепер давайте перевіримо швидкість вставки даних через sys_guid() та через randomUUID().
Для цього, створимо таку таблицю
CREATE table test_uuid_data ( uuid varchar2(36), date_record date );
Запустимо цей PL-SQL блок через sys_guid() та через randomUUID().
BEGIN FOR i IN 1..100000 LOOP INSERT INTO test_uuid_data (uuid, date_record) VALUES (sys_guid(), sysdate); -- VALUES (randomUUID(), sysdate); END LOOP; COMMIT; END; /
Записав відео на цьому тему, у моєму youtube каналі: