LIKE vs CONTAINS pe SQL Server (Programare, Server Sql, Performanță, Conține, Sql Ca)

user667429 a intrebat.

Care dintre următoarele interogări este mai rapidă (LIKE vs CONTAINS)?

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

sau

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

Comentarii

    23

  • Acceptați un răspuns, vă rog? –  > Por AgentFire.
  • 16

  • Nu a mai intrat de ani de zile omule. –  > Por Chris Owens.
4 răspunsuri
Damien_The_Unbeliever

Al doilea (presupunând că te referi la CONTAINS, , și de fapt a pus-o într-o interogare validă) ar trebui să fie mai rapidă, deoarece poate folosi unele formă de index (în acest caz, un index full text). Desigur, această formă de interogare este disponibilă doar pentru dacă coloana se află într-un index full text. În caz contrar, atunci este disponibilă doar prima formă.

Prima interogare, care utilizează LIKE, nu va putea utiliza un index, deoarece începe cu un wildcard, astfel încât va necesita întotdeauna o scanare completă a tabelului.


Adresa CONTAINS ar trebui să fie:

SELECT * FROM table WHERE CONTAINS(Column, 'test');

Comentarii

  • @edze – vă referiți la aceeași pagină care este deja legată ca fiind prima mea mențiune despre CONTAINS? Ce anume din ea? Forma originală a întrebării avea Column CONTAIN("%test%",Column)>0 ceea ce nu era nici pe departe valabil. Nici acum nu este complet corectă. –  > Por Damien_The_Unbeliever.
  • Acest lucru ne-a ajutat să rezolvăm o interogare pe SharePoint. Aveți o altă insignă Great Answer. –  > Por ouflak.
MI C

După ce am rulat ambele interogări pe o instanță SQL Server 2012, pot confirma că prima interogare a fost cea mai rapidă în cazul meu.

Interogarea cu LIKE a arătat o scanare a indexului grupat.

La CONTAINS a avut, de asemenea, o scanare a indexului clusterizat cu operatori suplimentari pentru potrivirea textului complet și o îmbinare de fuziune.

Comentarii

  • Paginile de frunze ale indexului clusterizat sunt tabelul. A LIKE interogare cu un wildcard principal nu va putea utiliza eficient partea de index. Va trebui să scaneze întregul index. Deși, fără îndoială, ar putea exista unele circumstanțe în care scanarea completă a IC să aibă rezultate mai bune decât o interogare care utilizează indexul textului complet (de exemplu, dacă o proporție foarte mare de rânduri se potrivesc), aceasta va fi în mare parte o excepție, nu o regulă generală pe care „o puteți confirma”. –  > Por Martin Smith.
  • Ei bine, mă uit la un plan de execuție real care a preluat peste 200 000 de înregistrări. Punând ambele interogări într-un lot, ambele au scanat indexul clusterizat, dar, în plus, interogarea „CONTAINS” are un cost suplimentar de FULL TEXT MATCH și un MERGE JOIN. –  > Por MI C.
  • Dacă alege o îmbinare prin fuziune, atunci SQL Server estimează că mai mult de x% din rânduri vor ajunge să corespundă predicatului. (unde X = valoarea punct de basculare). În acest caz, îmi imaginez că ambele ar putea sfârși prin a se potrivi destul de uniform. Costurile afișate în planul de execuție sunt doar estimări (chiar și în planul real). Deși există operatori suplimentari ai planului de execuție în planul FT, acesta are unele avantaje. Îmbinarea fuzionării se poate opri înainte de sfârșitul scanării atunci când nu mai are rezultate FT și, de asemenea, nu trebuie să evalueze LIKE. –  > Por Martin Smith.
  • Am rulat o interogare similară pentru a verifica planul de execuție în sql 2012 și mi-a dat un Index Seek. Poate că în exemplul de aici tabelul era aproape gol. În unele cazuri, sql utilizează o scanare a indexului în tabele foarte mici în loc să utilizeze indexul, deoarece este mai rapid. –  > Por Juan.
Omri Valfer

Eu cred că CONTAINS a durat mai mult și a folosit Merge pentru că ați avut o liniuță („-„) în interogare adventure-works.com.

Traducerea este un cuvânt de întrerupere, astfel încât CONTAINS a căutat în indexul de text complet pentru adventure și apoi a căutat works.com și a îmbinat rezultatele.

John Doe

Încercați, de asemenea, să schimbați de aici:

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

La aceasta:

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

Prima va găsi înregistrări cu valori precum „acesta este un test” și „un caz de test este planul„.

Cea de-a doua va găsi, de asemenea, înregistrări cu valori precum „testez acest lucru” și „aceasta este cea mai mare„.

Comentarii

  • Funcționează introducerea unui asterisc înainte și după termenul de căutare? Citind documentația pentru CONTAINS, se menționează doar utilizarea unor termeni prefix ca „test*”, nu și a unor termeni sufix catest” și nu căutarea de subșiruri complete precum „*test”.‘. Totuși, nu am încercat acest lucru. –  > Por matt forsythe.
  • Dacă citiți documentația pentru CONTAINS (docs.microsoft.com/en-us/sql/t-sql/queries/…), este acceptată doar căutarea pentru prefixe. Am încercat acest lucru în mod experimental de numeroase ori și nu este posibil să găsiți „acesta este cel mai mare” (în SQL Sever) cu Contains(Column, ‘”test„‘) –  > Por cl0rkster.