Com o SQL Server 2019, a Microsoft apresenta suporte a UTF-8CHAR
e VARCHAR
tipos de dados e diz:
Esse recurso pode proporcionar economias de armazenamento significativas, dependendo do conjunto de caracteres em uso. Por exemplo, alterar um tipo de dados de coluna existente com strings ASCII de NCHAR(10) para CHAR(10) usando um agrupamento habilitado para UTF-8 se traduz em quase 50% de redução nos requisitos de armazenamento. Essa redução ocorre porque NCHAR(10) requer 22 bytes para armazenamento, enquanto CHAR(10) requer 12 bytes para a mesma string Unicode.
O UTF-8 parece suportar todos os scripts, então basicamente podemos começar a armazenar dados Unicode em varchar
e char
colunas. E como é dito na documentação, isso pode reduzir o tamanho das tabelas e índices, e a partir daí podemos obter um desempenho ainda melhor, pois uma quantidade menor de dados é lida.
Eu estou querendo saber se isso significa que podemos parar de usar nvarchar
e nchar
colunas que implementam UTF-16?
Alguém pode apontar um cenário e motivo, para não usar os tipos de dados char com UTF
codificação e continuar usando os n-chars?
O suporte a UTF-8 oferece um novo conjunto de opções. Potencial economia de espaço (sem compactação de linha ou página ) é uma consideração, mas a escolha do tipo e codificação provavelmente deve ser feita principalmente com base nos requisitos reais para comparação, classificação, importação de dados e exportação .
Você pode precisar alterar mais do que pensa, pois, por exemplo, um
nchar(1)
tipo fornece dois bytes de armazenamento. Isso é suficiente para armazenar qualquer caractere em BMP (pontos de código 000000 a 00FFFF). Alguns dos caracteres nesse intervalo seriam codificados com apenas 1 byte em UTF-8, enquanto outros exigiriam 2 ou até 3 bytes (consulte este gráfico de comparação para obter mais detalhes). Portanto, garantir a cobertura do mesmo conjunto de caracteres em UTF-8 exigiriachar(3)
.Por exemplo:
dá o erro familiar:
Ou se o sinalizador de rastreamento 460 estiver ativo:
Expandir a coluna UTF8 para
char(2)
ouvarchar(2)
resolve o erro paraNCHAR(911)
:No entanto, se fosse, por exemplo
NCHAR(8364)
, , você precisaria expandir ainda mais a coluna, parachar(3)
ouvarchar(3)
.Observe também que todos os agrupamentos UTF-8 usam caracteres suplementares, portanto , não funcionarão com replicação.
Além de qualquer outra coisa, o suporte a UTF-8 está apenas em pré-visualização no momento, portanto, não está disponível para uso em produção.
A redução de tamanho só é possível se a maioria dos caracteres for essencialmente
[space]
,0 - 9
,A - Z
,a - z
, e alguma pontuação básica. Fora desse conjunto específico de caracteres (em termos de uso prático, valores ASCII padrão de 32 a 126), você será, na melhor das hipóteses, igual em tamanho aNVARCHAR
/ UTF-16 ou, em muitos casos, maior.Tome cuidado. UTF-8 não é um switch mágico de "consertar tudo". Todas as outras coisas sendo iguais, sim, ler menos melhora o desempenho. Mas aqui "todas as outras coisas" não são iguais. Mesmo ao armazenar apenas caracteres ASCII padrão (ou seja: todos os caracteres são de 1 byte, portanto, exigindo metade do espaço em comparação com o armazenamento em
NVARCHAR
), há uma pequena penalidade de desempenho ao usar UTF-8. Acredito que o problema se deve ao fato de o UTF-8 ser uma codificação de comprimento variável, o que significa que cada byte deve ser interpretado conforme é lido para saber se é um caractere completo ou se o próximo byte faz parte dele. Isso significa que todas as operações de string precisam começar no início e prosseguir byte a byte. Por outro lado,NVARCHAR
/ UTF-16 é sempre de 2 bytes (mesmo Caracteres Suplementares são compostos por dois Pontos de Código de 2 bytes), então tudo pode ser lido em pedaços de 2 bytes.Em meus testes, mesmo com apenas caracteres ASCII padrão, armazenar os dados como UTF-8 não proporcionou economia de tempo decorrido, mas foi definitivamente pior para o tempo de CPU. E isso foi sem compactação de dados, então pelo menos havia menos espaço em disco usado. Mas, ao usar compactação, o espaço necessário para UTF-8 era apenas 1% - 1,5% menor. Tão eficazmente sem economia de espaço ainda maior tempo de CPU para UTF-8.
As coisas ficam mais complicadas ao usar
NVARCHAR(MAX)
, pois a compactação Unicode não funciona com esse tipo de dados, mesmo que o valor seja pequeno o suficiente para ser armazenado em linha. Mas, se os dados forem pequenos o suficiente, eles ainda devem se beneficiar da compactação de linha ou página (nesse caso, ele se torna mais rápido que o UTF-8). No entanto, os dados fora da linha não podem usar nenhuma compactação. Ainda assim, tornar a tabela um Índice Columnstore Clusterizado reduz bastante o tamanho deNVARCHAR(MAX)
(mesmo que ainda seja um pouco maior que UTF-8 ao usar o Índice Columnstore Clusterizado).Definitivamente. Na verdade, eu realmente não encontro uma razão convincente para usá-lo na maioria dos casos. O único cenário que realmente se beneficia do UTF-8 é:
VARCHAR
)Meus testes mostram que em quase todos os casos, o NVARCHAR foi mais rápido, especialmente quando havia mais dados. Na verdade, 21 mil linhas com uma média de 5 mil caracteres por linha exigiam 165 MB para UTF-8 e 236 MB para
NVARCHAR
não compactados. E, no entanto,NVARCHAR
foi 2x mais rápido no tempo decorrido e pelo menos 2x mais rápido (às vezes mais) no tempo de CPU. Ainda assim, ele ocupava 71 MB a mais no disco.Fora isso, eu ainda não recomendaria usar UTF-8, pelo menos a partir do CTP 2, devido a uma variedade de bugs que encontrei nesse recurso.
Para uma análise detalhada desse novo recurso, incluindo uma explicação das diferenças entre UTF-16 e UTF-8 e uma lista desses bugs, consulte minha postagem:
Suporte nativo a UTF-8 no SQL Server 2019: Salvador ou Falso Profeta?