Diferencia entre texto y varchar (carácter variable)

Resuelto Adam Matan asked hace 13 años • 13 respuestas

¿ Cuál es la diferencia entre el texttipo 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?

Adam Matan avatar Jan 31 '11 15:01 Adam Matan
Aceptado

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 hasta n) 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.

Frank Heikens avatar Jan 31 '2011 08:01 Frank Heikens

Como señala " Tipos de caracteresvarchar(n) " en la documentación, , char(n)y textse 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 textcampo.

George avatar Feb 01 '2011 19:02 George

(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)

  1. use cualquier string_generator con UTF8

  2. 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 textel tipo de datos,
    evite el antiguo varchar(x)porque a veces no es un estándar, por ejemplo, en CREATE FUNCTIONlas cláusulas varchar(x)varchar(y) .

  • límites expresos (¡con la misma varcharejecución!) mediante CHECKcláusula en el CREATE TABLE
    ej CHECK(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%')

Peter Krauss avatar Apr 23 '2016 02:04 Peter Krauss

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

 avatar Nov 05 '2015 14:11

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 texttipo 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 textel tipo o varchar(n)donde nes 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 nno es mucho mayor que 2712, estás a salvo de estos errores.

yakya avatar Apr 11 '2018 12:04 yakya