¿Cuáles son las principales diferencias de rendimiento entre varchar y nvarchar tipos de datos SQL Server?

StackOverflow https://stackoverflow.com/questions/35366

Pregunta

Estoy trabajando en una base de datos para una pequeña web app en mi escuela, el uso de SQL Server 2005.
Veo a un par de escuelas de pensamiento sobre la cuestión de la varchar vs nvarchar:

  1. Uso varchar a menos que lidiar con un montón de internacionalización de datos, a continuación, utilizar nvarchar.
  2. Sólo uso nvarchar para todo.

Estoy empezando a ver los méritos de vista 2.Sé que nvarchar ocupa el doble de espacio, pero que no necesariamente es un gran negocio ya que esto sólo va a almacenar los datos de un par de cientos de estudiantes.A mí me parece que sería más fácil no preocuparse de él y sólo permite que todo uso de tipo nvarchar.O es que hay algo que me falta?

¿Fue útil?

Solución

Siempre use nvarchar.

Es posible que nunca necesite los caracteres de doble byte para la mayoría de las aplicaciones.Sin embargo, si usted necesita el soporte de idiomas de doble byte y sólo tiene un solo byte de apoyo en su esquema de base de datos es muy caro para volver atrás y modificar lo largo de su aplicación.

El costo de la migración de una aplicación de varchar, nvarchar va a ser mucho más que el poco de espacio extra en el disco que va a utilizar en la mayoría de las aplicaciones.

Otros consejos

Espacio en el disco no es el problema...pero la memoria y el rendimiento.El doble de la página se lee, el doble de tamaño del índice, extraño COMO y = constante, etc.

¿Necesita guardar Chino etc script?Sí o no...

Y desde MS BOL "Almacenamiento y Rendimiento de los Efectos de Unicode"

Editar:

Los últimos de MODO que la pregunta de relieve cómo la mala nvarchar el rendimiento puede ser...

SQL Server utiliza una CPU de alto al buscar dentro de cadenas de tipo nvarchar

Ser coherente!ÚNETE-ción de un tipo de datos VARCHAR NVARCHAR tiene un gran impacto en el rendimiento.

nvarchar va a tener una importante sobrecarga en la memoria, el almacenamiento, el trabajo conjunto y la indexación, por lo que si las especificaciones exigen que realmente se nunca de ser necesario, no te molestes.

Me gustaría no tener un duro y rápido "siempre nvarchar" regla porque puede ser una completa pérdida de tiempo en muchas situaciones - especialmente ETL de ASCII/EBCDIC o identificadores y código de las columnas, que a menudo son claves y claves foráneas.

Por otro lado, hay un montón de casos de columnas, donde estaría seguro de que esta pregunta temprano y que si no conseguía un duro y rápido responder de inmediato, me gustaría hacer la columna de tipo nvarchar.

Para su aplicación, nvarchar está bien porque el tamaño de base de datos es pequeño.Diciendo "siempre uso nvarchar" es una gran simplificación.Si usted no está requerido para almacenar cosas como Kanji o de otros locos personajes, el uso de tipo VARCHAR, que va a utilizar mucho menos espacio.Mi predecesor en mi trabajo actual diseñado algo utilizando NVARCHAR cuando no era necesario.Hemos cambiado recientemente a VARCHAR y salvó a los 15 GB en sólo esa tabla (fue altamente escrito).Además, si usted tiene un índice en la tabla y desea incluir la columna o de hacer un índice compuesto, acaba de hacer su índice de tamaño de archivo más grande.

Acaba de ser considerado en su decisión;en SQL desarrollo y definiciones de los datos parece que suele ser un "defecto de la respuesta" (aparte de evitar los cursores a toda costa, por supuesto).

No me atrevo a agregar otra respuesta aquí como ya hay bastantes, pero un par de puntos que el hecho de que no se ha hecho o no ha hecho claramente.

Primero: ¿ no siempre uso NVARCHAR.Que es muy peligroso, y a menudo costosos, actitud y enfoque.Y no es mejor decir "Nunca utilice los cursores", ya que a veces son el medio más eficiente para resolver un problema particular, y el trabajo en común-alrededor de de hacer un WHILE bucle casi siempre va a ser más lento que un correctamente hecho Cursor.

La única vez que usted debe utilizar el término "siempre" es cuando se aconseja a "hacer siempre lo que es mejor para la situación".Concedido que es a menudo difícil de determinar, especialmente cuando se trata de equilibrar las ganancias a corto plazo en el tiempo de desarrollo (manager:"necesitamos esta característica-que usted no sabía acerca hasta ahora -- hace una semana!") a largo plazo los costos de mantenimiento (gerente que inicialmente presionado equipo para completar 3 meses de duración del proyecto en 3 semanas de sprint:"¿por qué estamos teniendo estos problemas de rendimiento?¿Cómo podríamos tener posiblemente hecho X que no tiene la flexibilidad?No podemos darnos el lujo de un sprint o dos para solucionar este problema.¿Qué podemos hacer en una semana, así que podemos volver a nuestra elementos de prioridad?Y definitivamente, necesitamos pasar más tiempo en el diseño por lo que esto no siga pasando!").

Segundo: @gbn la respuesta de toques en algunos puntos muy importantes a tener en cuenta al hacer ciertos datos modelado de decisiones cuando la ruta no está 100% claro.Pero aún hay algo más a tener en cuenta:

  • el tamaño de los archivos de registro de transacciones
  • el tiempo que se necesita para replicarse (si se utiliza la replicación)
  • tiempo que se tarda en ETL (si ETLing)
  • tiempo que se tarda para enviar los registros a un sistema remoto y restaurar (si se utiliza un Registro de gastos de Envío)
  • el tamaño de las copias de seguridad
  • la longitud de tiempo que se necesita para completar la copia de seguridad
  • la longitud de tiempo que toma para hacer una restauración (esto podría ser importante algún día ;-)
  • el tamaño necesario para tempdb
  • el rendimiento de los factores desencadenantes (para insertar y borrar las tablas que se almacenan en tempdb)
  • el rendimiento de las versiones de fila (si se utiliza el AISLAMIENTO de INSTANTÁNEA, ya que la versión de la tienda es en tempdb)
  • capacidad de obtener un nuevo espacio en disco cuando el oficial principal de finanzas dice que solo pasaban de $1 millón en un SAN último año y por lo que no se autoriza a otro $250k para almacenamiento adicional
  • la longitud de tiempo que toma para hacer operaciones de INSERCIÓN y ACTUALIZACIÓN
  • la longitud de tiempo que toma para hacer el mantenimiento de los índices
  • etc, etc, etc.

Desperdiciar el espacio tiene un enorme efecto de cascada en todo el sistema.Yo escribí un artículo que va en explícito detalle sobre este tema: El Disco Es Barato!ORLY? (inscripción gratuita necesarios;lo siento, no el control de esa política).

Tercero: Mientras que algunas de las respuestas son incorrectamente, centrándose en el "esto es una pequeña aplicación" de aspecto, y algunos están correctamente lo que sugiere que "el uso de lo que es apropiado", ninguna de las respuestas que han proporcionado real orientación a la O. P.Un detalle importante mencionadas en la Pregunta, es que esto es una página web para su escuela.Genial!!!Por lo que podemos sugerir que:

  • Los campos para los Estudiantes y/o Profesores que los nombres de los probablemente ser NVARCHAR ya que, con el tiempo, sólo es cada vez más probable que los nombres de otras culturas se muestra en esos lugares.
  • Pero para la dirección de la calle y de la ciudad de nombres?El propósito de la aplicación no fue dicho (que habría sido de gran ayuda), pero suponiendo que la dirección de registros, si los hubiere, se refieren sólo a una región geográfica en particular (es decir,un solo idioma / cultura), a continuación, utilizar VARCHAR con el Código apropiado en la Página (que se determina a partir de la Intercalación del campo).
  • Si el Estado de almacenamiento y/o códigos ISO de País (no es necesario para almacenar INT / TINYINT desde ISO códigos de longitud fija, legible para los humanos, y así, estándar :) el uso de CHAR(2) para los códigos de dos letras y CHAR(3) si el uso de códigos de 3 letras.Y considerar el uso de una Intercalación binaria, tales como Latin1_General_100_BIN2.
  • Si el almacenamiento de los códigos postales (es decir,códigos postales), el uso de VARCHAR ya que es un estándar internacional para nunca utilizar cualquier letra fuera de A-Z.Y sí, todavía uso VARCHAR incluso si sólo el almacenamiento de NOSOTROS los códigos postales y no INT desde los códigos postales no son números, son cadenas, y algunos de ellos tienen un "0".Y considerar el uso de una Intercalación binaria, tales como Latin1_General_100_BIN2.
  • Si el almacenamiento de direcciones de correo electrónico y/o direcciones Url, usar NVARCHAR ya que tanto de aquellos que ahora puede contener caracteres Unicode.
  • y así sucesivamente....

Cuarto: Ahora que usted tiene NVARCHAR toma de datos de hasta dos veces la cantidad de espacio que se necesita para los datos que se adapta muy bien a VARCHAR ("encaja perfectamente" = no se convierta en "?") y de alguna manera, como si por arte de magia, hizo la aplicación de crecer y ahora hay millones de registros en al menos uno de estos campos donde la mayoría de los las filas son ASCII estándar, pero algunos contienen caracteres Unicode, así que debes mantener NVARCHAR, considere la siguiente:

  1. Si está utilizando SQL Server 2008 - 2016 RTM y están en Enterprise Edition, O si utiliza SQL Server 2016 SP1 (que hizo la Compresión de Datos disponibles en todas las ediciones) o más reciente, a continuación, puede habilitar La Compresión De Datos.La Compresión de datos puede (pero no "siempre") comprimir los datos Unicode en NCHAR y NVARCHAR campos.Los factores determinantes son:

    1. NCHAR(1 - 4000) y NVARCHAR(1 - 4000) el uso de la Esquema de Compresión estándar de Unicode, pero sólo a partir de SQL Server 2008 R2, Y sólo EN los datos de la FILA, no DESBORDAMIENTO!Este parece ser mejor que la normal de la FILA / PÁGINA algoritmo de compresión.
    2. NVARCHAR(MAX) y XML (y supongo que también VARBINARY(MAX), TEXT, y NTEXT) de datos que está EN la FILA (no fuera de la fila en LOB o DESBORDAMIENTO de páginas) al menos puede ser la compresión de PÁGINA, pero no Compresión de FILA.Por supuesto, la compresión de la PÁGINA depende del tamaño de la fila valor de:He probado con el tipo de datos VARCHAR(MAX) y vi que 6000 caracteres/byte filas no comprimir, pero 4000 caracteres/byte filas hizo.
    3. Los datos de la FILA, LOB o OVERLOW = Sin Compresión Para Usted!
  2. Si utiliza SQL Server 2005 o 2008 - 2016 RTM y no en Enterprise Edition, usted puede tener dos campos:uno VARCHAR y uno NVARCHAR.Por ejemplo, digamos que usted está almacenando las direcciones Url que son en su mayoría de la base de caracteres ASCII (valores de 0 - 127) y, por tanto, encaja en VARCHAR, pero a veces tiene caracteres Unicode.El esquema puede incluir los siguientes 3 campos:

      ...
      URLa VARCHAR(2048) NULL,
      URLu NVARCHAR(2048) NULL,
      URL AS (ISNULL(CONVERT(NVARCHAR([URLa])), [URLu])),
      CONSTRAINT [CK_TableName_OneUrlMax] CHECK (
                        ([URLa] IS NOT NULL OR [URLu] IS NOT NULL)
                    AND ([URLa] IS NULL OR [URLu] IS NULL))
    );
    

    En este modelo sólo SELECCIONE una de las [URL] columna calculada.Para insertar y actualizar, determinar el campo que desea utilizar para ver si la conversión se modifica el valor de entrada, que tiene que ser de NVARCHAR tipo:

    INSERT INTO TableName (..., URLa, URLu)
    VALUES (...,
            IIF (CONVERT(VARCHAR(2048), @URL) = @URL, @URL, NULL),
            IIF (CONVERT(VARCHAR(2048), @URL) <> @URL, NULL, @URL)
           );
    
  3. Usted puede GZIP valores entrantes en VARBINARY(MAX) y, a continuación, descomprima en el camino:

    • Para SQL Server 2005 - 2014:usted puede utilizar SQLCLR. SQL# (un SQLCLR biblioteca que escribí) viene con Util_GZip y Util_GUnzip en la versión Gratuita
    • Para SQL Server 2016 y más reciente:usted puede utilizar el built-in COMPRESS y DECOMPRESS funciones, que son también GZip.
  4. Si utiliza SQL Server 2017 o posterior, usted puede buscar en hacer de la mesa un Clúster de Índice de almacén de columnas.

  5. Aunque esto no es una opción viable, sin embargo, SQL Server 2019 introduce soporte nativo para UTF-8 en VARCHAR / CHAR los tipos de datos.Actualmente hay demasiados errores con ella para que se utiliza, pero si se fija, entonces esta es una opción para algunos los escenarios.Por favor, ver mi post, "Nativo de Soporte de UTF-8 en SQL Server 2019:Salvador o Falso Profeta?"para un análisis detallado de esta nueva característica.

Desde que la aplicación es pequeña, no hay prácticamente ninguna apreciable incremento de los costos para el uso de nvarchar más de tipo varchar, y usted se ahorrará posibles dolores de cabeza en el futuro, si usted tiene una necesidad de almacenar los datos unicode.

Hablando en general;Empezar con el más caro de tipo de datos que tiene menos restricciones. Ponerlo en producción.Si el rendimiento comienza a ser un problema, averiguar lo que realmente se almacena en los nvarchar columnas.Es que hay personajes que no encajan en varchar?Si no, cambie a varchar.No trate de pre-optimizar antes de saber donde está el dolor.Mi conjetura es que la elección entre nvarchar/varchar no es lo que se va a ralentizar su aplicación en el futuro previsible.Habrá otras partes de la aplicación en la optimización de rendimiento de le dará mucho más bang para los bucks.

Para que los últimos años todos nuestros proyectos han utilizado NVARCHAR para todo, ya que todos estos proyectos son multilingües.Datos importados de fuentes externas (por ejemplo,un archivo ASCII, etc.) es convertir a Unicode antes de ser insertado en la base de datos.

Aún tengo que encontrar cualquier problema relacionado con el rendimiento de los mayores índices, etc.Los índices de hacer uso de más memoria, pero la memoria es barata.

Si utiliza procedimientos almacenados o construir SQL sobre la marcha, asegúrese de que todas las constantes de cadena con el prefijo N (por ejemplo,SET @foo = N'Hello mundo".;) así, la constante es también Unicode.Esto evita cualquier cadena de conversión de tipo en tiempo de ejecución.

YMMV.

Puedo hablar desde la experiencia en esto, tenga cuidado de nvarchar.A menos que absolutamente necesario este campo de datos tipo de destruye el rendimiento en la base de datos más grande.He heredado una base de datos que estaba sufriendo en términos de rendimiento y espacio.Hemos sido capaces de reducir un 30 GB de base de datos en el tamaño de un 70%!Hubo algunas otras modificaciones realizadas para ayudar con el rendimiento, pero estoy seguro de que el varchar's ayudó mucho con eso.Si su base de datos tiene el potencial para el crecimiento de las tablas de un millón de + los registros de mantenerse alejado de nvarchar en todos los costos.

Estoy de acuerdo con esta pregunta en el trabajo a menudo:

  • FTP se alimenta de inventario y a las tarifas, descripciones de los artículos y otros textos en nvarchar cuando varchar funcionaba bien.La conversión de estos a varchar tamaño de archivo reducido casi a la mitad y realmente me ayudó con las subidas.

  • El escenario anterior funcionaba bien hasta que alguien ponga un carácter especial en la descripción del artículo (tal vez la marca, no recuerdo)

Yo todavía no utilice nvarchar cada vez más de tipo varchar.Si hay alguna duda o potencial para caracteres especiales, yo uso nvarchar.Me parece que el uso varchar sobre todo cuando estoy en control del 100% de lo que es llenar el campo.

Por qué, en toda esta discusión, no ha habido mención de UTF-8?Ser capaz de almacenar la información completa de unicode lapso de caracteres no significa que uno tiene que siempre asignar dos bytes por carácter (o "punto de código", para usar el UNICODE plazo).Todos los de ASCII es UTF-8.¿De verificación SQL Server para VARCHAR() campos en los que el texto es de estricta ASCII (es decir,top byte bit cero)?Espero que no.

Si luego desea almacenar unicode y desea compatibilidad con anteriores ASCII-sólo las aplicaciones, yo creo que el uso de VARCHAR() y UTF-8 sería la bala mágica:Solo se utiliza más espacio cuando sea necesario.

Para aquellos no familiarizados con UTF-8, podría recomiendo una capa de imprimación.

Habrá casos excepcionales en los que usted querrá deliberadamente restringir el tipo de datos para asegurarse de que no contienen caracteres de un determinado conjunto.Por ejemplo, yo tenía un escenario en el que necesitaba para almacenar el nombre de dominio en una base de datos.La internacionalización de los nombres de dominio no era fiable en el tiempo, así que era mejor para restringir la entrada en el nivel básico, y ayuda a evitar posibles problemas.

Si usted está usando NVARCHAR sólo porque un procedimiento almacenado del sistema lo requiere, el más frecuente de ocurrencia de ser inexplicablemente sp_executesql, y su dinámica SQL es muy largo, sería mucho mejor desde la perspectiva del desempeño de hacer todas las manipulaciones de cadenas (concatenación, sustitución, etc.) en VARCHAR a continuación, convertir el resultado final NVARCHAR y la alimentación en el proc parámetro.Así que no, no siempre el uso de NVARCHAR!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top