¿Cuál es su opinión sobre el uso de UUID como identificadores de filas de bases de datos, particularmente en aplicaciones web?

78

Siempre he preferido usar números enteros largos como claves principales en las bases de datos, por simplicidad y velocidad (supuesta). Pero cuando utilizo un esquema de URL REST o similar a Rails para instancias de objetos, terminaría con URL como esta:

http://example.com/user/783

Y luego se supone que también hay usuarios con ID de 782, 781, ..., 2 y 1. Suponiendo que la aplicación web en cuestión es lo suficientemente segura como para evitar que las personas ingresen otros números para ver a otros usuarios sin autorización, un La clave sustituta asignada secuencialmente simple también "filtra" el número total de instancias (más antiguas que esta), en este caso usuarios, que pueden ser información privilegiada. (Por ejemplo, soy el usuario n. ° 726 en stackoverflow).

¿Un UUID / GUID sería una mejor solución? Entonces podría configurar URL como esta:

http://example.com/user/035a46e0-6550-11dd-ad8b-0800200c9a66

No es exactamente conciso, pero se muestra menos información implícita sobre los usuarios. Claro, huele a "seguridad a través de la oscuridad" que no sustituye a la seguridad adecuada, pero parece al menos un poco más segura.

¿Vale ese beneficio el costo y la complejidad de implementar UUID para instancias de objetos direccionables a través de la web? Creo que todavía querría usar columnas enteras como PK de base de datos solo para acelerar las uniones.

También está la cuestión de la representación en la base de datos de los UUID. Sé que MySQL los almacena como cadenas de 36 caracteres. Postgres parece tener una representación interna más eficiente (¿128 bits?) Pero no lo he probado yo mismo. Alguien tiene alguna experiencia con esto?


Actualización: para aquellos que preguntaron sobre el uso del nombre de usuario en la URL (por ejemplo, http://example.com/user/yukondude ), eso funciona bien para instancias de objetos con nombres que son únicos, pero ¿qué pasa con los miles de millones de sitios web? objetos de la aplicación que realmente solo se pueden identificar por número? Pedidos, transacciones, facturas, nombres de imágenes duplicados, preguntas de stackoverflow, ...

yukondude
fuente

Respuestas:

34

No puedo decir sobre el lado web de su pregunta. Pero los uuids son excelentes para aplicaciones de n niveles. La generación de PK se puede descentralizar: cada cliente genera su propio PK sin riesgo de colisión. Y la diferencia de velocidad es generalmente pequeña.

Asegúrese de que su base de datos admita un tipo de datos de almacenamiento eficiente (16 bytes, 128 bits). Como mínimo, puede codificar la cadena uuid en base64 y usar char (22).

Los he usado mucho con Firebird y los recomiendo.

Douglas Tosi
fuente
18
base64? Si no tiene un tipo de datos nativo para UUID, suelte los guiones y pegue el byte (32). Probablemente sea más rápido que codificar / decodificar a / desde base64 cuando necesite el UUID.
CMircea
29

Por lo que vale, he visto un procedimiento almacenado de larga ejecución (más de 9 segundos) caer a solo unos cientos de milisegundos de tiempo de ejecución simplemente cambiando de claves primarias GUID a enteros. Eso no quiere decir que mostrar un GUID sea una mala idea, pero como otros han señalado, unirse a ellos e indexarlos, por definición, no va a ser tan rápido como con los números enteros.

Adam Tuttle
fuente
1
Si pudiera proporcionar más detalles sobre dónde vio esto, sería útil. ¿Tamaño de DB / tablas? DB backend? Patrón de acceso (¿cómo era la consulta) ... etc.?
Garen
12
¿Cómo es esto siquiera una respuesta?
davidahines
16
Es una evidencia anecdótica que apoya la teoría matemática de que unir e indexar enteros será más rápido que las cadenas largas (más o menos).
Adam Tuttle
23

Puedo responderle que en el servidor SQL, si usa un tipo de datos de identificador único (GUID) y usa la función NEWID () para crear valores, obtendrá una fragmentación horrible debido a las divisiones de página. La razón es que cuando se usa NEWID () el valor generado no es secuencial. SQL 2005 agregó la función NEWSEQUANTIAL () para remediar eso

Una forma de seguir usando GUID e int es tener un guid y un int en una tabla para que el guid se asigne al int. el guid se usa externamente pero el int internamente en la base de datos

por ejemplo

457180FB-C2EA-48DF-8BEF-458573DA1C10    1
9A70FF3C-B7DA-4593-93AE-4A8945943C8A    2

1 y 2 se usarán en las combinaciones y las guías en la aplicación web. Esta tabla será bastante estrecha y debería ser bastante rápida de consultar

SQLMenace
fuente
10

¿Por qué acoplar su clave principal con su URI?

¿Por qué no hacer que su clave URI sea legible por humanos (o imposible de adivinar, según sus necesidades), y su índice principal basado en números enteros, de esa manera obtendrá lo mejor de ambos mundos? Una gran cantidad de software de blogs hace eso, donde la identificación expuesta de la entrada se identifica con un "slug" y la identificación numérica está oculta dentro del sistema.

El beneficio adicional aquí es que ahora tiene una estructura de URL realmente agradable, lo cual es bueno para SEO. Obviamente, para una transacción esto no es algo bueno, pero para algo como stackoverflow, es importante (ver URL arriba ...). Obtener la singularidad no es tan difícil. Si está realmente preocupado, almacene un hash del slug dentro de una tabla en algún lugar y realice una búsqueda antes de la inserción.

editar: Stackoverflow no usa el sistema que describo, vea el comentario de Guy a continuación.

Jonathan Arkell
fuente
8
Apile los índices de desbordamiento en el ID y no en el slug. Intente cambiar la barra en la parte superior de la página y presione enter. Lo redireccionará 301 a la URL canónica de esta página según el ID (5949) e ignorará el slug. En el servidor, compara el slug con el slug almacenado / generado. Si no es el mismo, devuelve un 301. Sin embargo, lo encuentra mediante la búsqueda en el ID (5949).
Guy
4

En lugar de URL como esta:

http://example.com/user/783

Por qué no tener:

http://example.com/user/yukondude

¿Cuál es más amigable para los humanos y no filtra esa pequeña información?

Josh
fuente
si el apodo no es único o digamos que el título del libro se usó como enlace y se cambió, no es bueno para los marcadores de usuario y seo.
ZiiMakc
4

Puede utilizar un número entero que esté relacionado con el número de fila pero que no sea secuencial. Por ejemplo, puede tomar los 32 bits del ID secuencial y reorganizarlos con un esquema fijo (por ejemplo, el bit 1 se convierte en bit 6, el bit 2 se convierte en bit 15, etc.).
Este será un cifrado bidireccional, y estará seguro de que dos ID diferentes siempre tendrán cifrados diferentes.
Obviamente, sería fácil de decodificar, si uno se toma el tiempo para generar suficientes ID y obtener el esquema, pero, si entiendo correctamente su problema, simplemente querrá no revelar información con demasiada facilidad.

Andrea Bertani
fuente
No creo que la intención de la pregunta fuera tener una forma segura de usar UUID. Por lo que he entendido, el tema fueron las ramificaciones prácticas de esa decisión. ¡Y su esquema no agrega seguridad y es una pérdida de ciclos de CPU!
Patrick Cornelissen
4

Usamos GUID como claves principales para todas nuestras tablas, ya que también funciona como RowGUID para la replicación de MS SQL Server. Lo hace muy fácil cuando el cliente abre repentinamente una oficina en otra parte del mundo ...

Marius
fuente
3

No creo que un GUID le brinde muchos beneficios. Los usuarios odian las URL largas e incomprensibles.

Cree un ID más corto que pueda asignar a la URL o aplique una convención de nombre de usuario único ( http://example.com/user/brianly ). Los chicos de 37Signals probablemente se burlarían de usted por preocuparse por algo como esto cuando se trata de una aplicación web.

Por cierto, puede obligar a su base de datos a comenzar a crear ID enteros a partir de un valor base.

Brian Lyttle
fuente
Esto no es aplicable, no es necesario mostrar el uuid en la URL.
davidahines
3
@dah el interlocutor menciona su uso dentro de la URL en la pregunta.
Brian Lyttle
3

También depende de lo que le interese para su aplicación. Para aplicaciones de n niveles, los GUID / UUID son más simples de implementar y más fáciles de transferir entre diferentes bases de datos. Para producir claves enteras, algunas bases de datos admiten un objeto de secuencia de forma nativa y algunas requieren la construcción personalizada de una tabla de secuencia.

Las claves enteras probablemente (no tengo números) brindan una ventaja para el rendimiento de las consultas y la indexación, así como para el uso del espacio. La consulta directa a la base de datos también es mucho más fácil usando teclas numéricas, menos copiar / pegar, ya que son más fáciles de recordar.

Michael Barker
fuente
2

Trabajo con un sistema de gestión de estudiantes que utiliza UUID en forma de número entero. Tienen una tabla que contiene la siguiente identificación única.

Aunque probablemente sea una buena idea desde el punto de vista arquitectónico, dificulta el trabajo diario. A veces es necesario hacer inserciones masivas y tener un UUID hace que esto sea muy difícil, por lo general requiere escribir un cursor en lugar de una simple instrucción SELECT INTO.

GateKiller
fuente
2

Probé ambos en aplicaciones web reales.

Mi opinión es que es preferible usar números enteros y tener URL cortas y comprensibles.

Como desarrollador, se siente un poco horrible ver números enteros secuenciales y saber que se está filtrando cierta información sobre el recuento total de registros, pero honestamente, a la mayoría de la gente probablemente no le importa, y esa información nunca ha sido realmente crítica para mis negocios.

Tener urls UUID largas y feas me parece mucho más que un desaliento para los usuarios normales.

Daniel Alexiuc
fuente
Gracias por esta opinion. Investigué el uso de UUID como claves primarias con todas sus posibles desventajas durante días hasta que me di cuenta de que la única ventaja (ocultar información comercial) no vale la pena, en mi caso.
Dr. Jan-Philip Gehrcke
1

Creo que este es uno de estos temas que provocan debates cuasirreligiosos, y es casi inútil hablar de él. Solo diría que use lo que prefiera. En el 99% de los sistemas, no importa qué tipo de clave use, por lo que los beneficios (indicados en las otras publicaciones) de usar un tipo sobre el otro nunca serán un problema.

Dan
fuente
1

Creo que usar un GUID sería la mejor opción en su situación. Ocupa más espacio pero es más seguro.

Bryan Roth
fuente
1

Youtube usa 11 caracteres con codificación base64 que ofrece 11 ^ 64 posibilidades, y generalmente son bastante manejables de escribir. Me pregunto si eso ofrecería un mejor rendimiento que un UUID completo. UUID convertido a base 64 sería el doble del tamaño que creo.

Puede encontrar más información aquí: https://www.youtube.com/watch?v=gocwRvLhDf8

Sousaplex
fuente
-1

Siempre que utilice un sistema de base de datos con almacenamiento eficiente, el disco duro es barato en estos días de todos modos ...

Sé que los GUID pueden ser muy buenos para trabajar algunas veces y vienen con algunos gastos generales de consulta, sin embargo, desde una perspectiva de seguridad, son un salvador.

Pensando en la seguridad por la oscuridad, encajan bien cuando forman URI oscuros y construyen DB normalizados con seguridad definida por tabla, registro y columna, no puede equivocarse con los GUID, intente hacerlo con identificaciones basadas en números enteros.

user2106945
fuente