¿La búsqueda de índice sería notablemente más rápida con char vs varchar cuando todos los valores son 36 caracteres


30

Tengo un esquema heredado (¡descargo de responsabilidad!) Que utiliza una identificación generada basada en hash para la clave primaria para todas las tablas (hay muchas). Un ejemplo de tal identificación es:

922475bb-ad93-43ee-9487-d2671b886479

No hay esperanza posible de cambiar este enfoque, sin embargo, el rendimiento con acceso al índice es pobre. Dejando a un lado la gran cantidad de razones que esto podría ser, hay una cosa que me di cuenta de que parecía inferior a la óptima - a pesar de todos los valores de ID en todas las muchas mesas que son exactamente 36 caracteres de longitud, el tipo de columna es varchar(36), no char(36) .

¿Alterar los tipos de columna a una longitud fija char(36)ofrecería beneficios significativos en el rendimiento del índice, más allá del muy pequeño aumento en el número de entradas por página de índice, etc.?

Es decir, ¿los postgres funcionan mucho más rápido cuando se trata de tipos de longitud fija que con tipos de longitud variable?

No mencione el ahorro minúsculo de almacenamiento: eso no será importante en comparación con la cirugía requerida para realizar el cambio en las columnas.

Respuestas:


40

No. No hay ganancia en absoluto . El manual establece explícitamente :

Consejo: No hay diferencia de rendimiento entre estos tres tipos , aparte de un mayor espacio de almacenamiento cuando se usa el tipo de relleno en blanco, y algunos ciclos de CPU adicionales para verificar la longitud cuando se almacena en una columna con restricción de longitud. Si bien character(n)tiene ventajas de rendimiento en algunos otros sistemas de bases de datos, no existe tal ventaja en PostgreSQL; de hecho, character(n)suele ser el más lento de los tres debido a sus costos de almacenamiento adicionales. En la mayoría de las situaciones text o character varyingdebería usarse en su lugar .

El énfasis en negrita es mío.

char(n)es un tipo inútil, en gran medida anticuado. Quédate con varchar(n). Si no necesita imponer la longitud, varcharo textsería un poco más rápido. No podrás medir la diferencia.

Además, si todas las cadenas tienen exactamente 36 caracteres de longitud, no hay almacenamiento de almacenamiento de ninguna manera, ni siquiera minúscula. Ambos tienen exactamente el mismo tamaño en el disco y en la RAM. Puede probar con pg_column_size()(en una expresión y en una columna de tabla).

Relacionado:

No solicitó otras opciones , pero mencionaré dos:

  1. COLLATION- a menos que esté ejecutando su DB con la clasificación "C" . La colación a menudo se pasa por alto y posiblemente es costosa. Dado que sus cadenas no parecen ser significativas en un lenguaje natural, probablemente no tenga sentido seguir las COLLATIONreglas. Relacionado:

    Amplio punto de referencia que compara (entre otros) el efecto del COLLATE "C"rendimiento:

  2. UUID , obviamente. Su cadena se parece sospechosamente a un UUID (32 dígitos hexadecimales más 4 delimitadores). Sería mucho más eficiente almacenarlos comouuidtipo de datosreal, que es más rápido de múltiples maneras y solo ocupa 16 bytes, en lugar de 37 bytes en RAM para cualquierachar(36)ovarchar(36)(almacenado sin delimitadores, solo el 32 caracteres definitorios), o 33 bytes en el disco. Pero el relleno de alineación daría como resultado 40 bytes de cualquier manera en muchos casos). TambiénCOLLATIONsería irrelevante para eluuidtipo de datos.

    SELECT '922475bb-ad93-43ee-9487-d2671b886479'::uuid

    Esto puede ser útil (últimos capítulos):

    Ver también:


¿Significa esto que un char / varchar (n) de longitud limitada pasará ciclos de CPU para verificar la restricción, mientras que el campo de texto de longitud variable almacenaría el texto por separado de una manera menos accesible en comparación con char, que gana en este escenario y es este el ganador incluso vale la pena considerar por ejemplo 10 millones de filas con un texto
PirateApp

1
@PirateApp: char(n)casi nunca gana en ningún aspecto. No lo uses Los tipos de datos texty varchar(sin modificador de longitud) son binarios compatibles y comparten las mismas características de rendimiento. Hay razones históricas para que ambos coexistan en Postgres. Internamente, textes el tipo "preferido" entre los tipos de cadena (que puede influir en la resolución del tipo de función). Los ciclos de CPU para hacer cumplir varchar(n)apenas importan. Use una restricción de longitud cuando la necesite . En el caso que nos ocupa uuides el verdadero ganador.
Erwin Brandstetter
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.