Si hallas alguna incompatibilidad con tu código o proyecto, recuerda probar siempre en un ambiente de testing antes añadir el código al trabajo final.
Solución:
InnoDB almacena MEDIUMINT como valor de tres bytes. Pero cuando MySQL tiene que hacer algún cálculo, los tres bytes MEDIUMINT se convierten en ocho bytes de int largo sin firmar (supongo que nadie ejecuta MySQL en 32 bits hoy en día).
Hay pros y contras, pero entiende que el razonamiento “Es tonto y lento, y el código que lo implementa es un horror reptante” no es técnico, ¿verdad?
Diría que MEDIUMINT tiene sentido cuando el tamaño de los datos en el disco es crítico. Es decir, cuando una tabla tiene tantos registros que incluso una diferencia de un byte (4 bytes INT frente a 3 bytes MEDIUMINT) significa mucho. Es un caso bastante raro, pero posible.
mach_read_from_3 y mach_read_from_4: las primitivas que utiliza InnoDB para leer números de los registros de InnoDB son similares. Ambos devuelven ulint. Apuesto a que no notarás la diferencia en ningún carga de trabajo
Solo echa un vistazo al código:
ulint
mach_read_from_3(
/*=============*/
const byte* b) /*!< in: pointer to 3 bytes */
((ulint)(b[1]) << 8)
¿Crees que es mucho más lento que esto?
ulint
mach_read_from_4(
/*=============*/
const byte* b) /*!< in: pointer to four bytes */
((ulint)(b[1]) << 16)
En el gran esquema de las cosas, obtener una fila es el gran costo. Las funciones simples, las expresiones y, mucho menos, los formatos de datos, son insignificantes en la duración de una consulta.
Por otro lado, si su conjunto de datos es demasiado grande para permanecer en caché, la sobrecarga de E/S para obtener filas es aún más significativa. Una regla empírica cruda dice que una fila no almacenada en caché toma 10 veces siempre y cuando uno en caché. Por lo tanto, reducir el conjunto de datos (como usar un tamaño más pequeño) *INT
) mayo darle un gran beneficio de rendimiento.
Este argumento se aplica a ...INT
, FLOAT
contra DOUBLE
, DECIMAL(m,n)
, DATETIME(n)
etc. (Se necesita una discusión diferente para [VAR]CHAR/BINARY(...)
y TEXT/BLOB
.)
Para aquellos con experiencia en lenguaje ensamblador...
- una mesa es probable tener una mezcla de números y cadenas, frustrando así los intentos de "alinear" los valores.
- MySQL siempre ha manejado una variedad de hardware (big/little-endian, 16/32/64-bit) con compatibilidad binaria. Tenga en cuenta cómo el código proporcionado por @akuzminsky evita problemas de alineación y endian. Y permite que el compilador se ocupe de los problemas de 32 bits si el hardware es solo de 16 bits.
- El código para probar casos especiales probablemente supere la simple escritura de código genérico.
- Estamos hablando típicamente de menos del 1% del tiempo total de manejo de hileras.
Por lo tanto, la única forma sensata de escribir el código es trabajar a nivel de byte e ignorar el tamaño del registro y asumir que todos los valores están desalineados.
Para Optimización, en orden de importancia:
- Cuente los golpes del disco. Tocar el disco es abrumadoramente la parte más costosa de una consulta.
- Cuente el número de filas tocadas. Encontrar una fila (a través de BTree, etc.) requiere algo de CPU. Pero tenga en cuenta que muy pocas instalaciones están vinculadas a la CPU; los que lo son tienden a tener índices bajos. (Regla general: normalmente hay 100 filas en un bloque de índice o datos de InnoDB).
- Solo ahora entra en juego el análisis de la fila.
Regla general: si una optimización tentativa no produce una mejora del 10 % (a través de un cálculo al dorso del sobre), no pierda su tiempo en ella. En su lugar, busque una mejora mayor. Por ejemplo, los índices y las tablas de resumen a menudo se proporcionan 10 veces (no solo el 10%).