views:

594

answers:

5

I have a table with 117000 or so records. I need to perform a search that checks 3 separate fields for a given string pattern.

My where clause is as follows:

field1 LIKE '%' + @DESC + '%'
OR field2 LIKE '%' + @DESC + '%'
OR field3 LIKE '%' + @DESC + '%'

This seems to take about 24 seconds regardless of input...

Is there a better way to do this? Less than 10 (or 5!) seconds would be much more preferable.

Thanks for any help.

+6  A: 

Use Full Text Search and CONTAINS. LIKE cannot be optimized when searching in the middle of the field, ie. when the LIKE expression starts with an '%', so it will always do a full table scan.

Remus Rusanu
you can use an index, with a little work, when doing LIKE '%'+string, see the link in my other comment.
KM
@KM: Interesting trick, a reversed column. Also good analogy with the phone book, makes the case vividly clear.
Remus Rusanu
nice trick , to obad there isn't anything similar for the like '%text%' problem.
HLGEM
@KM: It definitely has to be a '%test%' form, so the reverse method is out, though I have seen that before and it's a clever trick. I will have to try the Full Text Search, but it looks like I'm going to have to convince the DBAs to index it properly. Thank you for the suggestion. I will see if Full Text/Contains boosts performance. I recall doing this on the old database with the exact same query and it was much faster...not sure what the new one is doing differently
IronicMuffin
After getting the DBA's to Full Text Index the tables, this brought me down to 1-3 seconds for a search. Thanks for the help!
IronicMuffin
+1  A: 

Anytime you start a LIKE search with a wildcard, you're doing a scan. Unless you can narrow your search criteria to include the first character (which may not be feasible), you'll need to resort to Full Text Search.

Stuart Ainsworth
@Stuart Ainsworth said _Anytime you start a LIKE search with a wildcard, you're doing a scan_, that soes not have to be true, see this: http://stackoverflow.com/questions/1388059/sql-server-index-columns-used-in-like/1395881#1395881
KM
Now you're just playing with semantics; you REVERSE the column and index it, and then reverse the like clause so it doesn't start with a wildcard. You're not starting a search with a wildcard, so therefore you're not doing a scan.I will admit that is an interesting solution, and I'll have to keep it in mind.
Stuart Ainsworth
A: 

how about

field1 + field2 + field3 LIKE '%' + @DESC + '%'

or

CONTAINS(field1 + field2 + field3, @DESC)
THEn
+1  A: 

Do you really need to start with a wildcard? Why? Often you can force users to type in the first character at least. I bring this up becasue some developers just use the wildcard as a habit not becasue there is a requirement. In most cases users will be able to type the first character unless the filed stores long strings (like say official airport names). Otherwise you really need to use full-text indexing although KM's trick with the reverse is pretty cool if you don't need the wildcard at the end.

If you can avoid doing the performance killing things, then do so.

HLGEM
Yes, I do need a double sided wildcard for this query. I need to find something like 'banana' in 'Strawberry Banana Yogurt.'
IronicMuffin
A: 

Whilst I agree with the accepted answer that Full Text Indexing would be the best solution and am by no means advocating the use of leading wildcard searches if they have to be performed then there are potential steps that can be taken to make the performance of them less bad.

Kalen Delaney in the book "Microsoft SQL Server 2008 Internals" says:

Collation can make a huge difference when SQL Server has to look at almost all characters in the strings. For instance, look at the following:

SELECT COUNT(*) FROM tbl WHERE longcol LIKE '%abc%'

This may execute 10 times faster or more with a binary collation than a nonbinary Windows collation. And with varchar data, this executes up to seven or eight times faster with a SQL collation than with a Windows collation.

Martin Smith