¿Diferencia entre cadena y texto en rieles?


436

Estoy creando una nueva aplicación web con Rails, y me preguntaba, ¿cuál es la diferencia entre stringy text? ¿Y cuándo se debe usar cada uno?

Respuestas:


523

La diferencia radica en cómo se convierte el símbolo en su tipo de columna respectivo en el lenguaje de consulta.

con MySQL: la cadena se asigna a VARCHAR (255) - http://guides.rubyonrails.org/migrations.html

:string |                   VARCHAR                | :limit => 1 to 255 (default = 255)  
:text   | TINYTEXT, TEXT, MEDIUMTEXT, or LONGTEXT2 | :limit => 1 to 4294967296 (default = 65536)

Referencia:

http://www.packtpub.com/article/Working-with-Rails-ActiveRecord-Migrations-Models-Scaffolding-and-Database-Completion

¿Cuándo se debe usar cada uno?

Como regla general, use :stringpara la entrada de texto breve (nombre de usuario, correo electrónico, contraseña, títulos, etc.) y use :textpara la entrada esperada más larga, como descripciones, contenido de comentarios, etc.


11
Creo que una mejor regla general es usar siempre :text. Ver depesz.com/2010/03/02/charx-vs-varcharx-vs-varchar-vs-text
Reed G. Law

74
Para MySQL, no tanto, puede tener índices en varchars, no puede en texto.
Omar Qureshi

12
La implementación de PostgreSQL prefiere texto. La única diferencia para pg string / text es la restricción en la longitud de la cadena. No hay diferencias de rendimiento.
Andy Bettisworth

Esta no parece ser toda la historia con ActiveRecord. Guardar el valor trueen un varchar (ergo, stringcampo de tipo) en MySQL serializa el valor en 1(lo cual es completamente justo). Sin embargo, bajo texttype, almacenar el valor "true" termina serializándolo como un carácter singular t. Migré una columna sin darme cuenta de esto y todas las filas futuras donde el valor es verdadero es ahora t. ¿Alguien tiene alguna idea de este comportamiento?
Peter

1
@ elli0t significa que no podrá indexar. Si esto es importante, entonces no debe usar texto en MySQL
Omar Qureshi

157

Si está utilizando postgres, use texto siempre que pueda, a menos que tenga una restricción de tamaño ya que no hay penalización de rendimiento para el texto frente a varchar

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 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 las situaciones, se debe usar texto o caracteres variables.

Manual de PostsgreSQL


44
Pero en aras de ser independiente de la base de datos, ¿es este el mejor enfoque? ¿Qué pasa si quieres cambiar la base de datos? Admito, en el mundo real, eso no sucede tan a menudo, pero aún así ... si no hay "diferencia de rendimiento", ¿por qué no apegarse al uso esperado de cadena para cosas cortas y texto para cosas más largas? Y teniendo en cuenta sus propias cadenas de indexación de comentarios, todavía parece el mejor enfoque.
Dan Barron

66
Hay varias razones por las cuales podría ser necesario en el mundo real, donde es mejor deshacerse de la noción de que hay una solución verdadera para cualquier problema.
Dan Barron el

14
Puede ser así, pero el agnosticismo de la base de datos es un falso profeta.
Omar Qureshi el

2
¿Alguien tiene alguna información sobre si la penalización de rendimiento es significativa o se trata de un caso de optimización prematura? Supongo que nunca notará una diferencia, lo que la apertura del párrafo parece confirmar: "No hay diferencia de rendimiento entre estos tres tipos".
Dennis

55
Haces un buen punto, pero no estoy completamente convencido. Los argumentos en esa publicación de blog para usar textsobre (n)tipos de datos son convincentes, pero el argumento para usar textsobre varcharno lo es. Él dice que son iguales pero prefiere textporque varcharse puede confundir con varchar(n)y porque texthay menos caracteres para escribir. Pero usando en textlugar de varchar, pierde el contexto de que los datos almacenados no deberían ser largos. Por ejemplo, almacenar un nombre de usuario con me textparece engañoso.
Dennis

17

La cadena se traduce a "Varchar" en su base de datos, mientras que el texto se traduce a "texto". Un varchar puede contener muchos menos elementos, un texto puede tener (casi) cualquier longitud.

Para un análisis en profundidad con buenas referencias, consulte http://www.pythian.com/news/7129/text-vs-varchar/

Editar: algunos motores de bases de datos pueden cargarse varcharde una vez, pero almacenar texto (y blob) fuera de la tabla. A SELECT name, amount FROM productspodría ser mucho más lento cuando se usa textpor nameque cuando lo usa varchar. Y desde Rails, de forma predeterminada, se cargan los registros con SELECT * FROM...sus columnas de texto. Sin embargo, esto probablemente nunca será un problema real en su aplicación o la mía (la optimización prematura es ...). Pero saber que el texto no siempre es "gratis" es bueno saberlo.


12

Cadena si el tamaño es fijo y pequeño y texto si es variable y grande. Esto es importante porque el texto es mucho más grande que las cadenas. Contiene muchos más kilobytes.

Entonces, para campos pequeños, siempre use string (varchar). Campos como. nombre, nombre de usuario, correo electrónico, asunto (de un artículo o publicación) y ejemplos de textos: contenido / cuerpo de una publicación o artículo. campos para párrafos, etc.

Tamaño de cadena de 1 a 255 (predeterminado = 255)

Tamaño de texto 1 a 4294967296 (predeterminado = 65536) 2


11

Como se explicó anteriormente, no solo el tipo de datos db, también afectará la vista que se generará si está utilizando andamios. string generará un campo text_field text generará un text_area


2

Use una cadena para un campo más corto, como nombres, dirección, teléfono, compañía

Use Texto para contenido más grande, comentarios, contenido, párrafos.

Mi regla general, si es algo que es más de una línea, normalmente voy por texto, si es de 2 a 6 palabras cortas, voy por cadena.

La regla oficial es 255 para una cadena. Entonces, si su cadena tiene más de 255 caracteres, busque texto.


1

Si está utilizando Oracle ... STRINGse creará como VARCHAR(255)columna y TEXT, como a CLOB.

NATIVE_DATABASE_TYPES = {
    primary_key: "NUMBER(38) NOT NULL PRIMARY KEY",
    string: { name: "VARCHAR2", limit: 255 },
    text: { name: "CLOB" },
    ntext: { name: "NCLOB" },
    integer: { name: "NUMBER", limit: 38 },
    float: { name: "BINARY_FLOAT" },
    decimal: { name: "DECIMAL" },
    datetime: { name: "TIMESTAMP" },
    timestamp: { name: "TIMESTAMP" },
    timestamptz: { name: "TIMESTAMP WITH TIME ZONE" },
    timestampltz: { name: "TIMESTAMP WITH LOCAL TIME ZONE" },
    time: { name: "TIMESTAMP" },
    date: { name: "DATE" },
    binary: { name: "BLOB" },
    boolean: { name: "NUMBER", limit: 1 },
    raw: { name: "RAW", limit: 2000 },
    bigint: { name: "NUMBER", limit: 19 }
}

https://github.com/rsim/oracle-enhanced/blob/master/lib/active_record/connection_adapters/oracle_enhanced_adapter.rb


1

La respuesta aceptada es increíble, explica adecuadamente la diferencia entre cadena y texto (principalmente el tamaño límite en la base de datos, pero hay algunas otras trampas), pero quería señalar un pequeño problema que me ayudó a resolverlo como esa respuesta no lo hizo completamente por mí.

El tamaño máximo : límite => 1 a 4294967296 no funcionó exactamente como lo puse, necesitaba ir -1 desde ese tamaño máximo. Estoy almacenando grandes blobs JSON y a veces pueden ser muy grandes.

Aquí está mi migración con el valor más grande establecido con el valor del que MySQL no se queja.

Tenga en cuenta el 5 al final del límite en lugar de 6

class ChangeUserSyncRecordDetailsToText < ActiveRecord::Migration[5.1]
  def up
    change_column :user_sync_records, :details, :text, :limit => 4294967295
  end

  def down
    change_column :user_sync_records, :details, :string, :limit => 1000
  end
end

0

Si el atributo coincide f.text_fielden la forma, use una cadena , si coincide, f.text_areause el texto .

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.