=, BINARY, LIKE, LIKE BINARY, REGEXP, agrupamento binário SQL – mysql sql desempenho
Pergunta:
Reformulação da pergunta a partir da resposta do @GabrielHenrique e pesquisa:
O que é agrupamento binário em uma coluna string na tabela?
BINARY serve para fazer uma busca case-sensitive e LIKE case-insensitive, então LIKE BINARY seria uma comparação case-sensitive com o uso do % e _ para completar o texto com qualquer valor?
Tem diferença e o que é mais performático, BINARY ou apenas =? Essa diferença é significativa em tabelas grandes? E em tabelas pequenas?
Qual é mais performático, REGEXP ou LIKE? Essa diferença é significativa em tabelas grandes? E em tabelas pequenas?
Qual é mais performático, REGEXP ou LIKE BINARY? Essa diferença é significativa em tabelas grandes? E em tabelas pequenas?
Autor da pergunta Guilherme Costamilam
Ricardo Pontual
Segundo a documentação do MySQL (string comparation), as comparações de strings não são case-sensitive, a menos que um dos operadores
seja case-sensitive, ou o collation do campo seja.
Portanto, usar = ou LIKE também pode ser uma busca case-sensitive dependendo do collation, assim por exemplo:
LIKE _latin1 'ABC%' COLLATE latin1_bin
Usando LIKE BINARY força uma comparação binária independente do collation, garantindo a comparação case-sensitive, embora possa prejudicar a performance dependendo do tamanho da tabela.
Sobre o uso de REGEX vs LIKE, algumas considerações devem ser feitas:REGEX não utiliza um índice, mesmo que presente, o que irá impactar na performance;LIKE usa um índice, se houver, desde que não inicie a comparação por % ou '_';
Aqui tem uma excelente resposta no SO inglês sobre isso: https://stackoverflow.com/a/8431675/4730201
EDIT: por sugestão estou copiando uma parte interessante da resposta do link acima:
SELECT * FROM t WHERE a = 'abc' <<-- (case insensitive ) pode usar o índice se existir
SELECT * FROM t WHERE a LIKE 'abc' <<-- (case insensitive como "=") pode usar o índice se existir
SELECT * FROM t WHERE a LIKE 'abc%' <<-- pode usar o índice se existir
SELECT * FROM t WHERE a LIKE 'a%' <<-- pode usar o índice se existir, dependendo da cardinalidade (1)
SELECT * FROM t WHERE a LIKE '%a%' <<-- não vai usar um índice
SELECT * FROM t WHERE a LIKE '_agf' <<-- não vai usar um índice
(1) Segundo o autor da resposta, dependendo da cardinalidade o MySQL pode ou não usar um índice:
Se mais de +/- 20% das linhas corresponderem ao critério, o MySQL não usará um índice, porque, nesse caso, fazer uma busca completa “full table scan” da tabela é mais rápido
Portanto, do ponto de vista de performance, é interessante considerar a presença de um índice na coluna, o collation e a pesquisa que será feita (iniciado ou não por % ou _) para escolher a melhor forma de comparação.
Dependendo também da comparação frequente no campo, iniciando por % e do volume de dados, uma outra opção a ser considerada é o uso de um índice fulltext, que é próprio pra otimizar esse tipo de pesquisa. Mais informação (em inglês) aqui: MySQL Fulltext Index
EDIT: esclarecendo uma dúvida sobre o COLLATION:
No exemplo acima, da documentação do MySQL, ele está especificando o collation que deseja usar na comparação, independente do collation original.
Como exemplo, uma tabela com um campo que foi criado assim texto VARCHAR(50) CHARACTER SET latin1 COLLATE latin1_german1_ci, ou seja a coluna nome está com o collation em alemão, mas você deseja comparar usando espanhol, você poderia fazer assim: WHERE texto LIKE _latin1 'ABC%' COLLATE latin1_spanish_ci
Coloquei um exemplo aqui: sqlfiddle
No MySQL, BINARY tem a função de forçar uma comparação exata, ou seja, uma comparação case-sensitive, byte a byte.
Creio que a utilização deste agrupamento seja para otimização da busca quando se busca um valor em especifíco.



