¿Cuál es más rápido: char(1) o tinyint(1)? ¿Por qué?


MI PLATAFORMA:

PHP & MySQL

MI SITUACIÓN:

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

  1. Declare la Columna como char(1) y almacene el valor como 'y' o 'n'
  2. O declare la Columna como tinyint(1) y almacene 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:

Así que quería saber, cuál de los dos tipos anteriores:

  1. Conduce a una velocidad de consulta más rápida cuando se accede a esa columna (en aras de la simplicidad, omitamos 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 cuando no lo están?

Entiendo que como char(1) y tinyint(1) ocupan solo 1 byte de espacio, el espacio de almacenamiento no será un problema en este caso. Entonces lo que quedaría es la velocidad de acceso. Por lo que 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 su experiencia en este caso.

Gracias de antemano.

Author: IJas, 2010-01-07

8 answers

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

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

También tenga en cuenta la clasificación por ENUM columna:

Los valores de ENUMERACIÓN se ordenan según el orden en que los miembros de la enumeración fueron enumerados en la especificación de la columna. (En otras palabras, los valores de ENUMERACIÓN se ordenan de acuerdo con sus números de índice. Por ejemplo, 'a' se ordena antes de " b " de " ENUM('a', 'b'), pero 'b' se ordena antes de 'a' para ENUM('b', 'a').

 30
Author: Ivan Nevostruev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-07 22:06:22
                       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 de insertar.

                       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 encontrado aquí

 36
Author: Glen Solsberry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-08 14:01:55

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 recuperar y ordenar campos enteros es más rápido que los campos de caracteres (solo tengo 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 de encendido/apagado estándar. Así que el almacenamiento de enteros parece ser mejor, se siente mejor, y es más fácil de usar en la lógica de código. 0/1 es el claro ganador para mí.

También puede notar que, hasta cierto punto, esta es la posición oficial de MySQL, también, de su documentación :

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

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

 10
Author: Matchu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-07 20:48:21

Para saberlo con seguridad, debes compararlo. O saber que probablemente no importará mucho en la visión más grande de todo el proyecto.

Las columnas Char tienen codificaciones y colaciones, y compararlas podría implicar cambios innecesarios entre codificaciones, por lo que mi conjetura es que un int será más rápido. Por la misma razón, creo que actualizar un índice en una columna int también es más rápido. Pero de nuevo, no importará mucho.

CHAR puede tomar más de un byte, dependiendo de 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.

 4
Author: Jan Fabry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-07 20:56:54

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

 2
Author: Dave Markle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-07 20:48:07

Si especifica los tipos BOOL o BOOLEAN como un 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.

Documentación

También:

Tenemos la intención de implementar booleano completo tipo de manipulación, de acuerdo con SQL estándar, en un futuro MySQL lanzar.

 1
Author: Powerlord,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-07 20:50:16

Si bien mi corazonada es que un índice en un TINYINT sería más rápido que un índice en un CHAR(1) debido al hecho de que no hay sobrecarga de manejo de cadenas (intercalación, espacios en blanco, etc.), no tengo ningún hecho para respaldar esto. Mi conjetura es que no hay una diferencia de rendimiento significativa que valga la pena preocuparse.

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

 1
Author: zombat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-07 20:50:53
 TINYINT    1 Byte
CHAR(M)     M Bytes, 0 <= M <= 255

¿Hay alguna diferencia?

 0
Author: streetparade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-01-07 20:54:10