Поиск по сайту:
Продолжать смеяться легче, чем окончить смех (К. Прутков).

Поддержка Javascript в MySQL: пример UUID

28.04.2024
Поддержка Javascript в MySQL: пример UUID

Возможно, вы заметили, что MySQL теперь поддерживает создание функций (и процедур хранения) в Javascript с использованием GraalVM.

Эта новая функциональность доступна только в MySQL Enterprise и MySQL HeatWave.

Как разработчик, вы также можете получить бесплатный доступ к MySQL Enterprise из Oracle Technology Network (OTN): Загрузка MySQL Enterprise.

 

Зачем использовать JS-функцию?

Как вы, возможно, знаете, UUID становятся все более популярными, и их использование в MySQL ограничено UUID V1.

Итак, мы знаем, что можно извлечь временную метку из UUIDv1. Есть компонент MySQL (C ++), который предоставляет 3 UDF (определяемые пользователем функции) для этой цели. Компонент доступен на GitHub: mysql-component-uuid_v1.

При использовании MySQL DBaaS невозможно установить такие компоненты, и то же самое происходит с MySQL HeatWave. Следовательно, возможность использования функций JavaScript становится особенно выгодной в этом сценарии.

 

Функции для обработки UUIDv1

Затем мы создадим функции для анализа UUID MySQL и отображения метки времени.

Давайте начнем с извлечения временной метки как времени Unix в миллисекундах:

USE test;
DROP function IF EXISTS js_uuid_to_unixtime;
CREATE FUNCTION js_uuid_to_unixtime (uuid_in CHAR(36))
RETURNS CHAR(23) LANGUAGE JAVASCRIPT AS $$
    
const UUID_T_LENGTH = 16;
const UNIX_TS_LENGTH = 6;

function uuidToUnixTs(uuid_str) {
    const MS_FROM_100NS_FACTOR = 10000;
    const OFFSET_FROM_15_10_1582_TO_EPOCH = 122192928000000000n;

    // Разделите UUID символом "-" в качестве разделителя
    let uuid_parts = uuid_str.split('-');

    // Создайте временную метку UUID из ее частей
    let uuid_timestamp =
        uuid_parts[2].substring(1) +
        uuid_parts[1] +
        uuid_parts[0];

    // Преобразовать строку шестнадцатеричной метки времени в целое число
    let timestamp = BigInt('0x' + uuid_timestamp);

    // Вычислить временную метку Unix в миллисекундах
    let unixTimestampMs = Number((timestamp - OFFSET_FROM_15_10_1582_TO_EPOCH) / BigInt(MS_FROM_100NS_FACTOR));

    return unixTimestampMs;
}

function stringToUuid(str) {
    if (str.length !== 36) {
        return 1;
    }
    if (str[14] !== '1') {
        return 1;
    }
    return 0;
}

let result = stringToUuid(uuid_in);
let timestamp_out;
if (result === 0) {
    timestamp_out = uuidToUnixTs(uuid_in)/1000;
} else {
    timestamp_out="Error parsing UUID";
}

return (timestamp_out);

$$    

;

 

Давайте протестируем это:

MySQL > select now(), from_unixtime(js_uuid_to_unixtime(uuid()));
+---------------------+--------------------------------------------+
| now()               | from_unixtime(js_uuid_to_unixtime(uuid())) |
+---------------------+--------------------------------------------+
| 2024-03-20 22:24:13 | 2024-03-20 22:24:13.503000                 |
+---------------------+--------------------------------------------+
1 row in set (0.0009 sec)

 

Мы создали другие функции Javascript, предлагающие другой результат:

  • js_uuid_to_datetime()
  • js_uuid_to_datetime_long()

 

Давайте посмотрим на них в действии:

MySQL > select js_uuid_to_datetime(uuid());
+-----------------------------+
| js_uuid_to_datetime(uuid()) |
+-----------------------------+
| 2024-03-20 22:31:20.824     |
+-----------------------------+
1 row in set (0.0009 sec)

MySQL > select js_uuid_to_datetime_long(uuid());
+----------------------------------------------+
| js_uuid_to_datetime_long(uuid())             |
+----------------------------------------------+
| Wednesday, March 20, 2024 at 10:31:30 PM GMT |
+----------------------------------------------+
1 row in set (0.0012 sec)

 

UUIDv7

Все больше и больше людей используют UUIDv7. К сожалению, они недоступны в MySQL. UUIDv7 являются последовательными и не используют Mac-адрес.

Мы также можем создавать функции Javascript для генерации и обработки UUIDv7 в MySQL HeatWave.

Функции доступны здесь.

Давайте протестируем UUIDv7 в качестве первичного ключа для таблицы:

MySQL > CREATE TABLE `item` (
  `id` varbinary(16) NOT NULL,
  `name` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

MySQL > insert into item values (uuid_to_bin(js_uuidv7()),'item01'),
                                (uuid_to_bin(js_uuidv7()),'item02'), 
                                (uuid_to_bin(js_uuidv7()),'item03');
Query OK, 3 rows affected (0.0060 sec)

MySQL > select * from item;
+------------------------------------+--------+
| id                                 | name   |
+------------------------------------+--------+
| 0x018E5E04BA3376AED34A5B5EB51720A5 | item01 |
| 0x018E5E04BA34732799E01BED0C1A06F9 | item03 |
| 0x018E5E04BA34780F6A683BA37F00CA27 | item02 |
+------------------------------------+--------+
3 rows in set (0.0007 sec)

MySQL > select bin_to_uuid(id) uuid, name from item;
+--------------------------------------+--------+
| uuid                                 | name   |
+--------------------------------------+--------+
| 018e5e04-ba33-76ae-d34a-5b5eb51720a5 | item01 |
| 018e5e04-ba34-7327-99e0-1bed0c1a06f9 | item03 |
| 018e5e04-ba34-780f-6a68-3ba37f00ca27 | item02 |
+--------------------------------------+--------+
3 rows in set (0.0008 sec)

 

Мы также можем получить время создания каждой записи:

MySQL > insert into item values (uuid_to_bin(js_uuidv7()),'item04');
Query OK, 1 row affected (0.0035 sec)

MySQL > select js_uuidv7_to_datetime(bin_to_uuid(id)) insert_date, 
        name from item;
+-------------------------+--------+
| insert_date             | name   |
+-------------------------+--------+
| 2024-03-20 22:39:11.923 | item01 |
| 2024-03-20 22:39:11.924 | item03 |
| 2024-03-20 22:39:11.924 | item02 |
| 2024-03-20 22:41:54.567 | item04 |
+-------------------------+--------+
4 rows in set (0.0041 sec)

 

Для повышения производительности лучше хранить UUID с использованием uuid_to_bin() как BINARY(16). Конечно, если мы планируем использовать и вторичные индексы.

Но, возможно, вы предпочитаете напрямую видеть представление (значение) UUID при запросе таблицы.

Затем мы можем изменить нашу таблицу следующим образом:

MySQL > alter table item add column uuid char(36) 
        generated always as (bin_to_uuid(id)) virtual after id,
        alter column id set invisible;

MySQL > insert into item (id, name) 
        values (uuid_to_bin(js_uuidv7()),'item05');

MySQL > select * from item;
+--------------------------------------+--------+
| uuid                                 | name   |
+--------------------------------------+--------+
| 018e5e04-ba33-76ae-d34a-5b5eb51720a5 | item01 |
| 018e5e04-ba34-7327-99e0-1bed0c1a06f9 | item03 |
| 018e5e04-ba34-780f-6a68-3ba37f00ca27 | item02 |
| 018e5e07-3587-73af-6535-f805bee0cc04 | item04 |
| 018e5e15-12bf-7590-a010-7a5b5457a6c3 | item05 |
+--------------------------------------+--------+
5 rows in set (0.0006 sec)

MySQL > select *, js_uuidv7_to_datetime(uuid) inserted_at from item;
+--------------------------------------+--------+-------------------------+
| uuid                                 | name   | inserted_at             |
+--------------------------------------+--------+-------------------------+
| 018e5e04-ba33-76ae-d34a-5b5eb51720a5 | item01 | 2024-03-20 22:39:11.923 |
| 018e5e04-ba34-7327-99e0-1bed0c1a06f9 | item03 | 2024-03-20 22:39:11.924 |
| 018e5e04-ba34-780f-6a68-3ba37f00ca27 | item02 | 2024-03-20 22:39:11.924 |
| 018e5e07-3587-73af-6535-f805bee0cc04 | item04 | 2024-03-20 22:41:54.567 |
| 018e5e15-12bf-7590-a010-7a5b5457a6c3 | item05 | 2024-03-20 22:57:03.167 |
+--------------------------------------+--------+-------------------------+
5 rows in set (0.0014 sec)

 

Заключение

Возможность писать программы на Javascript непосредственно в MySQL является приятным дополнением, особенно при запуске MySQL HeatWave в облаке, где невозможно установить дополнительные компоненты или плагины.

Для тех, кто владеет такими пользовательскими функциями (UDF), теперь вы можете переписать их в Javascript и использовать там, где MySQL поддерживает GraalVM: MySQL Enterprise и MySQL Heatwave.

 

Наслаждайтесь написанием функций Javascript в MySQL!

Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (1 оценок, среднее: 5,00 из 5)
Загрузка...
Поделиться в соц. сетях:
5 1 голос
Рейтинг статьи
Подписаться
Уведомить о
guest

**ссылки nofollow

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии

Это может быть вам интересно


Рекомендуемое
В будущем SSD-память может стать намного быстрее – как молниеносно.…

Спасибо!

Теперь редакторы в курсе.