Me doy cuenta de que se recomienda CHAR si todos mis valores son de ancho fijo. ¿Y qué? ¿Por qué no elegir VARCHAR para todos los campos de texto solo para estar seguro?
Me doy cuenta de que se recomienda CHAR si todos mis valores son de ancho fijo. ¿Y qué? ¿Por qué no elegir VARCHAR para todos los campos de texto solo para estar seguro?
Respuestas:
Generalmente elija CHAR si todas las filas tendrán una longitud similar . Elija VARCHAR cuando la longitud varía significativamente. CHAR también puede ser un poco más rápido porque todas las filas tienen la misma longitud.
Varía según la implementación de la base de datos, pero generalmente VARCHAR usa uno o dos bytes más de almacenamiento (para la longitud o la terminación) además de los datos reales. Entonces (suponiendo que esté usando un conjunto de caracteres de un byte) almacenando la palabra "FooBar"
La conclusión es que CHAR puede ser más rápido y más eficiente en el espacio para datos de relativamente la misma longitud (con una diferencia de longitud de dos caracteres).
Nota : Microsoft SQL tiene 2 bytes de sobrecarga para un VARCHAR. Esto puede variar de DB a DB, pero generalmente se necesita al menos 1 byte de sobrecarga para indicar la longitud o EOL en un VARCHAR.
Como señaló Gaven en los comentarios, si está utilizando un conjunto de caracteres de longitud variable de varios bytes como UTF8, entonces CHAR almacena el número máximo de bytes necesarios para almacenar el número de caracteres. Entonces, si UTF8 necesita como máximo 3 bytes para almacenar un carácter, entonces CHAR (6) se fijará en 18 bytes, incluso si solo almacena caracteres latin1. Entonces, en este caso, VARCHAR se convierte en una opción mucho mejor.
Si estás trabajando conmigo y estás trabajando con Oracle, probablemente te haría usar varchar
en casi todas las circunstancias. La suposición de que char
usa menos potencia de procesamiento de la que varchar
puede ser cierta ... por ahora ... pero los motores de bases de datos mejoran con el tiempo y este tipo de regla general tiene como resultado un "mito" futuro.
Otra cosa: nunca he visto un problema de rendimiento porque alguien decidió ir con él varchar
. Aprovechará mucho mejor su tiempo escribiendo un buen código (menos llamadas a la base de datos) y un SQL eficiente (cómo funcionan los índices, cómo toma decisiones el optimizador, por qué es exists
más rápido de lo in
normal ...).
Reflexión final: he visto todo tipo de problemas con el uso de CHAR
personas que buscan "cuándo deberían estar buscando", o personas que buscan "FOO" cuando deberían estar buscando "FOO (un montón de espacios aquí)" , o personas que no recortan los espacios en blanco finales, o errores con Powerbuilder agregando hasta 2000 espacios en blanco al valor que devuelve de un procedimiento de Oracle.
Además de los beneficios de rendimiento, CHAR
se puede usar para indicar que todos los valores deben tener la misma longitud, por ejemplo, una columna para las abreviaturas de los Estados Unidos.
CHAR
, tendrá que asegurarse de que su restricción descuenta el relleno.
Char es un poco más rápido, por lo que si tiene una columna que SABE que tendrá una cierta longitud, use char. Por ejemplo, almacenar (M) ale / (F) emale / (U) desconocido para género, o 2 caracteres para un estado de EE. UU.
¿NChar o Char funcionan mejor que sus alternativas var?
Gran pregunta La respuesta simple es sí en ciertas situaciones. Veamos si esto se puede explicar.
Obviamente, todos sabemos que si creo una tabla con una columna de varchar (255) (llamemos a esta columna miColumna) e inserte un millón de filas pero coloque solo unos pocos caracteres en miColumna para cada fila, la tabla será mucho más pequeña (en general número de páginas de datos que necesita el motor de almacenamiento) que si hubiera creado myColumn como char (255). Cada vez que realice una operación (DML) en esa tabla y solicite muchas filas, será más rápido cuando myColumn sea varchar porque no tengo que moverme por todos esos espacios "adicionales" al final. Mover, como cuando SQL Server realiza ordenamientos internos, como durante una operación distinta o de unión, o si elige una fusión durante su plan de consulta, etc.
Pero hay algunos gastos generales al usar varchar. SQL Server tiene que usar un indicador de dos bytes (sobrecarga) para, en cada fila, saber cuántos bytes tiene esa columna en particular myColumn. No son los 2 bytes adicionales los que presentan el problema, es la necesidad de "decodificar" la longitud de los datos en myColumn en cada fila.
En mi experiencia, tiene más sentido usar char en lugar de varchar en columnas que se unirán en consultas. Por ejemplo, la clave principal de una tabla o alguna otra columna que se indexará. CustomerNumber en una tabla demográfica, o CodeID en una tabla de decodificación, o quizás OrderNumber en una tabla de pedidos. Al usar char, el motor de consulta puede realizar la unión más rápidamente porque puede hacer aritmética de puntero directo (determinísticamente) en lugar de tener que mover sus punteros a una cantidad variable de bytes a medida que lee las páginas. Sé que podría haberte perdido en esa última oración. Las uniones en SQL Server se basan en la idea de "predicados". Un predicado es una condición. Por ejemplo myColumn = 1, o OrderNumber <500.
Entonces, si SQL Server está realizando una declaración DML, y los predicados o "claves" que se unen son de longitud fija (char), el motor de consulta no tiene que hacer tanto trabajo para hacer coincidir las filas de una tabla con las filas de otra mesa No tendrá que averiguar cuánto tiempo duran los datos en la fila y luego caminar por la cadena para encontrar el final. Todo eso lleva tiempo.
Ahora tenga en cuenta que esto puede implementarse fácilmente de manera deficiente. He visto char usado para campos de clave primaria en sistemas en línea. El ancho debe mantenerse pequeño, es decir, char (15) o algo razonable. Y funciona mejor en sistemas en línea porque generalmente solo está recuperando o insertando una pequeña cantidad de filas, por lo que tener que "recortar" esos espacios finales que obtendrá en el conjunto de resultados es una tarea trivial en lugar de tener que unirse a millones de filas de una tabla a millones de filas en otra tabla.
Otra razón por la cual CHAR tiene sentido sobre varchar en los sistemas en línea es porque reduce las divisiones de página. Al usar char, esencialmente está "reservando" (y desperdiciando) ese espacio, por lo que si un usuario aparece más tarde y coloca más datos en esa columna, SQL ya le ha asignado espacio y se va.
Otra razón para usar CHAR es similar a la segunda razón. Si un programador o usuario realiza una actualización "por lotes" a millones de filas, agregando alguna oración a un campo de nota, por ejemplo, no recibirá una llamada de su DBA en medio de la noche preguntándose por qué sus unidades están llenas. En otras palabras, conduce a un crecimiento más predecible del tamaño de una base de datos.
Estas son 3 formas en que un sistema en línea (OLTP) puede beneficiarse de char sobre varchar. Casi nunca uso char en un escenario de almacén / análisis / OLAP porque generalmente tienes TANTOS datos que todas esas columnas de char pueden agregar a un montón de espacio desperdiciado.
Tenga en cuenta que char puede hacer que su base de datos sea mucho más grande, pero la mayoría de las herramientas de respaldo tienen compresión de datos, por lo que sus respaldos tienden a ser aproximadamente del mismo tamaño que si hubiera usado varchar. Por ejemplo, LiteSpeed o RedGate SQL Backup.
Otro uso es en vistas creadas para exportar datos a un archivo de ancho fijo. Digamos que tengo que exportar algunos datos a un archivo plano para que un mainframe pueda leerlos. Es de ancho fijo (no delimitado). Me gusta almacenar los datos en mi tabla de "puesta en escena" como varchar (lo que consume menos espacio en mi base de datos) y luego usar una vista para CASTAR todo a su equivalente de caracteres, con la longitud correspondiente al ancho del ancho fijo para esa columna . Por ejemplo:
create table tblStagingTable (
pkID BIGINT (IDENTITY,1,1),
CustomerFirstName varchar(30),
CustomerLastName varchar(30),
CustomerCityStateZip varchar(100),
CustomerCurrentBalance money )
insert into tblStagingTable
(CustomerFirstName,CustomerLastName, CustomerCityStateZip) ('Joe','Blow','123 Main St Washington, MD 12345', 123.45)
create view vwStagingTable AS
SELECT CustomerFirstName = CAST(CustomerFirstName as CHAR(30)),
CustomerLastName = CAST(CustomerLastName as CHAR(30)),
CustomerCityStateZip = CAST(CustomerCityStateZip as CHAR(100)),
CustomerCurrentBalance = CAST(CAST(CustomerCurrentBalance as NUMERIC(9,2)) AS CHAR(10))
SELECT * from vwStagingTable
Esto es genial porque internamente mis datos ocupan menos espacio porque están usando varchar. Pero cuando uso DTS o SSIS o incluso solo cortar y pegar desde SSMS a Bloc de notas, puedo usar la vista y obtener el número correcto de espacios finales. En DTS solíamos tener una función llamada, maldita sea, olvido que creo que se llamaba "sugerir columnas" o algo así. En SSIS ya no puede hacer eso, debe definir tediosamente el administrador de conexión de archivos planos. Pero dado que tiene su configuración de vista, SSIS puede conocer el ancho de cada columna y puede ahorrar mucho tiempo al crear sus tareas de flujo de datos.
Así que, en resumen, usa varchar. Hay un número muy pequeño de razones para usar char y es solo por razones de rendimiento. Si tiene un sistema con cientos de millones de filas, verá una diferencia notable si los predicados son deterministas (char), pero para la mayoría de los sistemas que usan char es simplemente desperdiciar espacio.
Espero que ayude. Jeff
Hay beneficios de rendimiento, pero aquí hay uno que no se ha mencionado: la migración de filas. Con char, reserva todo el espacio por adelantado, así que digamos que tiene un char (1000) y almacena 10 caracteres, usará los 1000 caracteres del espacio. En un varchar2 (1000), solo usarás 10 caracteres. El problema surge cuando modifica los datos. Supongamos que actualiza la columna para que ahora contenga 900 caracteres. Es posible que el espacio para expandir el varchar no esté disponible en el bloque actual. En ese caso, el motor de base de datos debe migrar la fila a otro bloque y hacer un puntero en el bloque original a la nueva fila en el nuevo bloque. Para leer estos datos, el motor de DB ahora tendrá que leer 2 bloques.
Nadie puede decir equívocamente que varchar o char son mejores. Hay un espacio para el intercambio de tiempo y la consideración de si los datos se actualizarán, especialmente si hay una buena posibilidad de que crezcan.
Existe una diferencia entre la optimización temprana del rendimiento y el uso de un tipo de regla de mejores prácticas. Si está creando nuevas tablas donde siempre tendrá un campo de longitud fija, tiene sentido usar CHAR, debería usarlo en ese caso. Esto no es una optimización temprana, sino más bien implementar una regla general (o una mejor práctica).
es decir, si tiene un campo de estado de 2 letras, use CHAR (2). Si tiene un campo con los nombres de estado reales, use VARCHAR.
Elegiría varchar a menos que la columna almacene un valor fijo como el código de estado de EE. UU., Que siempre tiene 2 caracteres de largo y la lista de códigos de estado de EE. UU. Válidos no cambia a menudo :).
En cualquier otro caso, incluso al almacenar la contraseña hash (que es de longitud fija), elegiría varchar.
Por qué: la columna de tipo char siempre se completa con espacios, lo que hace que la columna my_column se defina como char (5) con el valor 'ABC' dentro de la comparación:
my_column = 'ABC' -- my_column stores 'ABC ' value which is different then 'ABC'
falso.
Esta característica puede provocar muchos errores irritantes durante el desarrollo y dificulta las pruebas.
CHAR ocupa menos espacio de almacenamiento que VARCHAR si todos sus valores de datos en ese campo tienen la misma longitud. Ahora, tal vez en 2009, una base de datos de 800 GB sea la misma para todos los efectos que un 810 GB si convierte los VARCHAR a CHAR, pero para cadenas cortas (1 o 2 caracteres), CHAR sigue siendo una "mejor práctica" de la industria, diría yo.
Ahora, si observa la amplia variedad de tipos de datos que la mayoría de las bases de datos proporcionan incluso solo para enteros (bit, tiny, int, bigint), hay razones para elegir uno sobre el otro. Simplemente elegir bigint cada vez es ser un poco ignorante de los propósitos y usos del campo. Si un campo simplemente representa la edad de una persona en años, un bigint es exagerado. Ahora no es necesariamente "incorrecto", pero no es eficiente.
Pero es un argumento interesante, y a medida que las bases de datos mejoran con el tiempo, se podría argumentar que CHAR vs VARCHAR se vuelve menos relevante.
Acepto el comentario de Jim McKeeth.
Además, los escaneos de indexación y de tabla completa son más rápidos si su tabla solo tiene columnas CHAR. Básicamente, el optimizador podrá predecir qué tan grande es cada registro si solo tiene columnas CHAR, mientras que necesita verificar el valor de tamaño de cada columna VARCHAR.
Además, si actualiza una columna VARCHAR a un tamaño mayor que su contenido anterior, puede obligar a la base de datos a reconstruir sus índices (porque forzó a la base de datos a mover físicamente el registro en el disco). Mientras que con las columnas CHAR eso nunca sucederá.
Pero probablemente no te importará el éxito en el rendimiento a menos que tu mesa sea enorme.
Recuerda las sabias palabras de Djikstra. La optimización temprana del rendimiento es la raíz de todo mal.
CHAR
columna, los índices también deben actualizarse. No hay diferencia en actualizar una columna VARCHAR o CHAR en ese sentido. Piensa en actualizar FOO
a BAR
.
Muchas personas han señalado que si conoce la longitud exacta del valor con CHAR tiene algunos beneficios. Pero si bien almacenar los estados de EE. UU. Como CHAR (2) es excelente hoy, cuando recibe el mensaje de las ventas de que "Acabamos de hacer nuestra primera venta a Australia", se encuentra en un mundo de dolor. Siempre envío a sobrestimar cuánto tiempo creo que los campos deberán ser en lugar de hacer una suposición "exacta" para cubrir futuros eventos. VARCHAR me dará más flexibilidad en esta área.
Creo que en su caso probablemente no haya razón para no elegir Varchar. Le brinda flexibilidad y, como han mencionado varios encuestados, el rendimiento es tal que, salvo en circunstancias muy específicas, los simples mortales (a diferencia de los DBA de Google) no notarán la diferencia.
Una cosa interesante que vale la pena señalar cuando se trata de Tipos de DB es que sqlite (una mini base de datos popular con un rendimiento bastante impresionante) pone todo en la base de datos como una cadena y escribe sobre la marcha.
Siempre uso VarChar y generalmente lo hago mucho más grande de lo que podría necesitar. P.ej. 50 para Nombre, como usted dice por qué no solo para estar seguro.
NUNCA usaría caracteres. He tenido este debate con muchas personas y siempre mencionan el cliché cansado de que el char es más rápido. Bueno, yo digo, ¿cuánto más rápido? ¿De qué estamos hablando aquí, milisegundos, segundos y, de ser así, cuántos? ¿Me estás diciendo que porque alguien afirma que es unos milisegundos más rápido, deberíamos introducir toneladas de errores difíciles de corregir en el sistema?
Aquí hay algunos problemas con los que se encontrará:
Cada campo se rellenará, por lo que terminará con un código para siempre que tiene RTRIMS en todas partes. Esto también es un gran desperdicio de espacio en disco para los campos más largos.
Ahora supongamos que tiene el ejemplo por excelencia de un campo de caracteres de un solo carácter, pero el campo es opcional. Si alguien pasa una cadena vacía a ese campo, se convierte en un espacio. Entonces, cuando otra aplicación / proceso lo consulta, obtienen un solo espacio, si no usan rtrim. Hemos tenido documentos xml, archivos y otros programas, muestran solo un espacio, en campos opcionales y separan cosas.
Así que ahora debe asegurarse de pasar nulos y no cadenas vacías al campo char. Pero ese NO es el uso correcto de nulo. Aquí está el uso de nulo. Digamos que obtienes un archivo de un proveedor
Nombre | Género | Ciudad
Bob || Los Angeles
Si no se especifica el género, ingrese Bob, vacíe la cadena y Los Ángeles en la tabla. Ahora supongamos que obtiene el archivo y su formato cambia y el género ya no está incluido, pero ya estaba en el pasado.
Nombre | Ciudad
Bob | Seattle
Bueno, ahora que el género no está incluido, usaría nulo. Los varchars respaldan esto sin problemas.
Char por otro lado es diferente. Siempre tienes que enviar nulo. Si alguna vez envía una cadena vacía, terminará con un campo que tiene espacios.
Podría seguir y seguir con todos los errores que tuve que corregir de los caracteres y en unos 20 años de desarrollo.
Hay una pequeña sobrecarga de procesamiento al calcular el tamaño real necesario para un valor de columna y asignar el espacio para un Varchar, por lo que si definitivamente está seguro de cuánto tiempo será siempre el valor, es mejor usar Char y evitar el golpe.
Es el equilibrio clásico entre espacio y rendimiento.
En MS SQL 2005, Varchar (o NVarchar para idiomas que requieren dos bytes por carácter, es decir, chino) son de longitud variable. Si agrega a la fila después de que se haya escrito en el disco duro, ubicará los datos en una ubicación no contigua a la fila original y conducirá a la fragmentación de sus archivos de datos. Esto afectará el rendimiento.
Por lo tanto, si el espacio no es un problema, los Char son mejores para el rendimiento, pero si desea mantener el tamaño de la base de datos bajo, los varchars son mejores.
Fragmentación. Char reserva espacio y VarChar no. Se puede requerir división de página para acomodar la actualización a varchar.
CHAR
columna.
En algunas bases de datos SQL, VARCHAR se rellenará a su tamaño máximo para optimizar las compensaciones. Esto es para acelerar los escaneos e índices de tablas completas.
Debido a esto, no tiene ningún ahorro de espacio al usar un VARCHAR (200) en comparación con un CHAR (200)
El uso de CHAR (NCHAR) y VARCHAR (NVARCHAR) trae diferencias en las formas en que el servidor de bases de datos almacena los datos. El primero presenta espacios en blanco finales; He encontrado un problema al usarlo con el operador LIKE en las funciones de SQL SERVER. Así que tengo que hacerlo seguro usando VARCHAR (NVARCHAR) todo el tiempo.
Por ejemplo, si tenemos una tabla TEST (ID INT, Status CHAR (1)) , y escribe una función para enumerar todos los registros con algún valor específico como el siguiente:
CREATE FUNCTION List(@Status AS CHAR(1) = '')
RETURNS TABLE
AS
RETURN
SELECT * FROM TEST
WHERE Status LIKE '%' + @Status '%'
En esta función, esperamos que cuando pongamos el parámetro predeterminado la función devolverá todas las filas, pero de hecho no lo hace. Cambiar el tipo de datos @Status a VARCHAR solucionará el problema.