LIKE vs CONTAINS no SQL Server

210

Qual das seguintes consultas é mais rápida (LIKE x CONTAINS)?

SELECT * FROM table WHERE Column LIKE '%test%';

ou

SELECT * FROM table WHERE Contains(Column, "test");
user667429
fonte
12
Aceite uma resposta, aceitaria?
AgentFire 23/09
7
Ele não aparece há anos, cara.
Chris

Respostas:

174

O segundo (supondo que você queira dizer CONTAINSe, na verdade, coloque-o em uma consulta válida) deve ser mais rápido, pois pode usar alguma forma de índice (nesse caso, um índice de texto completo). Obviamente, essa forma de consulta estará disponível apenas se a coluna estiver em um índice de texto completo. Caso contrário, apenas o primeiro formulário estará disponível.

A primeira consulta, usando LIKE, não poderá usar um índice, pois começa com um curinga, portanto sempre exigirá uma verificação completa da tabela.


A CONTAINSconsulta deve ser:

SELECT * FROM table WHERE CONTAINS(Column, 'test');
Damien_The_Unbeliever
fonte
@ edze - você quer dizer, a mesma página que já está vinculada para ser minha primeira menção CONTAINS? E daí? A forma original da pergunta Column CONTAIN("%test%",Column)>0não era nem de longe válida. Ainda não está completamente certo.
Damien_The_Unbeliever
Isso nos ajudou a resolver uma consulta no SharePoint. Tenha outro crachá de ótima resposta.
precisa saber é o seguinte
14

Depois de executar as duas consultas em uma instância do SQL Server 2012, posso confirmar que a primeira consulta foi mais rápida no meu caso.

A consulta com a LIKEpalavra - chave mostrou uma verificação de índice em cluster.

O CONTAINStambém tinha uma verificação de índice em cluster com operadores adicionais para o jogo de texto completo e uma junção por mesclagem.

Plano

MICROFONE
fonte
8
As páginas folha de índice agrupadas são a tabela. Uma LIKEconsulta com um curinga principal não poderá usar a parte do índice com eficiência. Será necessário apenas verificar a coisa toda. Embora, sem dúvida, possa haver algumas circunstâncias em que a verificação completa do IC tenha um desempenho melhor do que uma consulta usando o índice de texto completo (talvez se uma proporção muito alta de linhas corresponder, por exemplo), isso será uma exceção em grande parte, e não uma regra geral que você "possa confirmar "
Martin Smith
Bem, estou olhando para um plano de execução real que busca mais de 200.000 registros. Ao colocar as duas consultas em um lote, as duas varreram o índice em cluster, mas além disso, a consulta "CONTAINS" tem um custo adicional de FULL TEXT MATCH e MERGE JOIN.
MI C
Se escolher uma junção de mesclagem, o SQL Server estimar que mais de x% das linhas acabarão correspondendo ao predicado. (Onde X = o ponto de inflexão ). Nesse caso, eu imagino que ambos possam terminar de maneira uniforme. Os custos mostrados no plano de execução são apenas estimativas (mesmo no plano real). Embora existam operadores de plano de execução adicionais no plano FT, ele possui alguns benefícios. A junção de mesclagem pode parar antes do final da verificação quando ficar sem os resultados do FT e também não é necessário avaliar o LIKE.
Martin Smith
1
Eu executei uma consulta semelhante para verificar o plano de execução no sql 2012 e isso me deu uma busca por índice. Talvez no exemplo aqui a mesa estivesse quase vazia. Em alguns casos, o sql usa uma varredura de índice em uma tabela muito pequena para usá-lo porque é mais rápido.
Juan Juan
8

Eu acho que CONTAINSdemorou mais e usado Mergeporque você teve um traço ("-") na sua consultaadventure-works.com .

O traço é uma palavra de interrupção para que o CONTAINSíndice de texto completo adventureseja pesquisado works.come, em seguida, pesquisado e mesclado os resultados.

Omri Valfer
fonte
8

Tente também mudar disso:

    SELECT * FROM table WHERE Contains(Column, "test") > 0;

Para isso:

    SELECT * FROM table WHERE Contains(Column, '"*test*"') > 0;

O primeiro encontrará registros com valores como " este é um teste " e " um caso de teste é o plano ".

O último também encontrará registros com valores como " estou testando isso " e " este é o melhor ".

John Doe
fonte
4
Colocar o asterisco antes e depois do termo de pesquisa funciona? Ao ler a documentação CONTAINS, ele menciona apenas o uso de termos de prefixo como 'test *', não termos de sufixo como ' test' e não busca de substring completo como '* test '. Eu ainda não tentei.
precisa saber é o seguinte
5
Se você ler a documentação de CONTAINS ( docs.microsoft.com/en-us/sql/t-sql/queries/… ), apenas a pesquisa de prefixos é suportada. Eu tentei isso experimentalmente inúmeras vezes e não é possível encontrar "este é o maior" (no SQL Sever) com Contém (Coluna ' ' test '')
cl0rkster