Pergunta

Enquanto pesquisando opções para armazenar dados principalmente em inglês, mas às vezes não em um banco de dados SQL Server que pode ser potencialmente muito grande, estou inclinado a armazenar a maioria dos dados de string como codificados em UTF-8.

No entanto, a Microsoft escolheu o UCS-2 por razões que não entendo completamente, o que me faz duvidar dessa tendência.A documentação do SQL Server 2012 mostra como criar um UTF-8 UDT, mas a decisão para o UCS-2 presumivelmente permeia o SQL Server.

Wikipédia (que curiosamente observa que o UCS-2 está obsoleto em favor do UTF-16) observa que o UTF-8 é um conjunto de caracteres de largura variável capaz de codificar qualquer ponto de dados Unicode e que provides the de facto standard encoding for interchange of Unicode text.Portanto, parece que qualquer caractere Unicode pode ser representado em UTF-8 e, como a maior parte do texto será em inglês, a representação será quase duas vezes mais compacta que no UCS-2 (eu sei que o disco é "barato", mas o cache do disco não é 't, e a memória não é comparada aos tamanhos de dados com os quais estou lidando.Muitas operações degradam exponencialmente quando o conjunto de trabalho é maior que a RAM disponível).

Que problemas posso encontrar ao nadar no fluxo UCS-2?

Foi útil?

Solução

armazenando principalmente dados em inglês, mas às vezes não em um banco de dados SQL Server que pode ser potencialmente muito grande, estou inclinado a armazenar a maioria dos dados de string como codificados em UTF-8.

Ao contrário de alguns outros RDBMS que permitem a escolha de uma codificação, o SQL Server armazena dados Unicode apenas em UTF-16 (Little Endian) e dados não Unicode em uma codificação de 8 bits (Extended ASCII, DBCS ou EBCDIC) para qualquer página de código implícita no agrupamento do campo.

A Microsoft escolheu o UCS-2 por motivos que não entendo totalmente

A decisão deles de escolher O UCS-2 faz sentido, visto que o UTF-16 foi introduzido em meados de 1996 e totalmente especificado em 2000.Muitos outros sistemas também o usam (ou usaram) (veja: https://en.wikipedia.org/wiki/UTF-16#Usage).A decisão deles de continuar com isso pode ser mais questionável, embora provavelmente seja devido ao fato de o Windows e o .NET serem UTF-16.O layout físico dos bytes é o mesmo entre UCS-2 e UTF-16, portanto, a atualização dos sistemas de UCS-2 para suportar UTF-16 deve ser puramente funcional, sem necessidade de alterar quaisquer dados existentes.

A documentação do SQL Server 2012 mostra como criar um UDT UTF-8,

Hum, não.Criar um tipo personalizado definido pelo usuário via SQLCLR é não, de qualquer forma, conseguirá uma substituição de qualquer tipo nativo.É muito útil para criar algo para lidar com dados especializados.Mas as strings, mesmo com uma codificação diferente, estão longe de ser especializadas.Seguir esse caminho para seus dados de string destruiria qualquer usabilidade do seu sistema, sem mencionar o desempenho, pois você não seria capaz de usar qualquer funções de string integradas.Se você conseguisse economizar espaço em disco, esses ganhos seriam anulados pelo que você perderia no desempenho geral.O armazenamento de um UDT é feito serializando-o em um VARBINARY.Então para fazer qualquer comparação de strings OU classificação, fora de uma comparação "binária"/"ordinal", você teria que converter todos os outros valores, um por um, de volta para UTF-8 para então fazer a comparação de strings que pode explicar as diferenças linguísticas.

Além disso, essa "documentação" é apenas um exemplo de código/prova de conceito.O código foi escrito em 2003 ( http://msftengprodsamples.codeplex.com/SourceControl/latest#Kilimanjaro_Trunk/Programmability/CLR/UTF8String/CS/UTF8String/Utf8String.cs ) para SQL Server 2005.Vi um script para testar funcionalidade, mas nada envolvendo performance.

mas a decisão pelo UCS-2 presumivelmente permeia o SQL Server.

Sim muito mesmo.Por padrão, o manuseio das funções integradas é apenas para UCS-2.Mas a partir do SQL Server 2012, você pode fazer com que eles manipulem o conjunto completo de caracteres UTF-16 (bem, a partir do Unicode versão 5 ou 6, dependendo do seu sistema operacional e da versão do .NET Framework) usando um dos agrupamentos que tem um nome que termina em _SC (ou seja,Caracteres Suplementares).

Wikipédia ...observa que o UCS-2 está obsoleto em favor do UTF-16

Correto.UTF-16 e UCS-2 usam pontos de código de 2 bytes.Mas o UTF-16 usa alguns deles em pares (ou seja,Pares substitutos) para mapear personagens adicionais.Os pontos de código usados ​​para esses pares são reservados para esse propósito no UCS-2 e, portanto, não são usados ​​para mapear nenhum símbolo utilizável.É por isso que você pode armazenar qualquer caractere Unicode no SQL Server e ele será armazenado e recuperado corretamente.

Wikipédia ...observa que UTF-8 é um conjunto de caracteres de largura variável capaz de codificar qualquer ponto de dados Unicode

Correto, embora enganoso.Sim, UTF-8 tem largura variável, mas UTF-16 também é pouco variável, pois todos os caracteres suplementares são compostos de dois pontos de código de byte duplo.Portanto, o UTF-16 usa 2 ou 4 bytes por símbolo, embora o UCS-2 tenha sempre 2 bytes.Mas essa não é a parte enganosa.O que é enganoso é a implicação de que qualquer outra codificação Unicode não é capaz de codificar todos os outros pontos de código.Embora o UCS-2 possa mantê-los, mas não interpretá-los, tanto o UTF-16 quanto o UTF-32 podem mapear todos os pontos de código Unicode, assim como o UTF-8.

e que [ed:UTF-8] fornece a codificação padrão de fato para intercâmbio de texto Unicode.

Isto pode ser verdade, mas é totalmente irrelevante do ponto de vista operacional.

parece que qualquer caractere Unicode pode ser representado em UTF-8

Novamente, é verdade, mas totalmente irrelevante, já que UTF-16 e UTF-32 também mapeiam todos os pontos de código Unicode.

como a maior parte do texto será em inglês, a representação será quase duas vezes mais compacta que no UCS-2

Dependendo das circunstâncias, isso pode muito bem ser verdade, e você está certo em se preocupar com esse uso desnecessário.No entanto, como mencionei na pergunta que levou a esta ( Suporte UTF-8, SQL Server 2012 e UTF8String UDT ), você tem algumas opções para reduzir a quantidade de espaço desperdiçado se a maioria das linhas couber VARCHAR ainda assim, alguns precisam ser NVARCHAR.A melhor opção é ativar ROW COMPRESSION ou PAGE COMPRESSION (somente Enterprise Editon!).A partir do SQL Server 2008 R2, eles permitem não-MAX NVARCHAR campos para usar o "Esquema de compactação padrão para Unicode", que é pelo menos tão bom quanto UTF-8 e, em alguns casos, é ainda melhor que UTF-8. NVARCHAR(MAX) os campos não podem usar esta compactação sofisticada, mas seus dados IN ROW podem se beneficiar da compactação ROW e/ou PAGE regular.Consulte o seguinte para obter uma descrição dessa compactação e um gráfico comparando os tamanhos dos dados para:UCS-2/UTF-16 bruto, UTF-8 e UCS-2/UTF-16 brutos com compactação de dados habilitada.

SQL Server 2008 R2 – Compressão UCS2 o que é – Impacto nos sistemas SAP

Consulte também a página do MSDN para Compressão de dados para mais detalhes, pois existem algumas restrições (além de estar disponível apenas na Enterprise Edition - MAS disponibilizado para todos edições começando com SQL Server 2016, SP1 !!) e algumas circunstâncias em que a compactação pode piorar as coisas.

Eu sei que o disco é "barato"

A veracidade dessa afirmação depende de como se define “disco”.Se você está falando em termos de peças básicas que você pode comprar na prateleira de uma loja para usar em seu desktop/laptop, então com certeza.Mas, se estiver falando em termos de armazenamento de nível empresarial que será usado em seus sistemas de produção, divirta-se explicando a quem controla o orçamento que não deve rejeitar a SAN de mais de um milhão de dólares que você deseja porque é "barata". " ;-).

Que problemas posso encontrar ao nadar no fluxo UCS-2?

Nenhum que eu consiga pensar.Bem, contanto que você não siga nenhum conselho horrível para fazer algo como implementar esse UDT ou converter todas as strings para VARBINARY, ou usando NVARCHAR(MAX) para todos os campos de string ;-).Mas de todas as coisas com as quais você pode se preocupar, o SQL Server usando UCS-2/UTF-16 não deveria ser uma delas.

Mas, se por algum motivo esse problema de não suporte nativo para UTF-8 for muito importante, talvez seja necessário encontrar outro RDBMS para usar que permita UTF-8.


ATUALIZAÇÃO 02/10/2018

Embora esta ainda não seja uma opção viável, o SQL Server 2019 introduz suporte nativo para UTF-8 em VARCHAR / CHAR tipos de dados.Atualmente existem muitos bugs para que ele possa ser usado, mas se eles forem corrigidos, então esta é uma opção para alguns cenários.Por favor, veja minha postagem, "Suporte nativo a UTF-8 no SQL Server 2019:Salvador ou Falso Profeta?", para uma análise detalhada deste novo recurso.

Outras dicas

O que você quer dizer com "nadar no fluxo UCS-2"?

Aqui estão as suas opções:

  • use as novas classes 2012 _sc ( https://msdn.microsoft.com/en-us/library/ms143726.aspx ).Essa ideia vem de Srutzky.Você deve conferir sua resposta.Esta é de longe a melhor solução.

    Não recomendado, mas possível:

    • Implementar um UDT.Isso será muito trabalho e você perderá o suporte de pedágio (ou o mapeamento e certamente alguns recursos do SQL Server que funcionam em tipos nativos).
    • use varbinary (max): requer que você faça o código de conversão personalizado.Sem indexação de alcance.
    • use nvarchar (n) e ligue a compressão de linha.Começando com o SQL Server 2008 R2, isso usará uma codificação que é compacta como UTF-8.Mas isso requer edição empresarial.

      Veja os comentários para ler sobre as desvantagens graves que essas abordagens têm.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top