2011-04-08 28 views
7

He estado investigando y leyendo acerca de los tipos de datos SQL desde hace unos días (lo sé ... lo sé, no es muy largo) y una de las cosas que me resulta difícil de entender es cómo elegir los mejores datos escriba para capacidad de expansión, eficiencia y facilidad de acceso.Elegir el tipo de datos para MySQL?

Creo que es bastante sencillo elegir tipos de datos básicos (es decir, int vs varchar), pero ¿cómo elegir entre cosas como blob y texto?

Las páginas man de MySQL son geniales pero no son lo que a los fanáticos de las computadoras nos encantan ... eficientes.

Creo que sería increíble si pudiéramos compilar una lista de los tipos de datos MySQL, las ventajas/desventajas generales de cada uno y cuándo tendría sentido elegir ese tipo de datos.

+1

http://www.google.com/search?q=performance+of+mysql+data+types (nada en la primera página) – Ben

+0

Me gusta la pregunta, y espero una respuesta bien pensada, esto realmente podría ayudar a la velocidad en mis servidores (si escogí los tipos incorrectos). Mientras tanto, este artículo tenía algo que ver con eso (y los problemas con la elección del tipo de datos incorrecto) http://m.pinboard.in/blog/173/ – Ben

+0

@Ben, por supuesto, un enlace a Google, no piensas por leyendo mi pregunta que he pasado un tiempo buscando en Google y leyendo sobre lo que es mejor. El problema es que no hay una compilación de esa información de manera eficiente con una buena descripción de cuándo usar cada uno. Si lees 5 o 6 artículos, obtienes una buena cantidad de información para comenzar, pero podríamos encontrarla fácilmente en una lista de estilo wiki. Podría ser editable y utilizado mucho mejor que tamizar los resultados de google. El mejor artículo que la búsqueda tiene es peachpits y todavía está incompleto. :/Creo que una respuesta aquí podría ser mucho mejor. – austinbv

Respuesta

11

Los tipos de cadenas MySQL vienen en dos variantes: una sin una etiqueta de conjunto de caracteres y otra con una etiqueta de conjunto de caracteres.

Una cadena de longitud fija, rellenada con espacios al final, es CHAR (n). El tipo de coincidencia que no tiene una etiqueta de conjunto de caracteres es BINARIO (n). El almacenamiento de la cadena "hola" en un CHAR(255) CHARSET utf8 tomará 765 bytes (cadena rellenada con espacios de longitud completa, almacenada como utf8 que, en el peor de los casos, el uso de espacio de 3 bytes/caracteres asigna 3 * 255 bytes).

Una cadena de longitud variable con uno o dos bytes de longitud y sin relleno es VARCHAR ((n). El tipo de juego que no tiene etiqueta juego de caracteres es VARBINARY (n). El almacenamiento de la cadena "Hola" en un VARCHAR(255) CHARSET utf8 tendrá 6 bytes (1 byte de longitud, más 5 bytes para el texto real). el almacenamiento de la cadena ク リ ス en el mismo tipo se llevará a 10 bytes (byte 1 de longitud, más 3 caracteres usando 3 bytes por carácter para representarlos).

mysql> select hex('クリス'), length(hex('クリス'))/2 as bytes; 
+--------------------+--------+ 
| hex('クリス')  | bytes | 
+--------------------+--------+ 
| E382AFE383AAE382B9 | 9.0000 | 
+--------------------+--------+ 
1 row in set (0.02 sec) 

Una cadena de longitud variable con uno, dos, tres o cuatro bytes de longitud es TINYTEXT, TEXT, MEDIUMTEXT y LARGETEXT. Los tipos coincidentes que no tienen una etiqueta de conjunto de caracteres son TINYBLOB, BLOB, MEDIUMBLOB y LARGEBLOB.

Un tipo TEXTO/BLOB difiere de un tipo VARCHAR/VARBINARY en cómo y dónde se almacenan los datos, consulte http://www.mysqlperformanceblog.com/2010/02/09/blob-storage-in-innodb/ para obtener información sobre cómo se almacenan los tipos TEXT/BLOB en InnoDB según la versión y ROW_FORMAT configuraciones. Por motivos de rendimiento, desea una versión reciente de InnoDB y tablas de formato "Barracuda".

MySQL es incapaz de trabajar con datos mayores que max_allowed_packet (por defecto: 1M) de tamaño, a menos que construya soluciones complicadas y de memoria intensa en el lado del servidor. Esto restringe aún más lo que se puede hacer con tipos TEXT/BLOB, y generalmente hace que el tipo LARGETEXT/LARGEBLOB sea inútil en una configuración predeterminada.

Para los tipos sin una etiqueta de conjunto de caracteres (BINARY, VARBINARY y% BLOB%), MySQL aceptará los datos tal como se recibieron y los escribirá en el disco. Para los tipos con una etiqueta de conjunto de caracteres, MySQL observará lo que usted anunció como el conjunto de caracteres de sus clientes en el servidor con SET NAMES y cuál es la etiqueta definida del conjunto de caracteres de las columnas. Luego convertirá el conjunto de caracteres de conexión al juego de caracteres de columna y escribirá los datos convertidos. Puede verificarlo con la función HEX(), p. SELECT HEX(str) FROM t WHERE id = ....

En la recuperación, las conexiones de carácter anunciado fijó con SET NAMES puede ser diferente de lo que había sido en el momento de la escritura. MySQL volverá a verificar la etiqueta de conjunto de caracteres de columnas con el juego de caracteres anunciado para esta conexión, y si es necesario, se convertirá en el juego de caracteres de conexión.

La penalización de rendimiento para que la conversión de cualquier manera es insignificante en comparación con el tiempo que tarda el disco I/O originadas por dichos datos de cualquier forma, a performancewise poco importa el tipo que elija. En su lugar, la regla es: elija un tipo con una etiqueta de conjunto de caracteres, si está trabajando con datos de texto, y un tipo sin si no lo está.


Una pregunta relacionada a menudo preguntó: ¿Debo elegir CHAR o VARCHAR (binary o varbinary, respectivamente)?

Para InnoDB, la respuesta es siempre: Elija el tipo de datos de longitud variable. No hay beneficio de rendimiento de los tipos de datos de longitud fija en InnoDB, pero hay una gran penalización de tamaño si elige un tipo de datos de longitud fija y luego no usa todo el espacio en él. Además, los tipos de cadenas SQL de longitud fija tienen reglas realmente extrañas con respecto al relleno y el recorte con espacios al final que probablemente no se molesten en aprender. Para MySQL, el caso puede ser diferente, pero casi nunca lo es.


Otra pregunta relacionada: ¿Debo elegir VARCHAR o texto para mis cuerdas (VARBINARY o BLOB, respectivamente)?

La respuesta para eso está utilizando una versión reciente de InnoDB, mesas de formato Barracuda y luego TEXTO/BLOB. El motivo se explica detalladamente en http://www.mysqlperformanceblog.com/2011/04/07/innodb-row-size-limitation/. El resultado de esto es: Con cualquiera VARCHAR o TEXTO/BLOB en formato pre-Barracuda se corre el riesgo de desbordamiento del límite de tamaño de fila InnoDB si tiene demasiados de ellos en una sola fila.


Y finalmente: ¿Debo almacenar archivos/imágenes/otra gran cantidad de datos o texto en la base de datos?

La respuesta para eso es: Por lo general, no. Servir archivos desde una base de datos (http://mysqldump.azundris.com/archives/36-Serving-Images-From-A-Database.html) es una operación costosa en comparación con el servicio de archivos de un sistema de archivos. Si es posible, querría hacer eso en su lugar. Hay una forma de evitarlo, http://www.blobstreaming.org/, pero esa es una tecnología avanzada que requiere que tenga un control total de su entorno de ejecución, que nunca es el caso en un entorno alojado.


Para redondear esto: No hay tipos de datos de longitud variable en las tablas del motor MEMORY. Así que si usted está viendo "usando temporal" en una salida EXPLAIN, esto significa

  • VARCHAR se convierte en CHAR en esa tabla temporal
  • VARBINARY se convierte en BINARIO

Si la tabla temporal este proceso llega a ser más grande que tmp_table_size O max_heap_table_size, está sobre la marcha convertido al formato MyISAM y va al disco.

Ejemplo: Está definiendo una clase Ruby Active Record User con contiene diez campos etiquetados como :string. Cada uno de estos termina siendo VARCHAR(255) CHARSET utf8 en su tabla Users.

En otra parte de su base de código, Users se está utilizando de forma que implica un plan using temporary. Estás muriendo instantáneamente en operaciones de disco con carga, porque cada fila de la tabla Users ahora usa 7650 bytes en MEMORIA al menos, la mayoría de los espacios son espacios utilizados como relleno. Esto obliga a que la tabla temporal se convierta a MyISAM y se escriba en el disco.

  • cualquier% TEXT% o% BLOB tipo% no puede ser representado en la memoria, por lo que la tabla temporal va en el disco como MyISAM, aún si no hubiera sido lo suficientemente pequeño para ser guardado en la memoria de acuerdo con los límites establecidos anteriormente.

Esto implica que cualquier consulta con un tipo de TEXTO o BLOB y un plan con "using temporary" debe ser reescrito para evitar que las tablas temporales peguen en el disco.

1

Con respecto a BLOB vs TEXT (ya que esa es la única pregunta concreta en su publicación): BLOB es para datos binarios, y TEXT está destinado para datos de texto.

Por lo general, es bastante sencillo utilizar el tipo de columna más específico que se adapte a sus necesidades, y recurrir a los tipos genéricos si ninguno de ellos se ajusta a su uso.

1

Para MySQL hay un procedimiento llamado analizar que evaluará la heurística de datos con la idea de que informa la mejor opción para un tipo de datos y sugerirá un rango o valores para la enumeración.

Un script dinámico concat rápida para generar el SQL para ejecutar

select CONCAT(' SELECT ', COLUMN_NAME, ' FROM ', TABLE_NAME, ' procedure analyse() ;') 
FROM INFORMATION_SCHEMA.COLUMNS 
WHERE table_schema ="yourDbName" 
AND DATA_TYPE ="varchar" 
AND CHARACTER_MAXIMUM_LENGTH > 190 
AND COLUMN_KEY not in (' ') ; 

** SQL anterior no evalúa PK - suponiendo que no son campos de texto

El procedimiento es útil cuando se busca cambiar un tipo de datos basado en el uso de datos o para obtener más eficiencias moviendo o almacenando un paquete de datos más pequeño.

Percona Blog tiene un buen ejemplo de trabajo de análisis de procedimientos que se aplica a Drupal. https://www.percona.com/blog/2009/03/23/procedure-analyse/

Algunos de que la investigación se lleva a cabo para la compresión, que enlaza con los índices más largos utf8mb4 http://techblog.constantcontact.com/devops/space-the-final-frontier-a-story-of-mysql-compression/

Cuestiones relacionadas