Estoy trabajando en una base de datos para una pequeña aplicación web en mi escuela usando SQL Server 2005
.
Veo un par de escuelas de pensamiento sobre el tema de varchar
vs nvarchar
:
- Use a
varchar
menos que maneje una gran cantidad de datos internacionalizados, luego usenvarchar
. - Solo úsalo
nvarchar
para todo.
Estoy empezando a ver los méritos de la vista 2. Sé que nvarchar ocupa el doble de espacio, pero eso no es necesariamente un gran problema ya que esto solo va a almacenar datos para unos pocos cientos de estudiantes. Para mí, parece que sería más fácil no preocuparse por eso y simplemente permitir que todo use nvarchar. ¿O hay algo que me falta?
sql-server
sql-server-2005
storage
varchar
nvarchar
Jason Baker
fuente
fuente
NVARCHAR
", y puede tener impactos muy negativos en el rendimiento y los costos / presupuestos de hardware. Unas pocas filas, incluso unos pocos miles, no importan. Pero los sistemas crecen más rápidamente de lo que la gente espera, por lo que la respuesta actual aceptada es un perjuicio para la comunidad. Gracias.Respuestas:
Siempre use nvarchar.
Es posible que nunca necesite los caracteres de doble byte para la mayoría de las aplicaciones. Sin embargo, si necesita admitir idiomas de doble byte y solo tiene compatibilidad de un solo byte en el esquema de su base de datos, es realmente costoso volver atrás y modificar en toda su aplicación.
El costo de migrar una aplicación de varchar a nvarchar será mucho mayor que el poco espacio en disco extra que usará en la mayoría de las aplicaciones.
fuente
El espacio en disco no es el problema ... pero la memoria y el rendimiento sí lo serán. Duplica las lecturas de la página, duplica el tamaño del índice, LIKE extraño y = comportamiento constante, etc.
¿Necesita almacenar el script chino, etc.? Si o no...
Y de MS BOL " Almacenamiento y efectos de rendimiento de Unicode "
Editar :
Pregunta SO reciente que destaca cuán malo puede ser el rendimiento de nvarchar ...
SQL Server usa CPU alta cuando busca dentro de cadenas nvarchar
fuente
¡Se consistente! Unirse a un VARCHAR en NVARCHAR tiene un gran éxito en el rendimiento.
fuente
nvarchar
avarchar
vs convertirnvarchar
avarchar
y unirse avarchar
. A menos, por supuesto, que quisieras ser coherente en los tipos de datos de la columna, no en la unión.VARCHAR
yNVARCHAR
, eso debería deberse a la indexación de laVARCHAR
columna junto con el tipo de Colación utilizada para esa columna (y, por lo tanto, el índice). Cubro este tema en detalle en la siguiente publicación de blog: Impacto en los índices al mezclar tipos VARCHAR y NVARCHAR .nvarchar tendrá una sobrecarga significativa en la memoria, el almacenamiento, el conjunto de trabajo y la indexación, por lo que si las especificaciones dictan que realmente nunca será necesario, no se moleste.
No tendría una regla dura y rápida de "siempre nvarchar" porque puede ser un desperdicio completo en muchas situaciones, particularmente ETL de ASCII / EBCDIC o identificadores y columnas de código que a menudo son claves y claves foráneas.
Por otro lado, hay muchos casos de columnas, donde me aseguraría de hacer esta pregunta temprano y si no obtuviera una respuesta rápida y dura de inmediato, haría que la columna sea nvarchar.
fuente
Dudo en agregar otra respuesta aquí ya que ya hay bastantes, pero es necesario hacer algunos puntos que no se han hecho o no se han hecho con claridad.
Primero: Do no siempre se utilizan
NVARCHAR
. Esa es una actitud / enfoque muy peligroso, y a menudo costoso. Y no es mejor decir " Nunca use cursores" ya que a veces son los medios más eficientes para resolver un problema en particular, y la solución común de hacer unWHILE
bucle casi siempre será más lenta que una correcta. Cursor hecho .La única vez que debe usar el término "siempre" es cuando aconseja "hacer siempre lo mejor para la situación". Es cierto que a menudo es difícil de determinar, especialmente cuando se trata de equilibrar las ganancias a corto plazo en el tiempo de desarrollo (gerente: "necesitamos esta característica, que no conocías hasta ahora, ¡hace una semana!") costos de mantenimiento a largo plazo (gerente que inicialmente presionó al equipo para completar un proyecto de 3 meses en un sprint de 3 semanas: "¿por qué estamos teniendo estos problemas de rendimiento? ¿Cómo podríamos haber hecho X que no tiene flexibilidad? No podemos pagar un sprint o dos para arreglar esto. ¿Qué podemos hacer en una semana para volver a nuestros elementos prioritarios? ¡Y definitivamente necesitamos pasar más tiempo en el diseño para que esto no siga sucediendo! ").
Segundo: la respuesta de @ gbn toca algunos puntos muy importantes a considerar al tomar ciertas decisiones de modelado de datos cuando la ruta no es 100% clara. Pero aún hay más para considerar:
El desperdicio de espacio tiene un enorme efecto en cascada en todo el sistema. Escribí un artículo con detalles explícitos sobre este tema: ¡El disco es barato! ORLY? (Se requiere registro gratuito; lo siento, no controlo esa política).
Tercero: si bien algunas respuestas se centran incorrectamente en el aspecto "esta es una aplicación pequeña", y algunas sugieren correctamente "usar lo que es apropiado", ninguna de las respuestas ha proporcionado una guía real para el OP. Un detalle importante mencionado en la pregunta es que esta es una página web para su escuela. ¡Excelente! Entonces podemos sugerir que:
NVARCHAR
ya que, con el tiempo, es cada vez más probable que los nombres de otras culturas aparezcan en esos lugares.VARCHAR
con la página de códigos apropiada (que se determina a partir de la clasificación del campo).INT
/TINYINT
longitud ya que los códigos ISO son fijos, legible por humanos, y así, :) uso estándarCHAR(2)
de códigos de dos letras, yCHAR(3)
si se usa 3 códigos de letras. Y considere usar una intercalación binaria comoLatin1_General_100_BIN2
.VARCHAR
ya que es un estándar internacional no utilizar nunca ninguna letra fuera de AZ. Y sí, aún useVARCHAR
incluso si solo almacena códigos postales de EE. UU. Y no INT, ya que los códigos postales no son números, son cadenas, y algunos de ellos tienen un "0" inicial. Y considere usar una intercalación binaria comoLatin1_General_100_BIN2
.NVARCHAR
ya que ambos pueden contener caracteres Unicode.Cuarto: ahora que tiene
NVARCHAR
datos que ocupan el doble de espacio del necesario para los datos que encajan bienVARCHAR
("encaja bien = = no se convierte en"? ") Y de alguna manera, como por arte de magia, la aplicación creció y ahora hay millones de registros en al menos uno de estos campos donde la mayoría de las filas son ASCII estándar, pero algunas contienen caracteres Unicode, por lo que debe mantenerlasNVARCHAR
, considere lo siguiente:Si está utilizando SQL Server 2008 - 2016 RTM y está en Enterprise Edition, O si está utilizando SQL Server 2016 SP1 (que hizo que la compresión de datos esté disponible en todas las ediciones) o posterior, puede habilitar la compresión de datos . La compresión de datos puede (pero no "siempre") comprimir datos Unicode en
NCHAR
yNVARCHAR
campos. Los factores determinantes son:NCHAR(1 - 4000)
yNVARCHAR(1 - 4000)
use el Esquema de compresión estándar para Unicode , pero solo a partir de SQL Server 2008 R2, ¡Y solo para datos IN ROW, no OVERFLOW! Esto parece ser mejor que el algoritmo de compresión ROW / PAGE normal.NVARCHAR(MAX)
yXML
(y supongo que tambiénVARBINARY(MAX)
,TEXT
yNTEXT
) los datos que están EN LA FILA (no fuera de la fila en las páginas LOB o OVERFLOW) pueden al menos comprimirse en PÁGINA, pero no en ROW. Por supuesto, la compresión PAGE depende del tamaño del valor en fila: probé con VARCHAR (MAX) y vi que las filas de 6000 caracteres / bytes no se comprimirían, pero las filas de 4000 caracteres / bytes sí.Si usa SQL Server 2005 o 2008 - 2016 RTM y no está en Enterprise Edition, puede tener dos campos: uno
VARCHAR
y unoNVARCHAR
. Por ejemplo, supongamos que está almacenando URL que en su mayoría son caracteres ASCII básicos (valores 0-127) y, por lo tanto, se ajustanVARCHAR
, pero a veces tienen caracteres Unicode. Su esquema puede incluir los siguientes 3 campos:En este modelo solo SELECCIONA de la
[URL]
columna calculada. Para insertar y actualizar, usted determina qué campo usar al ver si la conversión altera el valor entrante, que debe ser deNVARCHAR
tipo:Puede GZIP valores entrantes
VARBINARY(MAX)
y luego descomprimir al salir:COMPRESS
yDECOMPRESS
incorporadas, que también son GZip.Si usa SQL Server 2017 o más reciente, puede considerar convertir la tabla en un Índice de almacén de columnas en clúster.
Si bien aún no es una opción viable, SQL Server 2019 presenta soporte nativo para UTF-8 en
VARCHAR
/CHAR
datatypes. Actualmente hay demasiados errores para que pueda usarse, pero si se corrigen, esta es una opción para algunos escenarios. Consulte mi publicación, " Soporte nativo de UTF-8 en SQL Server 2019: ¿Salvador o falso profeta? ", Para un análisis detallado de esta nueva característica.fuente
Para su aplicación, nvarchar está bien porque el tamaño de la base de datos es pequeño. Decir "siempre usar nvarchar" es una gran simplificación excesiva. Si no necesita almacenar cosas como Kanji u otros personajes locos, use VARCHAR, usará mucho menos espacio. Mi predecesor en mi trabajo actual diseñó algo usando NVARCHAR cuando no era necesario. Recientemente lo cambiamos a VARCHAR y ahorramos 15 GB solo en esa tabla (fue muy escrito). Además, si tiene un índice en esa tabla y desea incluir esa columna o hacer un índice compuesto, acaba de aumentar el tamaño del archivo de índice.
Solo sea reflexivo en su decisión; En el desarrollo de SQL y en las definiciones de datos, rara vez parece haber una "respuesta predeterminada" (aparte de evitar los cursores a toda costa, por supuesto).
fuente
Dado que su aplicación es pequeña, esencialmente no hay un aumento de costos apreciable al usar nvarchar sobre varchar, y se ahorra posibles dolores de cabeza en el futuro si necesita almacenar datos Unicode.
fuente
Generalmente hablando; Comience con el tipo de datos más caro que tenga las menores restricciones. Ponlo en producción . Si el rendimiento comienza a ser un problema, averigüe qué se almacena realmente en esas
nvarchar
columnas. ¿Hay algún personaje allí que no encajavarchar
? Si no, cambie a varchar. No intentes optimizar previamente antes de saber dónde está el dolor. Supongo que la elección entre nvarchar / varchar no es lo que va a ralentizar su aplicación en el futuro previsible. Habrá otras partes de la aplicación donde el ajuste del rendimiento le dará mucho más por los dólares .fuente
Durante los últimos años, todos nuestros proyectos han utilizado NVARCHAR para todo, ya que todos estos proyectos son multilingües. Los datos importados de fuentes externas (por ejemplo, un archivo ASCII, etc.) se convierten a Unicode antes de insertarse en la base de datos.
Todavía no he encontrado ningún problema relacionado con el rendimiento de los índices más grandes, etc. Los índices usan más memoria, pero la memoria es barata.
Si usa procedimientos almacenados o construye SQL sobre la marcha, asegúrese de que todas las constantes de cadena tengan el prefijo N (por ejemplo, SET @foo = N'Hello world. ';) Para que la constante también sea Unicode. Esto evita cualquier conversión de tipo de cadena en tiempo de ejecución.
YMMV.
fuente
Puedo hablar por experiencia sobre esto, tenga cuidado
nvarchar
. A menos que lo requiera absolutamente, este tipo de campo de datos destruye el rendimiento en bases de datos más grandes. Heredé una base de datos que me dolía en términos de rendimiento y espacio. ¡Pudimos reducir el tamaño de una base de datos de 30GB en un 70%! Se hicieron algunas otras modificaciones para ayudar con el rendimiento, pero estoy seguro de que también hanvarchar
ayudado significativamente con eso. Si su base de datos tiene el potencial de aumentar las tablas a más de un millón de registros, manténgase alejadonvarchar
a toda costa.fuente
Trato con frecuencia esta pregunta en el trabajo:
Fuentes FTP de inventario y precios: las descripciones de los artículos y otros textos estaban en nvarchar cuando varchar funcionaba bien. La conversión de estos a varchar redujo el tamaño del archivo casi a la mitad y realmente ayudó con las cargas.
El escenario anterior funcionó bien hasta que alguien puso un carácter especial en la descripción del artículo (tal vez marca registrada, no recuerdo)
Todavía no uso nvarchar cada vez sobre varchar. Si hay alguna duda o potencial para caracteres especiales, uso nvarchar. Me parece que uso varchar principalmente cuando tengo el 100% de control de lo que está poblando el campo.
fuente
¿Por qué, en toda esta discusión, no se ha mencionado UTF-8? Ser capaz de almacenar el intervalo completo de caracteres unicode no significa que uno deba asignar siempre dos bytes por carácter (o "punto de código" para usar el término UNICODE). Todo el ASCII es UTF-8. ¿SQL Server comprueba los campos VARCHAR () de que el texto es ASCII estricto (es decir, el byte superior bit cero)? Espero que no.
Si luego desea almacenar unicode y desea compatibilidad con aplicaciones antiguas de ASCII, creo que usar VARCHAR () y UTF-8 sería la bala mágica: solo usa más espacio cuando lo necesita.
Para aquellos de ustedes que no estén familiarizados con UTF-8, ¿podría recomendarles una cartilla ?
fuente
N
tipos prefijados). No tiene la opción de usar UTF-8. Además, las codificaciones Unicode (UTF-8, UCS-2 / UTF-16 y UTF-32) no se pueden aplicar a los campos VARCHAR.Habrá casos excepcionales en los que desee restringir deliberadamente el tipo de datos para asegurarse de que no contenga caracteres de un determinado conjunto. Por ejemplo, tuve un escenario en el que necesitaba almacenar el nombre de dominio en una base de datos. La internacionalización de los nombres de dominio no era confiable en ese momento, por lo que era mejor restringir la entrada en el nivel base y ayudar a evitar posibles problemas.
fuente
Si está utilizando
NVARCHAR
solo porque un procedimiento almacenado en el sistema lo requiere, la ocurrencia más frecuente es inexplicablesp_executesql
y su SQL dinámico es muy largo, sería mejor desde la perspectiva del rendimiento realizar todas las manipulaciones de cadenas (concatenación, reemplazo, etc.) alVARCHAR
convertir el resultado finalNVARCHAR
y alimentarlo en el parámetro proc. Así que no, ¡no lo uses siempreNVARCHAR
!fuente