Pregunta

Mientras investigando opciones Para almacenar datos en su mayoría en inglés, pero a veces no en una base de datos de SQL Server que puede ser bastante grande, me inclino por almacenar la mayoría de los datos de cadenas codificados en UTF-8.

Sin embargo, Microsoft eligió UCS-2 por razones que no entiendo del todo y que me hacen dudar de esa inclinación.La documentación de SQL Server 2012 muestra cómo crear un UTF-8 UDT, pero la decisión a favor de UCS-2 presumiblemente impregna SQL Server.

Wikipedia (que curiosamente señala que UCS-2 está obsoleto a favor de UTF-16) señala que UTF-8 es un conjunto de caracteres de ancho variable capaz de codificar cualquier punto de datos Unicode y que provides the de facto standard encoding for interchange of Unicode text.Por lo tanto, parece que cualquier carácter Unicode se puede representar en UTF-8 y, dado que la mayor parte del texto estará en inglés, la representación será casi dos veces más compacta que con UCS-2 (sé que el disco es "barato", pero el caché del disco no lo es). No, y la memoria no se compara con los tamaños de datos con los que estoy tratando.Muchas operaciones se degradan exponencialmente cuando el conjunto de trabajo es mayor que la RAM disponible).

¿Qué problemas podría encontrar al nadar por la corriente UCS-2?

¿Fue útil?

Solución

Al almacenar datos principalmente en inglés, pero a veces no en una base de datos de SQL Server que puede ser bastante grande, me inclino por almacenar la mayoría de los datos de cadenas codificados en UTF-8.

A diferencia de otros RDBMS que permiten elegir una codificación, SQL Server almacena datos Unicode solo en UTF-16 (Little Endian) y datos no Unicode en una codificación de 8 bits (ASCII extendido, DBCS o EBCDIC) para cualquier página de códigos implícita en la intercalación del campo.

Microsoft eligió UCS-2 por razones que no entiendo del todo

Su decisión de elegir UCS-2 tiene bastante sentido dado que UTF-16 se introdujo a mediados de 1996 y se especificó por completo en 2000.Muchos otros sistemas también lo usan (o usaron) (consulte: https://en.wikipedia.org/wiki/UTF-16#Usage).Su decisión de continuar con él podría ser más cuestionable, aunque probablemente se deba a que Windows y .NET son UTF-16.El diseño físico de los bytes es el mismo entre UCS-2 y UTF-16, por lo que actualizar los sistemas desde UCS-2 para que admitan UTF-16 debería ser puramente funcional sin necesidad de alterar ningún dato existente.

La documentación de SQL Server 2012 muestra cómo crear un UDT UTF-8,

Mmm no.Crear un tipo personalizado definido por el usuario a través de SQLCLR es no, de cualquier manera, conseguirá un reemplazo de cualquier tipo nativo.Es muy útil para crear algo que maneje datos especializados.Pero las cadenas, incluso con una codificación diferente, están lejos de ser especializadas.Seguir esta ruta para los datos de su cadena destruiría cualquier cantidad de usabilidad de su sistema, sin mencionar el rendimiento, ya que no podría usar cualquier funciones de cadena incorporadas.Si pudiera guardar algo en espacio en el disco, esas ganancias se borrarían por lo que perdería en rendimiento general.El almacenamiento de un UDT se realiza serializándolo en un VARBINARY.Entonces para poder hacer cualquier comparación de cadenas O clasificación, fuera de una comparación "binaria"/"ordinal", tendría que convertir todos los demás valores, uno por uno, nuevamente a UTF-8 para luego realizar la comparación de cadenas que pueda tener en cuenta las diferencias lingüísticas.

Además, esa "documentación" es en realidad solo código de muestra/prueba de concepto.El código fue escrito en 2003 ( http://msftengprodsamples.codeplex.com/SourceControl/latest#Kilimanjaro_Trunk/Programmability/CLR/UTF8String/CS/UTF8String/Utf8String.cs ) para SQL Server 2005.Vi un script para probar la funcionalidad, pero nada relacionado con el rendimiento.

pero la decisión a favor de UCS-2 presumiblemente impregna a SQL Server.

Sí mucho así.De forma predeterminada, el manejo de las funciones integradas es sólo para UCS-2.Pero a partir de SQL Server 2012, puede hacer que manejen el conjunto de caracteres UTF-16 completo (bueno, a partir de la versión Unicode 5 o 6, según su sistema operativo y la versión de .NET Framework) usando una de las intercalaciones que tiene un nombre que termina en _SC (es decir.Personajes suplementarios).

Wikipedia...señala que UCS-2 está obsoleto a favor de UTF-16

Correcto.Tanto UTF-16 como UCS-2 utilizan puntos de código de 2 bytes.Pero UTF-16 usa algunos de ellos en pares (es decir,Pares sustitutos) para asignar personajes adicionales.Los puntos de código utilizados para estos pares están reservados para este fin en UCS-2 y, por tanto, no se utilizan para asignar ningún símbolo utilizable.Es por eso que puede almacenar cualquier carácter Unicode en SQL Server y se almacenará y recuperará correctamente.

Wikipedia...señala que UTF-8 es un conjunto de caracteres de ancho variable capaz de codificar cualquier punto de datos Unicode

Correcto, aunque engañoso.Sí, UTF-8 tiene un ancho variable, pero UTF-16 también es ligeramente variable ya que todos los caracteres suplementarios están compuestos por dos puntos de código de doble byte.Por lo tanto, UTF-16 utiliza 2 o 4 bytes por símbolo, aunque UCS-2 siempre tiene 2 bytes.Pero esa no es la parte engañosa.Lo que es engañoso es la implicación de que cualquier otra codificación Unicode no es capaz de codificar todos los demás puntos de código.Si bien UCS-2 puede contenerlos pero no interpretarlos, tanto UTF-16 como UTF-32 pueden mapear todos los puntos de código Unicode, al igual que UTF-8.

y que [ed:UTF-8] proporciona la codificación estándar de facto para el intercambio de texto Unicode.

Esto puede ser cierto, pero es totalmente irrelevante desde una perspectiva operativa.

parece que cualquier carácter Unicode puede representarse en UTF-8

Nuevamente, es cierto, pero completamente irrelevante ya que UTF-16 y UTF-32 también asignan todos los puntos de código Unicode.

Dado que la mayor parte del texto estará en inglés, la representación será casi dos veces más compacta que con UCS-2.

Dependiendo de las circunstancias, esto bien podría ser cierto, y tiene razón al preocuparse por un uso tan despilfarrador.Sin embargo, como mencioné en la pregunta que condujo a esta ( Compatibilidad con UTF-8, SQL Server 2012 y UTF8String UDT ), tiene algunas opciones para mitigar la cantidad de espacio desperdiciado si la mayoría de las filas caben en VARCHAR sin embargo, algunos necesitan ser NVARCHAR.La mejor opción es habilitar la COMPRESIÓN DE FILAS o la COMPRESIÓN DE PÁGINA (¡solo Enterprise Editon!).A partir de SQL Server 2008 R2, permiten versiones no MAX NVARCHAR campos para utilizar el "Esquema de compresión estándar para Unicode", que es al menos tan bueno como UTF-8 y, en algunos casos, incluso mejor que UTF-8. NVARCHAR(MAX) Los campos no pueden usar esta elegante compresión., pero sus datos IN ROW pueden beneficiarse de la compresión regular de FILA y/o PÁGINA.Consulte lo siguiente para obtener una descripción de esta compresión y un cuadro que compara los tamaños de datos para:UCS-2/UTF-16, UTF-8 y UCS-2/UTF-16 sin formato con compresión de datos habilitada.

SQL Server 2008 R2 - Compresión UCS2 qué es - Impacto en los sistemas SAP

Consulte también la página de MSDN para Compresión de datos para obtener más detalles, ya que existen algunas restricciones (más allá de que esté disponible solo en Enterprise Edition, PERO disponible para todo ediciones que comienzan con SQL Server 2016, SP1!!) y algunas circunstancias en las que la compresión puede empeorar las cosas.

Sé que el disco es "barato"

La veracidad de esa afirmación depende de cómo se defina "disco".Si está hablando en términos de piezas básicas que puede comprar en una tienda para usar en su computadora de escritorio o portátil, entonces claro.Pero, si habla en términos de almacenamiento de nivel empresarial que se utilizará para sus sistemas de producción, entonces diviértase explicándole a quien controle el presupuesto que no debe rechazar la SAN de más de un millón de dólares que desea porque es "barata". " ;-).

¿Qué problemas podría encontrar al nadar por la corriente UCS-2?

Ninguno que se me ocurra.Bueno, siempre y cuando no sigas ningún consejo horrible para hacer algo como implementar ese UDT o convertir todas las cadenas a VARBINARY, o usando NVARCHAR(MAX) para todos los campos de cadena ;-).Pero de todas las cosas por las que podría preocuparse, SQL Server que usa UCS-2/UTF-16 no debería ser una de ellas.

Pero, si por alguna razón este problema de falta de soporte nativo para UTF-8 es muy importante, entonces es posible que necesite encontrar otro RDBMS que permita UTF-8.


ACTUALIZACIÓN 2018-10-02

Si bien esta aún no es una opción viable, SQL Server 2019 introduce soporte nativo para UTF-8 en VARCHAR / CHAR tipos de datos.Actualmente hay demasiados errores como para usarlo, pero si se solucionan, entonces esta es una opción para alguno escenarios.Por favor mira mi publicación, "Compatibilidad nativa con UTF-8 en SQL Server 2019:¿Salvador o falso profeta?", para un análisis detallado de esta nueva característica.

Otros consejos

¿Qué quieres decir con "nadar en la corriente UCS-2"?

Aquí están sus opciones:

No recomendado pero posible:

  • Implementar un UDT.Esto supondrá mucho trabajo y perderá soporte de pago (O mapeo y ciertamente algunas características de SQL Server que funcionan en tipos nativos).
  • Utilice varbinary(max):Requiere que hagas un código de conversión personalizado.Sin indexación de rango.
  • Utilice nvarchar(N) y active la compresión de filas.A partir de SQL Server 2008 R2, se utilizará una codificación tan compacta como UTF-8.Pero esto requiere una edición empresarial.

Consulte los comentarios para leer sobre los graves inconvenientes que tienen estos enfoques.

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