2010-01-07 13 views
24

mi plataforma:¿Qué es más rápido: char (1) o tinyint (1)? ¿Por qué?

PHP & mySQL

mi situación:

me encontré con una situación en la que necesito para almacenar un valor para la selección del usuario en una de mis columnas de una tabla . Ahora mis opciones serían:

  1. sea para declarar un Columna como char (1) y almacenar el valor como 'y' o 'n'
  2. o declarar la columna como tinyint (1) y almacenar el valor como 1 o 0
  3. Esta columna así declarada, también puede ser indexada para su uso dentro de la aplicación.

MIS PREGUNTAS:

por lo que quería saber, ¿cuál de las anteriores dos tipos:

  1. conduce a la velocidad de las consultas más rápido cuando se accede a esa columna (por el bien de simplicidad, vamos a dejar de mezclar otras consultas o acceder a otras columnas, por favor).

  2. ¿Es la forma más eficiente de almacenar y acceder a los datos y por qué?

  3. ¿Cómo varía la velocidad de acceso si las columnas están indexadas y cuándo no?

Mi entendimiento es que desde char (1) y tinyint (1) ocupan sólo el 1 byte de espacio, el espacio de almacenamiento no será un problema en este caso. Entonces, lo que quedará es la velocidad de acceso. Hasta donde yo sé, la indexación numérica es más rápida y más eficiente que cualquier otra cosa. Pero el caso aquí es difícil de decidir, creo. Definitivamente me gustaría escuchar tu experiencia en este.

Gracias de antemano.

+5

Haz un perfil y avísanos para resoult. – erenon

+2

Una dicotomía falsa, también hay 'enum ('1', '0')' (por ejemplo). –

+0

la pregunta no tiene nada que ver con php, así que eliminé la etiqueta php – streetparade

Respuesta

30

Creo que deberías crear una columna con ENUM('n','y'). Mysql almacena este tipo de manera óptima. También lo ayudará a almacenar solo los valores permitidos en el campo.

También puede hacerlo más humano ENUM('no','yes') sin afectar el rendimiento. Porque las cadenas 'no' y 'yes' se almacenan solo una vez por definición de ENUM. Mysql almacena solo el índice del valor por fila.

También nota acerca de la clasificación por ENUM columna:

valores ENUM son ordenados según el orden en que los miembros de la enumeración se enumeran en la especificación de la columna. (En otras palabras, los valores ENUM se ordenan según sus números índices). Por ejemplo, 'a' ordena antes que 'b' para ENUM ('a', 'b'), pero 'b' ordena antes de 'a' para ENUM ('b', 'a').

+10

Hace mucho tiempo, tenía la misma pregunta que el OP, y la comparé para encontrar enum la más rápida y eficiente de las tres opciones. Solo asegúrate de no utilizar enum ('0', '1') como lo hice, terminarás preguntándote por qué UPDATE X SET Y = 0; no funciona (necesita comillas simples). – Langdon

+0

+1 para Langdon. Ese es un punto único que has especificado. Nunca lo supe hasta ahora. Entonces eso significa que si usamos enum ('0', '1'), nuestra consulta debe tener UPDATE X SET Y = '0'; ¿Es eso correcto? @Ivan Si estoy en lo cierto, ENUM ('n', 'y') ocupa el mismo espacio que ENUM ('no', 'yes'). ¿Estoy en lo cierto? – Devner

+0

@Devner Sí, el uso del espacio es el mismo porque no puede agregar ningún otro valor que no sea '', 'no' y 'sí'. Mysql almacena solo el índice del valor por fila, no la cadena. Las cadenas 'no' y 'sí' se almacenan solo una vez en la definición de la tabla. –

10

Usar tinyint es una práctica más estándar, y le permitirá verificar más fácilmente el valor del campo.

// Using tinyint 0 and 1, you can do this: 
if($row['admin']) { 
    // user is admin 
} 

// Using char y and n, you will have to do this: 
if($row['admin'] == 'y') { 
    // user is admin 
} 

No soy un experto en el funcionamiento interno de MySQL, pero intuitivamente siente que la recuperación y clasificación de los campos de enteros es más rápido que los campos de caracteres (apenas consigo la sensación de que 'a'> 'z' es más trabajo que 0> 1), y parece sentirse mucho más familiar desde una perspectiva informática en la que 0s y 1s son los indicadores estándar de encendido/apagado. Por lo tanto, el almacenamiento de los enteros parece ser mejor, se siente mejor y es más fácil de usar en la lógica del código. 0/1 es el claro ganador para mí.

También cabe señalar que, en cierta medida, esta es la posición oficial de MySQL, así, desde their documentation:

BOOL, BOOLEANA: Estos tipos son sinónimos de TINYINT (1). Un valor de cero es considerado falso. Los valores distintos de cero son considerados verdaderos.

Si MySQL llega a equiparar TINYINT (1) con BOOLEAN, parece que es el camino a seguir.

+0

+1 Una buena manera de realizar el control cuando se usa PHP. – Devner

+0

Quizás sea bueno tener ese tipo de control. El IDE, déjenme explicar ... require_once ("./ Permissions.php"); ... if ($ fila [ ''] === permisos Permisos :: ADMIN) {// \t de usuario es admin } no sólo es bueno para la legibilidad del código, usando una propiedad estática para hacer referencia un valor proporciona una buena verificación del tiempo de compilación contra los errores tipográficos, y cuando se utiliza un IDE predictivo, le ayudará a codificar rápidamente. Este ejemplo le da permisos de varios niveles, pero creo que la legibilidad y el mantenimiento es clave para desarrollar proyectos a gran escala, así que estoy de acuerdo. –

+0

@Gary Gracias por su comentario, pero no puedo decir si defiende el uso de 0 y 1 o la falta de uso de este. Siento que tu práctica de programación es diferente a la mía, así que por favor ten paciencia conmigo ya que podría tomarte un poco más de tiempo para entender lo que estás implicando. – Devner

4

Para saberlo con certeza, debe compararlo. O sepa que probablemente no importe tanto en la vista más grandiosa de todo el proyecto.

Las columnas de caracteres tienen codificaciones y colaciones, y compararlas podría implicar cambios innecesarios entre codificaciones, por lo que supongo que una int será más rápida. Por el mismo motivo, creo que actualizar un índice en una columna int también es más rápido. Pero, de nuevo, no importará mucho.

CHAR puede ocupar más de un byte, según el conjunto de caracteres y las opciones de tabla que elija. Algunos caracteres pueden tomar tres bytes para codificar, por lo que MySQL a veces reserva ese espacio, incluso si solo usa y y n.

+0

+1 para "Pero, de nuevo, no importará mucho". Estoy pensando lo mismo. La diferencia es probablemente insignificante. –

+0

@ Jan Lo que dices, tiene sentido para mí. Entonces, si utilizo enum ('n', 'y'), ¿se aplican los cambios entre las codificaciones y las comparaciones? ¿En qué se diferenciaría al usar INNODB VS MyISAM? – Devner

+0

@Devner: Sí, dado que las columnas enum se definen con una codificación y una intercalación, supongo que esto puede tener un impacto en el rendimiento. No sé sobre las diferencias entre InnoDB y MyISAM, solo una nota que describe y la opción InnoDB que puede afectar el almacenamiento de char [http://dev.mysql.com/doc/refman/5.1/en/data-size.html] –

2

Ambos van a estar tan cerca que no importa. Si sientes que tienes que hacer esta pregunta en SO, estás sobre-optimizando. Use el que tenga el sentido más lógico.

+0

@Dave Gracias por el comentario. – Devner

1

Si especifica los tipos BOOL o BOOLEAN como tipo de columna al crear una tabla en MySQL, crea el tipo de columna como TINYINT(1). Presumiblemente, este es el más rápido de los dos.

Documentation

también:

Tenemos la intención de implementar el control completo tipo booleano, de acuerdo con SQL estándar, en una futura versión de MySQL .

+0

+1 Gracias por el comentario y la referencia. – Devner

1

Mientras mi impresión es que un índice en una TINYINT sería más rápido que un índice en una CHAR (1), debido al hecho de que no hay ninguna cadena de manipulación de la cabeza (cotejo, espacios en blanco, etc.), I don No tengo ningún hecho para respaldar esto. Supongo que no hay una diferencia de rendimiento significativa por la que valga la pena preocuparse.

Sin embargo, como está utilizando PHP, almacenar como TINYINT tiene mucho más sentido. Usar los valores de 1/0 es equivalente a usar true y false, incluso cuando se devuelven como cadenas a PHP, y se pueden manejar como tales.Simplemente puede hacer un if ($record['field']) con sus resultados como una verificación booleana, en lugar de convertir entre 'y' y 'n' todo el tiempo.

+0

+1 @Zombat Eso tiene sentido. Creo que usar números realmente facilitaría el procesamiento con código PHP dentro de la aplicación. – Devner

0
TINYINT 1 Byte 
CHAR(M)  M Bytes, 0 <= M <= 255 

¿hay alguna diferencia?

36
     Rate insert tinyint(1) insert char(1) insert enum('y', 'n') 
insert tinyint(1)  207/s    --   -1%     -20% 
insert char(1)  210/s    1%    --     -19% 
insert enum('y', 'n') 259/s    25%   23%     -- 
         Rate insert char(1) insert tinyint(1) insert enum('y', 'n') 
insert char(1)  221/s    --    -1%     -13% 
insert tinyint(1)  222/s    1%    --     -13% 
insert enum('y', 'n') 254/s   15%    14%     -- 
         Rate insert tinyint(1) insert char(1) insert enum('y', 'n') 
insert tinyint(1)  234/s    --   -3%     -5% 
insert char(1)  242/s    3%    --     -2% 
insert enum('y', 'n') 248/s    6%    2%     -- 
         Rate insert enum('y', 'n') insert tinyint(1) insert char(1) 
insert enum('y', 'n') 189/s     --    -6%   -19% 
insert tinyint(1)  201/s     7%    --   -14% 
insert char(1)  234/s     24%    16%    -- 
         Rate insert char(1) insert enum('y', 'n') insert tinyint(1) 
insert char(1)  204/s    --     -4%    -8% 
insert enum('y', 'n') 213/s    4%     --    -4% 
insert tinyint(1)  222/s    9%     4%    -- 

parece que, en su mayor parte, enum('y', 'n') es más rápido para insertar en.

     Rate select char(1) select tinyint(1) select enum('y', 'n') 
select char(1)  188/s    --    -7%     -8% 
select tinyint(1)  203/s    8%    --     -1% 
select enum('y', 'n') 204/s    9%    1%     -- 
         Rate select char(1) select tinyint(1) select enum('y', 'n') 
select char(1)  178/s    --    -25%     -27% 
select tinyint(1)  236/s   33%    --     -3% 
select enum('y', 'n') 244/s   37%    3%     -- 
         Rate select char(1) select tinyint(1) select enum('y', 'n') 
select char(1)  183/s    --    -16%     -21% 
select tinyint(1)  219/s   20%    --     -6% 
select enum('y', 'n') 233/s   27%    6%     -- 
         Rate select tinyint(1) select char(1) select enum('y', 'n') 
select tinyint(1)  217/s    --   -1%     -4% 
select char(1)  221/s    1%    --     -2% 
select enum('y', 'n') 226/s    4%    2%     -- 
         Rate select char(1) select tinyint(1) select enum('y', 'n') 
select char(1)  179/s    --    -14%     -20% 
select tinyint(1)  208/s   17%    --     -7% 
select enum('y', 'n') 224/s   25%    7%     -- 

Seleccionar también parece ser el enum. El código puede ser found here

+0

+1 @ gms8994 Muchas gracias por las estadísticas. Da más información sobre la velocidad. ¿Será posible que nos informe si hay alguna otra herramienta que produzca los mismos resultados que los anteriores? Gracias de nuevo. – Devner

+0

@Devner No hay ninguno que yo sepa. Escribí este específicamente para usar con esta pregunta, pero puedes consultar la página de GitHub vinculada en la respuesta. –

Cuestiones relacionadas