2012-01-25 12 views
5

Si bien researching options para almacenar datos en su mayoría de 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 cadena como codificados en UTF-8.UCS-2 y SQL Server

Sin embargo, Microsoft eligió UCS-2 por razones que no entiendo completamente, lo que me está haciendo dudar de esa inclinación. La documentación de SQL Server 2012 muestra cómo crear un UTF-8 UDT, pero la decisión para UCS-2 presumiblemente impregna SQL Server.

Wikipedia (que curiosamente observa que UCS-2 es obsoleta en favor de UTF-16) señala que UTF-8 es un carácter de anchura variable ajustado 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 puede representarse en UTF-8, y como la mayoría del texto será en inglés, la representación será casi dos veces más compacta que con UCS-2 (sé que el disco es "barato", pero la caché de disco no está 't, y la memoria no está en comparación con los tamaños de datos con los que estoy tratando. Muchas operaciones se degradan exponencialmente cuando el conjunto de trabajo es más grande que la RAM disponible).

¿Qué problemas podría encontrar al navegar por la secuencia de UCS-2?

+0

Sql Server 2012 en Windows 2012 admitirá hasta 4 TB de memoria RAM. En general, es más barato comprar RAM que emplear a alguien para mejorar el código. Es sólo una sugerencia. – Ben

+0

Hice la pregunta mientras decidía sobre la arquitectura de un nuevo sistema. Ese es el momento ideal para hacer tales preguntas. Si RAM o el esfuerzo de codificación es más barato depende de la escala de su problema. Si Google pudiera emplear a un solo programador durante unas semanas para reducir sus necesidades de disco y RAM a la mitad, sería una buena inversión. –

+0

OK, buen punto :-) No estoy trabajando en sistemas tan grandes. Para mí, esas preguntas son fáciles. :-) – Ben

Respuesta

9

almacenando datos en su mayoría de 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 cadena como codificación UTF-8.

A diferencia de algunos otros de RDBMS que permiten la elección de una codificación, SQL Server almacena datos Unicode única en UTF-16 (Little Endian), y no Unicode de datos en ASCII de 8 bits para lo que está implicado página de códigos por la colación del campo

Microsoft eligió UCS-2 por razones que no entendemos completamente

Su decisión de elegir UCS-2 tiene sentido suficiente ya que UTF-16 se introdujo a mediados de 1996 y totalmente especificado en 2000.Muchos otros sistemas también lo usan (o lo usan) (ver: https://en.wikipedia.org/wiki/UTF-16#Usage). Su decisión de continuar con 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 de UCS-2 para admitir UTF-16 debe ser puramente funcional sin necesidad de alterar ningún dato existente.

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

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

Además, esa "documentación" es realmente solo un 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 una secuencia de comandos para probar la funcionalidad, pero nada relacionado con el rendimiento.

pero la decisión para UCS-2 presumiblemente impregna SQL Server.

Sí, mucho más. Por defecto, el manejo de las funciones integradas es solo para UCS-2. Pero comenzando en SQL Server 2012, puede hacer que manejen el conjunto completo de caracteres UTF-16 (bueno, a partir de la versión 5 o 6 de Unicode, dependiendo de su sistema operativo y la versión de .NET Framework) utilizando una de las intercalaciones que tiene un nombre que termina en _SC (es decir, caracteres suplementarios).

Wikipedia ... señala que UCS-2 es obsoleta en favor de UTF-16

correcta. UTF-16 y UCS-2 usan puntos de código de 2 bytes. Pero UTF-16 usa algunos de ellos en pares (es decir, pares sustituidos) para asignar caracteres adicionales. Los puntos de código utilizados para estos pares están reservados para este propósito en UCS-2 y, por lo tanto, no se utilizan para asignar a 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 ... toma nota de que UTF-8 es un personaje de anchura variable fija capaz de codificar cualquier punto de datos Unicode

correcta, aunque engañosa. Sí, UTF-8 es de ancho variable, pero UTF-16 también es levemente variable ya que todos los caracteres suplementarios se componen de dos puntos de código de doble byte. Por lo tanto, UTF-16 usa 2 o 4 bytes por símbolo, aunque UCS-2 siempre es de 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. Mientras que 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 completamente irrelevante desde una perspectiva operativa.

se siente como cualquier carácter Unicode se puede representar en UTF-8

Una vez más, es cierto, pero completamente irrelevante, ya que UTF-16 y UTF-32 también el mapa todos los puntos de código Unicode.

ya que la mayoría de texto será el Inglés, la representación será casi dos veces tan compacto como con UCS-2

Dependiendo de las circunstancias esto podría muy bien ser cierto, y que son correctos para preocuparse tal uso derrochador Sin embargo, como mencioné en la pregunta que conduce a este (UTF-8 Support, SQL Server 2012 and the UTF8String UDT), tiene algunas opciones para mitigar la cantidad de espacio desperdiciado si la mayoría de las filas pueden caber en VARCHAR aunque algunas necesitan ser NVARCHAR. La mejor opción es habilitar ROW COMPRESSION o PAGE COMPRESSION (¡Enterprise Editon solamente!). Comenzando en SQL Server 2008 R2, permiten que los campos que no son MAX NVARCHAR usen el "Esquema de Compresión Estándar para Unicode" que sea al menos tan bueno como UTF-8, y en algunos casos es incluso mejor que UTF-8. NVARCHAR(MAX) los campos no pueden usar esta compresión de lujo, pero sus datos de ROW IN pueden beneficiarse de la compensación normal de ROW y/o PAGE. Consulte lo siguiente para obtener una descripción de esta compresión y un cuadro comparativo de tamaños de datos para: UCS-2/UTF-16 sin procesar, UTF-8 y UCS-2/UTF-16 con habilitación de compresión de datos.

SQL Server 2008 R2 - UCS2 compression what is it - Impact on SAP systems

Consulte también la página de MSDN para Data Compression para más detalles, ya que hay algunas restricciones (más allá de lo que está disponible sólo en Enterprise Edition) y algunas circunstancias cuando la compresión podría empeorar las cosas.

Sé el disco es "barato"

La veracidad de esta afirmación depende de cómo se defina "disco". Si habla en términos de partes de productos básicos que puede comprar en una tienda para su uso en su computadora de escritorio/portátil, entonces seguro. Pero, si habla en términos de almacenamiento a nivel empresarial que se utilizará para sus sistemas de producción, diviértase explicando 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 nadando en la secuencia de UCS-2?

Nada 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 al VARBINARY, o usar NVARCHAR(MAX) para todos los campos de cadena ;-). Pero de todas las cosas de las que podría preocuparse, SQL Server con UCS-2/UTF-16 no debería ser una de ellas.

Pero, si por alguna razón este tema de no compatibilidad nativa para UTF-8 es muy importante, entonces es posible que necesite encontrar otro RDBMS para usar que no permita UTF-8.

0

¿Qué quiere decir con "nadar la secuencia UCS-2"?

Estas son las opciones:

No se recomienda pero posible:

  • Implementar un UDT. Esto requerirá mucho trabajo y perderá soporte de peaje (o mapeo O y ciertamente algunas características de SQL Server que funcionan en tipos nativos).
  • Usar varbinary (max): Requiere que hagas un código de conversión personalizado. Sin indexación de rango.
  • Use nvarchar (N) y active la compresión de filas. Comenzando con SQL Server 2008 R2 esto usará una codificación que es 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.

+1

Al "nadar contra corriente", me refiero a pelear contra la decisión de diseño que MS ha hecho para codificar cadenas en UCS-2. ¿Por qué recomienda las versiones (máximas) frente a las (n) versiones de las definiciones de columnas? ¿El (máximo) no es potencialmente más lento? http://rusanu.com/2010/03/22/performance-comparison-of-varcharmax-vs-varcharn/ –

+0

Las diferentes versiones son igualmente rápidas siempre que pongas las mismas cadenas en ellas. Si coloca cadenas más largas en las columnas más largas, obtendrá, por supuesto, un peor rendimiento. Internamente, el parámetro de tipo de conteo se implementa como un int16 que está prefijando cada columna. No conozco ningún caso en el que cambiar el recuento máximo cambie el rendimiento. – usr

+0

Según tengo entendido, los datos para las variantes (MAX) se almacenan fuera de los datos de la fila, lo que puede causar otra búsqueda en el disco. Creo que esa es la raíz de los números de rendimiento del enlace que compartí. ¿Tiene una referencia que soporte que el rendimiento sea el mismo? –