2009-02-02 8 views
25

Suponiendo que quiero utilizar un hash como ID en lugar de un número. ¿Sería una ventaja de rendimiento almacenarlos como BINARY en lugar de no binario?MySQL binario contra no binario para identificadores hash

CREATE TABLE `test`.`foobar` (
    `id` CHAR(32) BINARY CHARACTER SET ascii COLLATE ascii_bin NOT NULL, 
    PRIMARY KEY (`id`) 
) 
CHARACTER SET ascii; 
+0

¿Puede ser más específico sobre la "ventaja" que está buscando? ¿Está tratando de optimizar el espacio, el rendimiento, la facilidad de uso o el rango de valores únicos? –

+0

Estoy interesado principalmente en las ventajas de rendimiento ya que el espacio es casi gratuito y un valor de 128 bits es el doble del rango de valor que tendría utilizando un BIGINT como clave principal. – Gumbo

Respuesta

28

Sí. A menudo, un hash de resumen se almacena como la representación ASCII de dígitos hexadecimales, por ejemplo MD5 de la palabra hash 'es:

0800fc577294c34e0b28ad2839435945 

Esta es una cadena ASCII de 32 caracteres.

Pero MD5 realmente produce un valor de hash binario de 128 bits. Este debe requerir solo 16 bytes para almacenarse como valores binarios en lugar de dígitos hexadecimales. De modo que puede ganar algo de eficiencia en el uso de cadenas binarias.

CREATE TABLE test.foobar (
    id BINARY(16) NOT NULL PRIMARY KEY 
); 

INSERT INTO test.foobar (id) VALUES (UNHEX(MD5('hash'))); 

Re. sus comentarios indican que está más preocupado por el rendimiento que por la eficiencia del espacio:

No tengo ninguna razón para que el tipo de datos BINARY sea más rápido que CHAR.

Ser la mitad de grande puede ser una ventaja para el rendimiento si utiliza los almacenamientos intermedios de caché de manera efectiva. Es decir, una cantidad determinada de memoria caché puede almacenar el doble de filas de datos BINARIOS si la cadena tiene la mitad del tamaño del CHAR necesario para almacenar el mismo valor en hexadecimal. Del mismo modo, la memoria caché para el índice en esa columna puede almacenar el doble.

El resultado es un caché más efectivo, porque una consulta aleatoria tiene una mayor probabilidad de golpear los datos o el índice en caché, en lugar de requerir un acceso al disco. La eficiencia de la caché es importante para la mayoría de las aplicaciones de bases de datos, ya que generalmente el cuello de botella es E/S de disco. Si puede usar la memoria caché para reducir la frecuencia de E/S del disco, es mucho más grande para el dinero que la opción entre un tipo de datos u otro.

En cuanto a la diferencia entre una cadena de hash almacenada en BINARIO contra una BIGINT, elegiría BIGINT. La eficiencia de la caché será aún mayor, y también en procesadores de 64 bits la aritmética de enteros y las comparaciones deberían ser muy rápidas.

No tengo medidas para respaldar las afirmaciones anteriores. El beneficio neto de elegir un tipo de datos sobre otro depende mucho de los patrones de datos y los tipos de consultas en su base de datos y aplicación. Para obtener la respuesta más precisa, debe probar ambas soluciones y medir la diferencia.


Re. el supuesto de que la comparación cadena binaria es más rápida que la comparación entre mayúsculas y minúsculas cadena por defecto, que intentó la siguiente prueba:

mysql> SELECT BENCHMARK(100000000, 'foo' = 'FOO'); 
1 row in set (5.13 sec) 

mysql> SELECT BENCHMARK(100000000, 'foo' = BINARY 'FOO'); 
1 row in set (4.23 sec) 

Así binaria comparación de cadenas es 17.5% más rápido que entre mayúsculas y minúsculas comparación de cadenas. Pero tenga en cuenta que después de evaluar esta expresión 100 millones de veces, la diferencia total sigue siendo inferior a 1 segundo.Si bien podemos medir la diferencia relativa en la velocidad, la diferencia absoluta en la velocidad es realmente insignificante.

Así que voy a reiterar:

  • Medida, no adivinar o suponer. Tus conjeturas educadas estarán equivocadas la mayor parte del tiempo. Mida antes y después de cada cambio que realice, para que sepa cuánto le ayudó.
  • Invierte tu tiempo y atención donde obtienes la mayor ganancia por el dinero.
  • No te preocupes por las cosas pequeñas. Por supuesto, una pequeña diferencia se suma con suficientes iteraciones, pero dadas esas iteraciones, una mejora en el rendimiento con un mayor beneficio absoluto es aún preferible.
+0

Ya he pensado en eso. Me ahorraría la mitad del espacio, aunque 2^128 son suficientes (BIGINT tiene solo 2^64 y eso ya es suficiente). – Gumbo

+0

He actualizado mi pregunta tal como lo solicitó. Sería bueno si le echas otro vistazo. – Gumbo

+0

Pensé que el binario sería más rápido ya que no hay comparaciones adicionales de letras mayúsculas y minúsculas como la comparación normal, así que "'foo' = 'FOO'" es verdadero pero "BINARY 'foo' = 'FOO" "falso – Gumbo

6

De the manual:

The BINARY and VARBINARY types are similar to CHAR and VARCHAR, except 
that they contain binary strings rather than non-binary strings. That is, 
they contain byte strings rather than character strings. This means that 
they have no character set, and sorting and comparison are based on the 
numeric values of the bytes in the values. 

Desde CHAR (32) BINARIO provoca un binario (32) de columna que se creará bajo el capó, el beneficio es que tendrá menos tiempo para ordenar por esa columna, y probablemente menos tiempo para encontrar las filas correspondientes si la columna está indexada.

+0

Gracias por su respuesta. ¿No sabría usted algunas cifras sobre eso? – Gumbo