August 21, 2017 at 9:21 am
I currently have a large query which is taking over an hour to run, and am attempting to optimize. Unfortunately, I do not have permissions to see the execution plan, but believe I have narrowed the issue down to several like statements that are being used (shown below).
Select 1.A, 1.B, 1.C
from Table1 1
left join Table2 2 on 2.id = 1.id
left join Table3 3 on 2.id = 3.id and 3.seq = '1'
Where 2.date between 201501 and 201707
AND (3.Desc Like '%red%'
OR 3.Desc like '%blue%'
OR 3.Desc like '%Teal%'
OR 3.Desc like '%yellow black%'
OR 3.Desc like '%brown%'
OR 1.Class = 'english')
Is it possible to move the like statements to a join to make it more efficient?
I attempted to use a temporary table as shown below but it did not work. I am thinking it was because I added the 1.Class to the inner join. I am looking to return items from Table 1 that have a Class equal to English or a Desc from Table 3 like red, blue, Teal, yellow black, or brown.
CREATE TABLE #HH (Desc VARCHAR(60),
);
insert into #HH
select Desc.Desc
from Table3 Desc
Where Desc.Desc Like '%red%'
OR Desc.Desc like '%blue%'
OR Desc.Desc like '%Teal%'
OR Desc.Desc like '%yellow black%'
OR Desc.Desc like '%brown%'
group by Desc.Desc
Select 1.A, 1.B, 1.C
from Table1 1
left join Table2 2 on 2.id = 1.id
left join Table3 3 on 2.id = 3.id and 3.seq = '1'
--------Added----
inner join on #HH HH on 3.Desc = HH.Desc or 1.Class = 'english'
Where 2.date between 201501 and 201707
]
August 21, 2017 at 9:34 am
It's likely to be a table scan caused by the non-sargable LIKE operators that are causing you pain, by forcing a scan of the whole table. I imagine that if you don't even have access to see the execution plan, creating a persisted column or an indexed view is out of the question?
John
August 21, 2017 at 9:40 am
I am not sure as I have never worked with persisted column or indexed views before. Guess I would need to determine how to use each and attempt to see if it makes an improvement.
August 21, 2017 at 9:53 am
I meant do you even have permission to create one? If you do, you'd do it something like this:
ALTER TABLE Table3
ADD DescColour AS (
CASE
WHEN Desc LIKE '%blue%' THEN 'blue'
WHEN Desc LIKE '%Teal%' THEN 'Teal'
WHEN Desc LIKE '%yellow black%' THEN 'yellow black'
WHEN Desc LIKE '%brown%' THEN 'brown'
ELSE ''
END
)
You can then index the column and use it in your view. You'd have to test to see whether it actually gets used by the query optimizer - with such a low number of values, it's not very selective.
The other alternative is to write your query as an indexed view, so that the whole thing is persisted in the database and doesn't have to be calculated on the fly. Of course, if you only run the query once a week, for example, it's probably not worth the overheads associated with maintaining it.
John
August 21, 2017 at 10:04 am
It does appear I do not have permissions to create a view. So your saying the only other option is to write the query as an indexed view?
August 21, 2017 at 1:16 pm
LIKEs are tough on the optimizer, as are all those ORs.
Best,
Kevin G. Boles
SQL Server Consultant
SQL MVP 2007-2012
TheSQLGuru on googles mail service
August 21, 2017 at 2:13 pm
That is why I was hoping that I could put the values from the LIKEs in a temp table, and then incorporate it into the join as the values versus using the LIKEs. I am open to any thoughts.
August 21, 2017 at 2:23 pm
Since using actual words, what about Full Text Search?
Best,
Kevin G. Boles
SQL Server Consultant
SQL MVP 2007-2012
TheSQLGuru on googles mail service
August 21, 2017 at 9:03 pm
ollyjolly - Monday, August 21, 2017 9:21 AMI currently have a large query which is taking over an hour to run, and am attempting to optimize. Unfortunately, I do not have permissions to see the execution plan, but believe I have narrowed the issue down to several like statements that are being used (shown below)...
Is it possible to move the like statements to a join to make it more efficient?
Yes. I answered this earlier today . Here's a similar but more simple but less dynamic way to tackle this:
First some sample data:CREATE TABLE dbo.sometable
(
someId int identity primary key clustered,
col1 varchar(100) not null
);
INSERT dbo.sometable(col1)
VALUES ('xxx blue'),('ggg red gg'),('xxx'),('fff pink h'),('I''m yellow!!!');
Next for our indexed view:CREATE VIEW dbo.vwSomeTable
WITH SCHEMABINDING AS
SELECT someId, col1
FROM dbo.sometable
WHERE col1 LIKE '%blue%'
OR col1 LIKE '%pink%';
GO
CREATE UNIQUE CLUSTERED INDEX uq_cl_vwSomeTable ON dbo.vwSomeTable(someId);
Now, if you run the query below (just as an example) you'll notice that the optimizer is able to perform an index seek against the index on my view even without me referencing it in my query.
SELECT someId, col1
FROM dbo.sometable
WHERE
(
col1 LIKE '%blue%' OR
col1 LIKE '%pink%'
)
AND someId < 4;
The execution plan:
This is one of those very cool but rarely mentioned benefits of indexed views.
You could one or more add nonclustered indexes to your view to speed things up even further. As is the case with all Indexes, however, Indexed views do not come without the usual overhead so you'll have to test for yourself to see if the improved performance is worth the added overhead. There's also no guarantee that the optimizer will always chose your indexed view which is why you can consider referencing it directly along with a NOEXPAND query hint. I generally don't recommend query hints but will say that I've had great success with NOEXPAND (after plenty of testing 😉) On the topic of NOEXPAND - note this great article by Paul White: Another Reason to Use NOEXPAND hints in Enterprise Edition
-- Itzik Ben-Gan 2001
August 22, 2017 at 2:04 am
ollyjolly - Monday, August 21, 2017 10:04 AMIt does appear I do not have permissions to create a view. So your saying the only other option is to write the query as an indexed view?
No, an indexed view is a view. If you don't have DDL permissions on your database, you won't be able to create the index view or add the persisted column. If you can prove that it works, perhaps you could persuade the owner of the database that it's worth doing?
John
August 23, 2017 at 1:12 pm
John Mitchell-245523 - Tuesday, August 22, 2017 2:04 AMollyjolly - Monday, August 21, 2017 10:04 AMIt does appear I do not have permissions to create a view. So your saying the only other option is to write the query as an indexed view?
No, an indexed view is a view. If you don't have DDL permissions on your database, you won't be able to create the index view or add the persisted column. If you can prove that it works, perhaps you could persuade the owner of the database that it's worth doing?
John
I missed this and agree that there's a case to get permission to create a view as that would be the best solution imho. That said, a computed column could work too.
CREATE TABLE dbo.sometable
(
someId int identity primary key clustered,
col1 varchar(100) not null
);
INSERT dbo.sometable(col1)
VALUES ('xxx blue'),('ggg red gg'),('xxx'),('fff pink h'),('I''m yellow black!!!');
ALTER TABLE dbo.sometable
ADD hasThatColor AS
(
cast(sign(
charindex('red', col1)+
charindex('blue', col1)+
charindex('teal', col1)+
charindex('yellow black', col1)+
charindex('brown', col1)) as bit)
) persisted;
CREATE NONCLUSTERED INDEX nc_sometable_hasThatColor on dbo.sometable(hasThatColor)
INCLUDE (someId, col1);
Using my sample data above, the following query will get you a nonclustered covering index seek which is what I like to see.
SELECT *
FROM dbo.sometable
WHERE hasThatColor = 1
-- Itzik Ben-Gan 2001
Viewing 11 posts - 1 through 10 (of 10 total)
You must be logged in to reply to this topic. Login to reply