Com o SQL Server 2019 Microsoft introduz suporte UTF-8 para CHAR
e VARCHAR
tipos de dados e diz:
Esse recurso pode proporcionar economia significativa de armazenamento, dependendo do conjunto de caracteres em uso. Por exemplo, alterar um tipo de dados de coluna existente com cadeias ASCII de NCHAR (10) para CHAR (10) usando um agrupamento habilitado para UTF-8, se traduz em uma redução de quase 50% 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 cadeia Unicode.
O UTF-8 parece suportar todos os scripts, portanto, basicamente, podemos começar a armazenar dados Unicode em varchar
e char
colunas. E como é dito na documentação, isso pode reduzir o tamanho de tabelas e índices e, a partir daí, podemos obter um desempenho ainda melhor, porque uma quantidade menor de dados é lida.
Gostaria de 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 uma razão para não usar os tipos de dados char com UTF
codificação e continuar usando os n-chars?
CHAR
tipos UTF-8 do que tipos Unicode (com ou sem compactação, já que, em última análise, os dados precisam ser descompactados para serem processados). Considere também que o tipo de string nativo do Windows é Unicode, portanto, as strings UTF-8 geralmente precisam ser decodificadas. As compensações envolvidas significam que não é provável que osN
tipos sejam aposentados tão cedo.CHAR
provavelmente é o SQL Server no Linux, se o mecanismo obtiver suporte nativo para processar cadeias diretamente como UTF-8 - aqui UTF-8 é o conjunto de caracteres "nativo" (mais ou menos) e manter as cordas ao redor como UTF-16 é a alternativa menos eficiente. Também não vai doer usá-lo no Windows em locais onde você já está usandoCHAR
, é claro, já que agrupamentos que restringem os caracteres que podem ser armazenados nunca foram atraentes.Respostas:
Redução no tamanho só é possível se a maioria dos personagens são essencialmente
[space]
,0 - 9
,A - Z
,a - z
, e alguns sinais de pontuação básica. Fora desse conjunto específico de caracteres (em termos de uso prático, valores ASCII padrão 32 - 126), você terá, na melhor das hipóteses , tamanho igual aNVARCHAR
/ UTF-16 ou, em muitos casos, maior.Seja cuidadoso. O UTF-8 não é um interruptor mágico "conserte tudo". Todas as outras coisas são 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 têm 1 byte, exigindo, portanto, metade do espaço em comparação com a armazenagem
NVARCHAR
), há uma pequena penalidade de desempenho ao usar UTF-8. Acredito que o problema se deva 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 cadeia precisam começar do início e prosseguir byte a byte. Por outro lado,NVARCHAR
/ UTF-16 é sempre 2 bytes (até caracteres suplementares são compostos por dois pontos de código de 2 bytes), para que tudo possa ser lido em blocos de 2 bytes.Nos meus testes, mesmo com apenas caracteres ASCII padrão, o armazenamento dos dados como UTF-8 não proporcionou economia de tempo decorrido, mas foi definitivamente pior para o tempo da CPU. E isso sem a compactação de dados, pelo menos havia menos espaço em disco usado. Porém, ao usar a compactação, o espaço necessário para o UTF-8 era apenas 1% - 1,5% menor. Tão eficazmente, sem economia de espaço, quanto 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 deverão se beneficiar da compactação de linha ou de página (nesse caso, eles realmente se tornam mais rápidos que o UTF-8). No entanto, dados fora da linha não podem usar nenhuma compactação. Ainda assim, tornar a tabela um Índice de armazenamento de colunas em cluster reduz bastante o tamanho deNVARCHAR(MAX)
(mesmo que ainda seja um pouco maior que UTF-8 ao usar o Índice de armazenamento de colunas em cluster).Definitivamente. Na verdade, não acho realmente um motivo 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. De fato, 21k linhas com uma média de 5k caracteres por linha exigiam 165 MB para UTF-8 e 236 MB para
NVARCHAR
descompactado. E, no entanto,NVARCHAR
foi duas vezes mais rápido no tempo decorrido e pelo menos duas vezes mais rápido (às vezes mais) no tempo da CPU. Ainda assim, foram necessários 71 MB a mais em disco.Fora isso, eu ainda não recomendaria o uso de UTF-8, pelo menos a partir do CTP 2, devido a uma variedade de erros 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 erros, consulte o meu post:
Suporte nativo a UTF-8 no SQL Server 2019: Salvador ou Falso Profeta?
fonte
O suporte UTF-8 oferece um novo conjunto de opções. A economia potencial 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 de comparação, classificação, importação de dados e exportação .
Pode ser necessário alterar mais do que você pensa, pois, por exemplo, um
nchar(1)
tipo fornece dois bytes de armazenamento. Isso é suficiente para armazenar qualquer caractere no BMP (pontos de código 000000 a 00FFFF). Alguns dos caracteres desse intervalo seriam codificados com apenas 1 byte em UTF-8, enquanto outros exigiriam 2 ou até 3 bytes (consulte esta tabela de comparação para obter mais detalhes). Portanto, seria necessário garantir a cobertura do mesmo conjunto de caracteres em UTF-8char(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)
resolver o erro deNCHAR(911)
:No entanto, se fosse
NCHAR(8364)
, por exemplo , 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 visualização no momento, portanto, não está disponível para uso em produção.
fonte