
Tenga en cuenta que hay una publicación de seguimiento más actualizada aquí: Almacenamiento de UUID y columnas generadas
Hace unos años, Peter Zaitsev escribió en una publicación titulada «UUID o no UUID»: «Hay una parte basada en la marca de tiempo en UUID que tiene propiedades similares a auto_increment y que podría usarse para tener valores generados en el mismo punto en el tiempo físicamente local en el índice BTREE».
Para esta publicación, he reorganizado la parte de la marca de tiempo de UUID (identificador único universal) e hizo algunos puntos de referencia.
Mucha gente ve el UUID como un carácter (36) y lo usa como un valor de identidad de fila (CLAVE PRIMARIA) porque es único en cada tabla, cada base de datos y cada servidor y permite combinar fácilmente registros de diferentes bases de datos. Pero aquí viene el problema, usarlo como PRIMARY KEY provoca los problemas que se describen a continuación.
Problemas con UUID
- El UUID tiene 36 caracteres que lo hacen voluminoso.
- InnoDB almacena los datos en el orden PRIMARY KEY y todas las claves secundarias también contienen PRIMARY KEY. Luego, tener UUID como CLAVE PRINCIPAL hace que el índice sea más grande para que no se pueda insertar en la memoria
- Las inserciones son aleatorias y los datos están dispersos.
A pesar de los problemas con UUID, la gente todavía lo prefiere porque es ÚNICO en cada tabla, se puede generar en cualquier lugar. En este blog, explicaré cómo almacenar UUID de manera efectiva reorganizando la parte de marca de tiempo de UUID.
estructura UUID
MySQL usa UUID versión 1, que es un número de 128 bits representado por una cadena utf8 de cinco números hexadecimales.
- Los primeros tres números son generados por una marca de tiempo.
- El cuarto número conserva la unicidad temporal en caso de que el valor de la marca de tiempo pierda su monotonicidad (por ejemplo, debido a la hora del día).
- El quinto número es un número de nodo IEEE 802 que proporciona unicidad espacial. Se reemplaza un número aleatorio si este último no está disponible (por ejemplo, porque la computadora host no tiene una tarjeta Ethernet, o no sabemos cómo encontrar la dirección de hardware de una interfaz en su sistema operativo). En este caso, no se puede garantizar la unicidad espacial. Sin embargo, una colisión debe tener una probabilidad muy baja.
La marca de tiempo se asigna de la siguiente manera:
Cuando la marca de tiempo tiene el valor hexadecimal (60 bits): 1d8eebc58e0a7d7. Se establecen las siguientes partes del UUID: 58e0a7d7–eebc–11d8-9669-0800200c9a66. tu 1 antes de que los números más significativos (en 11d8) de la marca de tiempo indiquen la versión de UUID, para los UUID basados en tiempo es 1.
Las partes cuarta y quinta serán en su mayoría constantes si son generadas por un solo servidor. Los tres primeros números se basan en la marca de tiempo, por lo que deben aumentar de forma monótona. Reorganizamos toda la secuencia al acercar el UUID a la secuencia. Esto hace que publicar y recuperar datos recientes sea más rápido. Los guiones (‘-‘) no tienen sentido, así que los eliminamos.
58e0a7d7-eebc-11d8-9669-0800200c9a66 => 11d8eebc58e0a7d796690800200c9a66
evaluación comparativa
Creé tres tablas.
- events_uuid – UUID binario (16) CLAVE PRINCIPAL
- events_int: columna de incremento automático BIGINT adicional y hacerlo como clave principal e índice en la columna UUID
- events_uuid_ordered – Reorganizar el UUID binario (16) como CLAVE PRINCIPAL
Creé tres procedimientos almacenados que insertan archivos aleatorios de 25K a la vez en las tablas respectivas. Hay tres procedimientos almacenados más que requieren procedimientos de inserción aleatorios en un ciclo y también calculan el tiempo necesario para insertar 25 000 filas y datos y el tamaño del índice después de cada ciclo. En total, inserté 25 millones de discos.
-
- Tamaño de datos
Eje Horizontal – Número de inserciones x 25.000
Eje vertical: datos de tamaño en MBEl tamaño de los datos de la tabla UUID es mayor que el de las otras dos tablas.
- Tamaño del índice
Eje horizontal – Número de inserciones x 25.000
Eje vertical – Tamaño del índice en MB - Tamaño total
Eje Horizontal – Número de inserciones x 25.000
Eje vertical – Tamaño total en MB - Tiempo tomado
Eje horizontal – Número de inserciones x 25.000
Eje vertical – Tiempo tomado en segundos
- Tamaño de datos
Para la tabla con UUID como PRIMARY KEY, puede notar que a medida que la tabla crece, el tiempo necesario para insertar filas aumenta casi linealmente. Mientras que para otras mesas, el tiempo empleado es casi constante.
El tamaño de la tabla UUID es casi un 50 % más grande que la tabla UUID solicitada y un 30 % más grande que la tabla con BIGINT como PRIMARY KEY. Comparando la tabla UUID de la tabla BIGINT, el tiempo necesario para insertar las filas y el tamaño son casi iguales. Pero pueden variar ligeramente dependiendo de la estructura del índice.
root @ localhost: ~ # ls -lhtr / media / data / test / | grep ibd -rw-rw —- 1 mysql mysql 13G 24 de julio 15:53 eventos_uuid_ordered.ibd -rw-rw —- 1 mysql mysql 20G 25 de julio 02:27 events_uuid.ibd —- r 1 mysql mysql 15G 25 de julio 07:59 events_int.ibd
radica@anfitrión local:~# ls -lhtr / media / datos / prueba / | grep ibd –rw–rw—- 1 mysql mysql 13G jul 24 15:53 eventos_uuid_ordenados.ibd –rw–rw—- 1 mysql mysql 20G jul 25 02:27 eventos_uuid.ibd –rw–rw—- 1 mysql mysql 15G jul 25 07:59 eventos_int.ibd |
Estructura de la mesa
# 1 events_int CREATE TABLE `events_int` (` count` bigint (20) NOT NULL AUTO_INCREMENT, `id` binary (16) NOT NULL,` unit_id` binary (16) DEFAULT NULL, `event` int (11) DEFAULT NULL, `ref_url` varchar (255) COLLATE utf8_unicode_ci DEFAULT NULL,` Campaign_id` binary (16) COLLATE utf8_unicode_ci DEFAULT », `unique_id` binary (16) COLLATE utf8_unicode_ci DEFAULT (utf8_unicode_ci DEFAULT) (v) COLLATE utf8_unicode_ci DEFAULT NULL, `country` varchar (80) COLLATE utf8_unicode_ci DEFAULT NULL,` demand_partner_id` binary (16) DEFAULT NULL, `publisher_id` binary (16) DEFAULT`site NULL`, binary DEFAULT NULL,` página 16 ) DEFAULT NULL, `action_at` datetime DEFAULT NULL, ` impresión` smallint (6) DEFAULT NULL, `click` smallint (6) DEFAULT NULL, ` sold_impression` smallint (6) DEFAULT NULL, `price` decimal (15.7) DEFAULT ‘0.0000000’, `actioned_at` timestamp NOT NULL DEFAULT ‘ 0000-00-00 00:00:00′,’ unique_ads’ varchar (255) COLLATE utf8_unicode e_ci DEFAULT NU LL, `notification_url` text COLLATE utf8_unicode_ci, PRIMARY KEY (` count`), KEY `id` (` id`), KEY `index_events_on_actioned_at` (` actioned_at`), KEY `index_events_unit_andnerid`,` unit_demand_partnerid`_)) = InnoDB CONJUNTO DE CARACTERES POR DEFECTO = utf8 COLLATE = utf8_unicode_ci; # 2 events_uuid CREAR TABLA `events_uuid` (` id` binario (16) NO NULO, `unit_id` binario (16) NULO POR DEFECTO, ~ ~ CLAVE PRIMARIA (` id`), CLAVE `index_events_on_actioned_at` (` actioned_at`), CLAVE `index_events_unit_demand_partner` (` unit_id`, `demand_partner_id`)) MOTOR = InnoDB DEFAULT CHARSET = utf8 COLLATE = utf8_unicode_ci; # 3 events_uuid_ordered CREATE TABLE `events_uuid_ordered` (` id` binary (16) NOT NULL, `unit_id` binary (16) DEFAULT NULL, ~ ~ PRIMARY KEY (` id`), KEY `index_events_on_actioned_at`), (` actioned_at`) `index_events_unit_demand_partner` (` unit_id`, `demand_partner_id`)) MOTOR = InnoDB DEFAULT CHARSET = utf8 COLLATE = utf8_unicode_ci;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 dieciséis 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# 1 eventos_int CREAR MESA `eventos_int` ( `contar` Empezando(20) NO NULO AUTOINCREMENTO, `identificación` binario(dieciséis) NO NULO, `unidad_id` binario(dieciséis) DEFECTO NULO, `evento` En t(11) DEFECTO NULO, `ref_url` varchar(255) COTEJAR utf8_unicode_ci DEFECTO NULO, `campo_id` binario(dieciséis) COTEJAR utf8_unicode_ci DEFECTO », `Identificación única` binario(dieciséis) COTEJAR utf8_unicode_ci DEFECTO NULO, `agente de usuario` varchar(100) COTEJAR utf8_unicode_ci DEFECTO NULO, `ciudad` varchar(80) COTEJAR utf8_unicode_ci DEFECTO NULO, `país` varchar(80) COTEJAR utf8_unicode_ci DEFECTO NULO, `demand_partner_id` binario(dieciséis) DEFECTO NULO, `id_editor` binario(dieciséis) DEFECTO NULO, `Identificación del sitio` binario(dieciséis) DEFECTO NULO, `id_página` binario(dieciséis) DEFECTO NULO, `acción_en` tiempo de datos DEFECTO NULO, `impresión` pequeña(6) DEFECTO NULO, `hacer clic` pequeña(6) DEFECTO NULO, `vender_imprimir` pequeña(6) DEFECTO NULO, `precio` decimal(15,7) DEFECTO ‘0.0000000’, `accionado_en` marca de tiempo NO NULO DEFECTO ‘0000-00-00 00:00:00’, `annuncii_uni` varchar(255) COTEJAR utf8_unicode_ci DEFECTO NULO, `notificación_url` texto COTEJAR utf8_unicode_ci, LA OFICINA DEL ALCALDE LLAVE (`contar`), LLAVE `identificación` (`identificación`), LLAVE `index_events_on_actioned_at` (`accionado_en`), LLAVE `index_events_unit_demand_partner` (`unidad_id`,`demand_partner_id`) ) MOTOR=InnoDB DEFECTO CARÁCTER=utf8 COTEJAR=utf8_unicode_ci; # 2 eventos_uuid CREAR MESA `eventos_uuid` ( `identificación` binario(dieciséis) NO NULO, `unidad_id` binario(dieciséis) DEFECTO NULO, ~ ~ LA OFICINA DEL ALCALDE LLAVE (`identificación`), LLAVE `index_events_on_actioned_at` (`accionado_en`), LLAVE `index_events_unit_demand_partner` (`unidad_id`,`demand_partner_id`) ) MOTOR=InnoDB DEFECTO CARÁCTER=utf8 COTEJAR=utf8_unicode_ci; # 3 eventos_uuid_pedidos CREAR MESA `eventos_uuid_ordenados` ( `identificación` binario(dieciséis) NO NULO, `unidad_id` binario(dieciséis) DEFECTO NULO, ~ ~ LA OFICINA DEL ALCALDE LLAVE (`identificación`), LLAVE `index_events_on_actioned_at` (`accionado_en`), LLAVE `index_events_unit_demand_partner` (`unidad_id`,`demand_partner_id`) ) MOTOR=InnoDB DEFECTO CARÁCTER=utf8 COTEJAR=utf8_unicode_ci; |
Conclusiones para el almacenamiento de valores UUID
-
- Crear una función para reorganizar los campos UUID y usarlos
DELIMITADOR // CREAR DEFINITOR = `root` @` localhost` FUNCIÓN `ordered_uuid` (uuid BINARY (36)) DEVUELVE binario (16) DETERMINISTIC RETURN UNHEX (CONCAT (SUBSTR (uuid, 15, 4), SUBSTR (uuid, 10, ) 4), SUBSTR (uuid, 1, 8), SUBSTR (uuid, 20, 4), SUBSTR (uuid, 25))); // DELIMITADOR;
LÍMITES // CREAR DEFINIR=`radica`@`anfitrión local` FUNCIÓN `pedido_uuid`(uuid BINARU(36)) DEVOLUCIONES binario(dieciséis) DETERMINISTA REGRESAR UNHEX(CONCAT(SUBSTR(uuid, 15, 4),SUBSTR(uuid, 10, 4),SUBSTR(uuid, 1, 8),SUBSTR(uuid, 20, 4),SUBSTR(uuid, 25))); // LÍMITES ; |
anuncios
INSERTAR EN events_uuid_ordered VALORES (ordered_uuid (uuid ()), ‘1’, ‘M’, ….);
INSERTAR EN eventos_uuid_ordenados VALORES (pedido_uuid(uuid()),‘1’,‘METRO’,....); |
Seleccione
SELECCIONE HEX (uuid), is_active, … DESDE events_uuid_ordered;
SELECCIONE MALEFICIO(uuid),está activo,... SÍ eventos_uuid_ordenados ; |
-
- Definir UUID como binario (16) como binario no tiene un conjunto de caracteres