Diferencia entre texto y varchar (carácter variable)
¿ Cuál es la diferencia entre el text
tipo de datos y los tipos de datos character varying
( varchar
)?
Según la documentación
Si se utiliza la variación de caracteres sin especificador de longitud, el tipo acepta cadenas de cualquier tamaño. Esta última es una extensión de PostgreSQL.
y
Además, PostgreSQL proporciona el tipo de texto, que almacena cadenas de cualquier longitud. Aunque el tipo de texto no está en el estándar SQL, varios otros sistemas de administración de bases de datos SQL también lo tienen.
Entonces, ¿cuál es la diferencia?
No hay diferencia, bajo el capó es todo varlena
( matriz de longitud variable ).
Consulte este artículo de Depesz: http://www.depesz.com/index.php/2010/03/02/charx-vs-varcharx-vs-varchar-vs-text/
Un par de aspectos destacados:
Para resumir todo esto:
- char(n): ocupa demasiado espacio cuando se trata de valores más cortos que
n
(los rellena hastan
) y puede provocar errores sutiles debido a la adición de espacios finales, además es problemático cambiar el límite- varchar(n): es problemático cambiar el límite en el entorno en vivo (requiere un bloqueo exclusivo al modificar la tabla)
- varchar – al igual que el texto
- text – para mí un ganador – sobre (n) tipos de datos porque carece de sus problemas, y sobre varchar – porque tiene un nombre distinto
El artículo realiza pruebas detalladas para mostrar que el rendimiento de las inserciones y selecciones para los 4 tipos de datos es similar. También analiza detalladamente formas alternativas de limitar la longitud cuando sea necesario. Las restricciones o dominios basados en funciones proporcionan la ventaja de un aumento instantáneo de la restricción de longitud y, basándose en que disminuir una restricción de longitud de una cadena es poco común, depesz concluye que uno de ellos suele ser la mejor opción para un límite de longitud.
Como señala " Tipos de caracteresvarchar(n)
" en la documentación, , char(n)
y text
se almacenan todos de la misma manera. La única diferencia es que se necesitan ciclos adicionales para verificar la longitud, si se proporciona uno, y el espacio y tiempo adicionales necesarios si se necesita relleno char(n)
.
Sin embargo, cuando solo necesita almacenar un carácter, existe una ligera ventaja de rendimiento al usar el tipo especial "char"
(conserve las comillas dobles, son parte del nombre del tipo). Obtiene un acceso más rápido al campo y no hay gastos generales para almacenar la longitud.
Acabo de hacer una tabla de 1.000.000 "char"
elegidos al azar del alfabeto en minúsculas. Una consulta para obtener una distribución de frecuencia ( select count(*), field ... group by field
) tarda unos 650 milisegundos, frente a unos 760 para los mismos datos utilizando un text
campo.
(Esta respuesta es una Wiki, puedes editarla ; ¡corrígela y mejora!)
ACTUALIZACIÓN DE LOS PUNTOS DE REFERENCIA PARA 2016 (pág. 9.5+)
Y utilizando puntos de referencia "SQL puro" (sin ningún script externo)
use cualquier string_generator con UTF8
principales puntos de referencia:
2.1. INSERTAR
2.2. SELECCIONAR comparando y contando
CREATE FUNCTION string_generator(int DEFAULT 20,int DEFAULT 10) RETURNS text AS $f$
SELECT array_to_string( array_agg(
substring(md5(random()::text),1,$1)||chr( 9824 + (random()*10)::int )
), ' ' ) as s
FROM generate_series(1, $2) i(x);
$f$ LANGUAGE SQL IMMUTABLE;
Preparar prueba específica (ejemplos)
DROP TABLE IF EXISTS test;
-- CREATE TABLE test ( f varchar(500));
-- CREATE TABLE test ( f text);
CREATE TABLE test ( f text CHECK(char_length(f)<=500) );
Realizar una prueba básica:
INSERT INTO test
SELECT string_generator(20+(random()*(i%11))::int)
FROM generate_series(1, 99000) t(i);
Y otras pruebas,
CREATE INDEX q on test (f);
SELECT count(*) FROM (
SELECT substring(f,1,1) || f FROM test WHERE f<'a0' ORDER BY 1 LIMIT 80000
) t;
... Y use EXPLAIN ANALYZE
.
ACTUALIZADO OTRA VEZ 2018 (pág.10)
Pequeña edición para agregar los resultados de 2018 y reforzar las recomendaciones.
Resultados en 2016 y 2018
Mis resultados, después del promedio, en muchas máquinas y muchas pruebas: todos iguales
(estadísticamente menos que la desviación estándar).
Recomendación
Utilice
text
el tipo de datos,
evite el antiguovarchar(x)
porque a veces no es un estándar, por ejemplo, enCREATE FUNCTION
las cláusulasvarchar(x)
≠varchar(y)
.límites expresos (¡con la misma
varchar
ejecución!) medianteCHECK
cláusula en elCREATE TABLE
ejCHECK(char_length(x)<=10)
.
Con una pérdida insignificante de rendimiento en INSERT/UPDATE también puedes controlar rangos y estructura de cadenas,
por ejemploCHECK(char_length(x)>5 AND char_length(x)<=20 AND x LIKE 'Hello%')
En el manual de PostgreSQL
No hay diferencia de rendimiento entre estos tres tipos, aparte del mayor espacio de almacenamiento cuando se usa el tipo con relleno en blanco y algunos ciclos de CPU adicionales para verificar la longitud cuando se almacena en una columna de longitud limitada. Si bien el carácter (n) tiene ventajas de rendimiento en algunos otros sistemas de bases de datos, no existe tal ventaja en PostgreSQL; de hecho, el carácter (n) suele ser el más lento de los tres debido a sus costos de almacenamiento adicionales. En la mayoría de situaciones, se debe utilizar texto o caracteres variables.
Normalmente uso texto
Referencias: http://www.postgresql.org/docs/current/static/datatype-character.html
En mi opinión, varchar(n)
tiene sus propias ventajas. Sí, todos usan el mismo tipo subyacente y todo eso. Pero cabe señalar que los índices en PostgreSQL tienen un límite de tamaño de 2712 bytes por fila.
TL;DR:
Si usa text
tipo sin restricción y tiene índices en estas columnas, es muy posible que alcance este límite para algunas de sus columnas y obtenga un error cuando intente insertar datos varchar(n)
, pero usando puede evitarlo.
Algunos detalles más: El problema aquí es que PostgreSQL no da ninguna excepción al crear índices para text
el tipo o varchar(n)
donde n
es mayor que 2712. Sin embargo, dará error cuando se intente insertar un registro con un tamaño comprimido mayor que 2712. Significa que puede insertar fácilmente 100.000 caracteres de cadena compuesta por caracteres repetitivos porque se comprimirá muy por debajo de 2712, pero es posible que no pueda insertar alguna cadena con 4000 caracteres porque el tamaño comprimido es superior a 2712 bytes. Utilizando varchar(n)
donde n
no es mucho mayor que 2712, estás a salvo de estos errores.