Eu configurei o agrupamento de banco de dados para Latin1_General_BIN
, para fazer comparações de strings com distinção entre maiúsculas e minúsculas. Isso terá impacto no desempenho? Isso terá algum impacto nas operações DML ou DDL no banco de dados? O banco de dados já existe com tabelas nele.
relate perguntas
-
SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado
-
Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?
-
Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?
-
Quais são as principais causas de deadlocks e podem ser evitadas?
-
Como determinar se um Índice é necessário ou necessário
Os agrupamentos no SQL Server determinam as regras para correspondência e classificação de dados de caracteres. Normalmente, você escolheria um agrupamento primeiro com base na semântica de comparação e na ordem de classificação exigida pelos consumidores dos dados.
Os humanos geralmente não descobrem que os agrupamentos binários produzem os comportamentos de classificação e comparação que esperam. Portanto, embora elas ofereçam o melhor desempenho (especialmente as versões BIN2 de ponto de código puro), a maioria das implementações não as utiliza.
Em seguida, em termos de desempenho bruto (mas apenas para strings não Unicode) estão os agrupamentos SQL de compatibilidade com versões anteriores . Ao trabalhar com dados Unicode, esses agrupamentos usam um agrupamento do Windows , com as mesmas características de desempenho. Existem armadilhas sutis aqui, então você precisa ter boas razões para escolher um agrupamento SQL hoje em dia (a menos que esteja trabalhando em um sistema americano, onde ainda é o padrão).
Os agrupamentos do Windows são os mais lentos, em geral, devido às complexas regras de comparação e classificação Unicode. No entanto, eles oferecem total compatibilidade com o Windows no SQL Server e são mantidos regularmente para acompanhar as mudanças no padrão Unicode. Para uso moderno que inclui dados Unicode, geralmente é recomendado um agrupamento do Windows.
TL;DR
Se tudo o que você deseja é comparação com distinção entre maiúsculas e minúsculas e semântica de classificação, você deve escolher a
_CS_
variação (para Diferenciar maiúsculas e minúsculas) de qualquer ordenação de base que forneça o comportamento esperado para o idioma e a cultura de seus usuários. Por exemplo, ambos são agrupamentos que diferenciam maiúsculas de minúsculas:Você pode ver essas definições usando sys.fn_helpcollations
Exemplos
Quatro tabelas que são exatamente iguais, exceto pelo agrupamento; um binário, um que diferencia maiúsculas de minúsculas, um que não diferencia maiúsculas de minúsculas e um SQL que diferencia maiúsculas de minúsculas:
Mesmos dados de amostra para cada tabela:
Agora queremos encontrar strings maiores que 'a':
Resultados:
Finalmente...
Observe que, se usarmos um literal Unicode com o agrupamento SQL, as regras de conversão implícitas resultarão em uma comparação de agrupamento do Windows:
... e os resultados do agrupamento SQL mudam :
Dado que este é um banco de dados existente que já possui tabelas definidas nele, existem algumas implicações muito sérias para a ação de alterar o agrupamento do banco de dados, além do impacto potencial no desempenho das operações DML (que na verdade já estava lá). Há um impacto muito real no desempenho e na funcionalidade, e essa mudança não apenas não atingiu o objetivo pretendido (pelo menos não de forma consistente), mas provavelmente alterou o comportamento (ou alterará o comportamento quando novas tabelas são criadas) em termos de como os dados são ordenados e equacionados.
Paul já forneceu boas explicações e exemplos das diferenças de desempenho e comportamento entre os diferentes tipos de agrupamentos em sua resposta, então não vou repetir isso aqui. No entanto, alguns pontos precisam de alguns detalhes adicionais, e há vários outros pontos a serem adicionados em relação ao cenário atual de alteração do agrupamento de um banco de dados existente, em vez de definir o agrupamento de um novo banco de dados.
Os agrupamentos binários são mais do que apenas diferenciam maiúsculas de minúsculas: eles são sensíveis a tudo ! Portanto, usando um agrupamento binário (terminando em
_BIN
ou_BIN2
), suas comparações agora também são sensíveis ao acento, sensíveis ao kana, sensíveis à largura e potencialmente sensíveis ao glúten (pelo menos essa parece ser a tendência nos dias de hoje ;-) ). Este foi o efeito desejado de fazer essa mudança? Os usuários finais estão esperando essa mudança de comportamento?Os agrupamentos afetam não apenas as comparações, mas também a classificação. Uma ordenação binária será classificada com base no valor do byte
ASCII
ouUNICODE
(dependendo deVARCHAR
ouNVARCHAR
, respectivamente) de cada byte . Portanto, ao escolher um agrupamento binário, você está desistindo de regras de ponderação específicas de idioma/cultura que ordenam cada caractere (mesmo caracteres em algum idioma, como o húngaro, que são compostos por 2 letras) de acordo com o alfabeto dessa cultura. Então, se "ch" deve vir naturalmente depois de "k", bem, isso não vai acontecer usando um agrupamento binário. Novamente, este foi o efeito desejado de fazer essa mudança? Os usuários finais estão esperando essa mudança de comportamento?A menos que você tenha requisitos específicos de compatibilidade com versões anteriores para seu aplicativo, você deve usar o
BIN2
em vez deBIN
agrupamentos, assumindo, é claro, que você deseja um agrupamento binário em primeiro lugar. OsBIN2
agrupamentos foram introduzidos no SQL Server 2005 e de acordo com a página do MSDN para Diretrizes para uso de agrupamentos BIN e BIN2 :Também deve ser observado que os
_BIN2
agrupamentos correspondem convenientemente ao comportamento daOrdinal
opção da StringComparison Enumeration , de modo que as comparações e ordenações feitas no código .NET usando essa opção produzirão os mesmos resultados que as mesmas operações executadas no SQL Server (ao usar as_BIN2
colações, é claro).Por razões semelhantes ao que acaba de ser declarado sobre os
_BIN2
agrupamentos, a menos que você tenha requisitos específicos para manter o comportamento de compatibilidade com versões anteriores, você deve usar os agrupamentos do Windows e não os agrupamentos específicos do SQL Server (ou seja, os que começam comSQL_
agora são considerados meio "sujo" ;-) ).Ao usar dados Unicode (ou seja, string prefixada com
N
ou entrando no SQL Server do código do aplicativo em que o tipo de dados foi especificado comoNChar
ouNVarChar
), não vejo como usar um agrupamento versus outro faria diferença para inserir ou atualizar um campoNCHAR
ouNVARCHAR
string .Ao usar dados não Unicode ou inserir ou atualizar um campo não Unicode, o agrupamento específico (banco de dados ou campo) pode desempenhar um papel pequeno se algum caractere inserido/atualizado precisar ser traduzido ou não for mapeável (é que mesmo uma palavra?), conforme especificado pela página de código que é definida pelo agrupamento. Obviamente, esse problema potencial existe sempre que alguém está usando dados ou tipos de dados não Unicode e não é específico para esse cenário de alteração do agrupamento de banco de dados. Essa alteração afetará os literais de string (o que já pode ter sido um problema se o agrupamento do banco de dados fosse diferente do agrupamento do campo). Mas mesmo que nenhuma alteração seja feita no agrupamento de banco de dados, os dados provenientes de outros bancos de dados ou de fora do SQL Server (qualquer código de cliente) podem conter quaisquer caracteres e ser de qualquer codificação específica.
MUITO IMPORTANTE!!! Ao alterar o agrupamento padrão do banco de dados, o agrupamento especificado para quaisquer campos de string existentes em qualquer tabela existente não será alterado, mas quaisquer novos campos terão um agrupamento do padrão do banco de dados (a menos que substituído por meio da
COLLATE
cláusula). Isso afetará suas consultas de três maneiras:1) Se qualquer consulta JOIN em qualquer um desses campos existentes para qualquer um dos novos campos, você receberá um erro de incompatibilidade de agrupamento:
Devoluções:
2) Predicados/filtros em campos existentes de tabelas existentes (definidos para o agrupamento padrão anterior) que se comparam a literais ou variáveis de string não apresentarão erros, mas certamente podem ser afetados em termos de desempenho devido ao SQL Server precisar igualar o agrupamento de ambos os lados e convertendo automaticamente a string literal ou variável para o agrupamento do campo. Habilite "Incluir Plano de Execução Real" (Control-M) e execute o seguinte (supondo que você já tenha executado as consultas mostradas acima):
3) E, falando de conversões implícitas, observe como é a string literal (com uma ordenação implícita da ordenação padrão do banco de dados:
Latin1_General_BIN2
) que é convertida, não o campo na tabela. Algum palpite sobre se esse filtro não diferencia maiúsculas de minúsculas (o agrupamento antigo) ou diferencia maiúsculas de minúsculas (o novo agrupamento)? Execute o seguinte para ver:Devoluções:
D'oh! Não apenas há um pequeno (ou talvez mais significativo?) impacto no desempenho para essa consulta devido ao
CONVERT_IMPLICIT()
, mas ela nem se comporta da maneira desejada com distinção entre maiúsculas e minúsculas.Portanto, se o agrupamento for alterado em um banco de dados que já possui tabelas, sim, tanto o desempenho quanto a funcionalidade serão afetados.
Se a ordenação está sendo definida em um novo banco de dados, Paul já cobriu isso explicando como uma ordenação binária, embora rápida, provavelmente não será classificada da maneira que se esperaria ou desejaria.
Também deve ser observado que você sempre pode especificar agrupamentos por condição. A cláusula COLLATE
WHERE
pode ser adicionada a condições,ORDER BY
e a quase todos os locais que aceitam uma string.Exemplo 1 (condição WHERE):
Devoluções:
Exemplo 2 (ORDEM POR):
Devoluções:
Exemplo 3 (instrução SE):
Devoluções:
Exemplo 4 (associado ao parâmetro de entrada da função):
Devoluções:
The UCS-2 value of 55,356 is partially correct in that it is the first of the two values in the "surrogate pair". But unless explicitly given the
_SC
collation, theUNICODE()
function can only see each character as a double-byte value and doesn't know how to properly handle a double double-byte surrogate pair.UPDATE
Even with all of the examples above, one aspect of Case Sensitive comparisons that is usually overlooked, and is negated by binary comparisons / collations, is normalization (composition and decomposition) that is part of Unicode.
Example 5 (when a binary comparison is not case-sensitive):
True case-sensitive comparisons allow for combining characters that, in combination with another character, form yet another character that already exists as another Unicode code point. Case-sensitive comparisons care about the displayable character, not the code point(s) used to create it.
Returns:
True case-sensitive comparisons also allow for wide characters to equate to their non-wide equivalents.
Returns:
Ergo:
BINARY (
_BIN
and_BIN2
) collations are not Case-Sensitive!