Importancia de la longitud varchar en la tabla MySQL

112

Tengo una tabla MySQL donde las filas se insertan dinámicamente. Como no puedo estar seguro de la longitud de las cuerdas y no quiero que se corten, las hago varchar (200) que generalmente es mucho más grande de lo que necesito. ¿Hay un gran impacto en el rendimiento al dar a un campo varchar mucha más longitud de la necesaria?

Brian
fuente
Una tabla con una sola VARCHAR(255) utf8mb4columna indexada con ~ 150.000 filas mide 11,5 MB. Una tabla con una VARCHAR(48) utf8mb4columna indexada con los mismos datos (longitud máxima de 46 caracteres) usó 4.5 MB. No es realmente una gran diferencia en las consultas, está indexado. Pero se suma con consultas de E / S y cosas como copias de seguridad de bases de datos.
Code4R7

Respuestas:

59

No, en el sentido de que si los valores que almacenas en esa columna son siempre (digamos) de menos de 50 caracteres, declarando la columna como varchar(50)o varchar(200)tiene el mismo rendimiento.

Alex Martelli
fuente
9
No es exactamente la verdad. Ver respuesta de Bill Karwin
hejdav
5
Creo que una respuesta como debería estar respaldada por documentos, puntos de referencia o algo similar.
Gokhan Sari
301

Hay un posible impacto en el rendimiento: en MySQL, las tablas temporales y las MEMORYtablas almacenan una VARCHARcolumna como una columna de longitud fija, rellenada hasta su longitud máxima. Si diseña VARCHARcolumnas mucho más grandes que el tamaño más grande que necesita, consumirá más memoria de la necesaria. Esto afecta la eficiencia de la caché, la velocidad de clasificación, etc.

Bill Karwin
fuente
33
+1. También me parecen algunos controladores JDBC que asignan suficiente espacio para el tamaño máximo al configurar búferes para recuperar filas. No hace falta decir que esto causa mucha angustia y crujir de dientes cuando un payaso acaba de hacer varchar (50000) por si acaso alguien tiene un apellido muy grande :-)
paxdiablo
21
+1. Este es un impacto importante y creo que esta es la verdadera respuesta a esta pregunta.
Emre Yazici
6
Esta respuesta y la respuesta aceptada son necesarias para comprender la respuesta correcta al OP.
kd8azz
2
De hecho, cuando una MEMORYtabla de este tipo se considera demasiado grande, se escribe en el disco, lo que provoca una degradación significativa del rendimiento.
Timo
1
Esta respuesta podría necesitar especificar de qué motores de almacenamiento es verdadero (observo que dev.mysql.com/doc/refman/8.0/en/… indica que las tablas temporales son siempre InnoDB a partir de MySQL 8; ¿eso cambia algo?) y con vínculos a documentos que respaldan las afirmaciones que realiza. Por lo que he visto de tu salida en Stack Exchange, tengo fe en que tenías razón cuando escribiste esto, pero es posible que las cosas hayan cambiado, y los enlaces serían un buen ejemplo para los demás y ayudarían a enseñar al resto de nosotros a encontrar este tipo de información para nosotros.
Mark Amery
14

VARCHAR es ideal para la situación que describe, porque significa "carácter variable": el límite, según su ejemplo, sería de 200 caracteres, pero se acepta cualquier cantidad menor y no llenará el tamaño asignado de la columna.

VARCHAR también ocupa menos espacio: los valores se almacenan como un prefijo de longitud de uno o dos bytes más datos. El prefijo de longitud indica el número de bytes del valor. Una columna usa un byte de longitud si los valores no requieren más de 255 bytes, dos bytes de longitud si los valores pueden requerir más de 255 bytes.

Para obtener más información sobre la comparación de los tipos de datos CAR de MySQL con VARCHAR, consulte este enlace .

Ponis dios mio
fuente
1
todos los interesados ​​en el almacenamiento MySQL (sobre CHAR y VARCHAR) deben leer el enlace mencionado en esta respuesta. ¡Gracias!
Pascal
14

¡El tamaño es rendimiento! Cuanto menor sea el tamaño, mejor. No hoy ni mañana, pero algún día sus mesas crecerán a un tamaño cuando se trata de cuellos de botella serios, sin importar el diseño que haya presentado. Pero puede prever algunos de esos posibles cuellos de botella en su fase de diseño que probablemente sucedan primero y tratar de expandir el tiempo que su base de datos funcionará rápida y felizmente hasta que necesite repensar su esquema o escalar horizontalmente agregando más servidores.

En su caso, hay muchas fugas de rendimiento con las que puede encontrarse: las combinaciones grandes son casi imposibles con varcharcolumnas largas . La indexación en esas columnas es un verdadero asesino. Su disco tiene que almacenar los datos. Una página de memoria puede contener menos filas y los escaneos de tablas serán mucho más lentos. Además, es poco probable que la caché de consultas le ayude aquí.

Tienes que preguntarte: ¿Cuántas inserciones al año pueden ocurrir? ¿Cuál es la longitud media? ¿Realmente necesito más de 200 caracteres o puedo captar eso en la interfaz de mi aplicación, incluso informando a los usuarios sobre la longitud máxima? ¿Puedo dividir la tabla en una estrecha para indexar y escanear rápidamente y en otra para almacenar datos adicionales que se necesitan con menos frecuencia y de tamaño en expansión? ¿Puedo escribir los posibles datos varchar en categorías y así extraer algunos de los datos en algunas columnas más pequeñas, tal vez int o bool-type y reducir la columna varchar de esa manera?

Puedes hacer mucho aquí. Puede ser mejor ir con una primera suposición y luego rediseñar paso a paso utilizando datos de rendimiento medidos en la vida real. Buena suerte.

Empujar
fuente
+1 para enumerar opciones de diseño y explorar el impacto. Muy útil para mi pregunta también. stackoverflow.com/q/12083089/181638
Assad Ebrahim
5
¿Existe algún impacto real en el rendimiento al establecer una longitud máxima alta, o el rendimiento solo está determinado por el tamaño real?
Poolie
5

¿Actuación? No. ¿Almacenamiento en disco? Sí, pero es barato y abundante. A menos que su base de datos crezca a una escala de terabytes, probablemente esté bien.

duffymo
fuente
Es extraño que esta respuesta haya sido rechazada seis años después de su publicación y ninguna de las otras lo fue. Parece vengativo y mezquino. No hay nada incorrecto en esta respuesta. Moderadores
duffymo
1
Como se dijo, afecta el rendimiento. Además, el almacenamiento en disco tampoco es gratuito. Una columna más ancha significa más lecturas / escrituras en disco (y el acceso al disco es lento), y también índices más amplios, lo que reduce su utilidad. Ambas cosas tienen un impacto negativo en el rendimiento. Tal vez eso sea insignificante en una base de datos pequeña, pero en la escala gigabyte / terabyte seguramente importará, como usted dice. Para una tabla de 100 registros, no importa.
Alejandro
5

Algunos de ustedes se equivocan al pensar que a varchar(200)ocupa más tamaño de tabla en el disco que a varchar(20). Este no es el caso. Solo cuando va más allá de 255 caracteres, mysql usa un byte adicional para determinar la longitud de los varchardatos del campo.

DCH
fuente
9
No es así para las tablas y MEMORYtablas temporales .
Lightness Races in Orbit
4
Cada vez que su consulta de selección utiliza una tabla temporal (agrupar y ordenar por operaciones, entre otras cosas), convertirá varchar (200) en un char (200) y el rendimiento se verá afectado.
Jamie
1

Puede haber impactos en el rendimiento, pero generalmente no a un nivel que la mayoría de los usuarios notarían.

Cuando se conoce el tamaño de cada campo de antemano, MySQL sabe exactamente cuántos bytes hay entre cada campo / fila y puede avanzar una página sin leer todos los datos. El uso de caracteres variables disminuye esta capacidad de optimización.

¿Varchar da como resultado un impacto en el rendimiento debido a la fragmentación de datos?

Aún mejor, char vs varchar .

Para la mayoría de usos, se le multa con cualquiera - pero no es una diferencia, y para bases de datos a gran escala, hay razones por las que quedaría con uno u otro.

Rizwan Kassim
fuente
0

Al ser varchar, en lugar de solo char, el tamaño se basa en un campo interno para indicar su longitud real y la cadena en sí. Entonces, usar varchar (200) no es muy diferente de usar varchar (150), excepto que tiene el potencial de almacenar más.

Y debe considerar lo que sucede en una actualización, cuando crece una fila. Pero si esto es raro, entonces debería estar bien.

Rob Farley
fuente
0

según el nombre del tipo de datos sugiere que esto es VARCHAR, es decir, almacenamiento de datos de caracteres variables, el motor mysql en sí asigna la memoria que se utiliza según los datos almacenados, por lo que no hay impacto en el rendimiento según mi conocimiento.

usuario2903114
fuente
0

Debería intentar ver una columna varchar de la misma manera que lo haría con una columna char en la mayoría de los escenarios y establecer la longitud de forma conservadora. No tiene que pensar siempre en el modificador var tanto como en algo que afecte su toma de decisiones sobre la longitud máxima. Realmente debería verse como una sugerencia de rendimiento en lugar de que las cadenas suministradas serán de diferentes longitudes.

No es una directiva que deba ser seguida estrictamente por los internos de la base de datos, se puede ignorar por completo. Sin embargo, tenga cuidado con esto, ya que a veces la implementación puede tener fugas (longitud fija y relleno, por ejemplo) aunque no debería hacerlo en un mundo ideal.

Si tiene un varchar (255), no tiene garantía de que el rendimiento siempre se comporte de manera diferente a un char (255) en todas las circunstancias.

Puede parecer fácil configurarlo en algo como 255, 65535, etc. en línea con los consejos dados en el manual sobre los requisitos de almacenamiento. Esto da la impresión de que cualquier valor entre 0 (sí, es una cosa) y 255 tendrá el mismo impacto. Sin embargo, eso no es algo que pueda garantizarse por completo.

Los requisitos de almacenamiento tienden a ser ciertos o un buen indicador de motores de almacenamiento persistentes decentes y maduros en términos de almacenamiento en filas. No es un indicador tan fuerte para cosas como índices.

A veces es una pregunta difícil, exactamente cuánto tiempo debe ser un trozo de cuerda para colocarlo en el límite más alto que sepa que debe estar, pero eso no tiene ningún impacto. Desafortunadamente, esto a menudo es algo que el usuario debe resolver y es algo arbitrario. Realmente no se puede decir nunca sobredimensionar una cuerda porque tal vez haya casos en los que no esté exactamente seguro.

Debe asegurarse de que las consultas de MySQL arrojen un error cuando una cadena sea demasiado larga en lugar de truncarse para que al menos sepa si puede ser demasiado corta debido a las emisiones de errores. Cambiar el tamaño de las columnas para agrandarlas o encogerlas puede ser una operación DDL costosa, esto debe tenerse en cuenta.

También se debe considerar el juego de caracteres cuando entran en juego la duración y el rendimiento. La longitud se refiere a esto en lugar de a bytes. Si usa utf8, por ejemplo, (no MB4), entonces varchar (255) es realmente varbinary (3 * 255). Es difícil saber cómo se desarrollarán realmente cosas como esta sin ejecutar pruebas y profundizar en el código fuente / documentación. Debido a esto, existe la posibilidad de que una longitud excesiva tenga un impacto inflado inesperadamente. esto no solo se aplica al rendimiento. Si un día necesita cambiar el conjunto de caracteres de una columna varchar a una más grande, podría terminar alcanzando algún límite sin recurso si permitió que estuvieran presentes cadenas innecesariamente largas que podrían haberse evitado. Este es normalmente un problema de nicho, pero surge,

Si resulta que MAX (LENGTH (column)) es siempre <64 (como si se decidiera que habría un límite en la entrada que no coincidía con la definición de la columna) pero tiene varchar (255), entonces hay un Es muy probable que utilice cuatro veces más espacio del necesario en algunos escenarios.

Esto puede incluir:

  • Diferentes motores, algunos pueden ignorarlo por completo.
  • Los tamaños de búfer, por ejemplo, actualizar o insertar, podrían tener que asignar los 255 completos (aunque no he verificado el código fuente para probar esto, es solo una hipótesis).
  • Índices, esto será inmediatamente obvio si intenta hacer una clave compuesta a partir de muchas columnas varchar (255).
  • Tablas intermedias y posiblemente conjuntos de resultados. Dada la forma en que funcionan las transacciones, puede que no siempre sea posible que algo utilice la longitud máxima real de las cadenas en una columna en lugar del límite definido.
  • Las optimizaciones predictivas internas pueden tomar la longitud máxima como entrada.
  • Cambios en las versiones de implementación de la base de datos.

Como regla general, realmente no hay necesidad de que un varchar sea más largo de lo que debe ser de todos modos, problemas de rendimiento o no, así que recomiendo seguir con eso cuando pueda. Hacer un mayor esfuerzo para muestrear el tamaño de sus datos, hacer cumplir un límite real o descubrir el límite real mediante preguntas / investigaciones es el enfoque ideal.

Cuando no pueda, si desea hacer algo como varchar (255) para los casos en los que tenga dudas, le recomiendo hacer la ciencia. Esto podría consistir en duplicar la tabla, reducir el tamaño de la columna var char, luego copiar los datos en ella desde el original y observar el tamaño de los datos de índice / fila (indexar la columna también, también probarla como clave primaria que podría comportarse de manera diferente en InnoDB ya que las filas están ordenadas por clave primaria). Como mínimo, de esta manera sabrá si tiene un impacto en IO, que tiende a ser uno de los cuellos de botella más sensibles. Probar el uso de la memoria es más difícil, es difícil probarlo de manera exhaustiva. Recomendaría probar los peores casos potenciales (consultas con muchos resultados intermedios en la memoria, verifique con la explicación para tablas temporales grandes, etc.).

Si sabe que no va a haber muchas filas en la tabla, no va a utilizar la columna para combinaciones, índices (especialmente compuestos, únicos), etc., lo más probable es que no tenga muchos problemas.

jgmjgm
fuente