Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
nmg196
Yak Posting Veteran
70 Posts |
Posted - 2006-05-12 : 08:10:34
|
Hi,I have a query which returns companies based on their type. There is a link table which links companies to types and it has a few thousand rows in it.The problem is that the query is too slow to use and I can't see why.I pass in a CSV list of types (optionally). The idea is that IF the list of types is not null, it will return the list of companies that have a type that's in the list. The problem is, the more types you pass in, the slower the query is. It's taking quite a while (10-30 seconds) to execute if you select 3 types which is too slow to be used on the website.I can speed it up a bit by generating the list of EntryIDs of the right type as a temp table FIRST, then querying against the temp table, but it doesn't make a huge difference.I can't see why this query would take so long to execute.Can somebody please point out if there's a faster way of doing this.ALTER PROCEDURE [dbo].[SearchCompaniesFiltered] @Name nvarchar(100) = null, @ProductionTypes nvarchar(20) = nullASBEGINdeclare @ProductionTypesTable TABLE ( ProductionTypeID int)IF @productionTypes is not null BEGIN set nocount on declare @separator char(1) select @separator = ',' declare @separator_position int -- This is used to locate each separator character declare @array_value varchar(100) -- this holds each array value as it is returned set @ProductionTypes = @ProductionTypes + @separator while patindex('%' + @separator + '%' , @ProductionTypes) <> 0 -- Loop through the string searching for separtor characters begin select @separator_position = patindex('%' + @separator + '%' , @ProductionTypes) -- patindex matches the a pattern against a string select @array_value = left(@ProductionTypes, @separator_position - 1) insert into @ProductionTypesTable (ProductionTypeID) values (@array_value) select @ProductionTypes = stuff(@ProductionTypes, 1, @separator_position, '') -- This replaces what we just processed with and empty string end set nocount offENDSELECT tblEntry.EntryID, EntryName , Town, County, PostcodeFROM tblEntryINNER JOIN WHERE (@Name is null OR CONTAINS(tblEntry.*, @Name)) -- nameAND (@ProductionTypes is null OR or tblEntry.EntryID in (select EntryID from @ProductionTypesTable as types inner join tblEntryProductionTypes on types.ProductionTypeID =tblEntryProductionTypes.ProductionTypeID) )ORDER BY PaidEntry DESC, EntrySortNameENDThanks,Nick... |
|
|
rahul8346
Starting Member
21 Posts |
Posted - 2006-05-12 : 08:23:05
|
| Hi, I am a Newbie but i feels if make the list table index clustered it will reduce your execution time... |
 |
|
|
mmarovic
Aged Yak Warrior
518 Posts |
|
|
Kristen
Test
22859 Posts |
|
|
nmg196
Yak Posting Veteran
70 Posts |
Posted - 2006-05-12 : 12:36:30
|
| I don't think the problem is with turning an 8 character string into a table - that bit happens in a couple of milliseconds. I think the problem lies with the way it does the join, but I can't figure out why that makes it so slow. It can't be spending 24 seconds splitting the string. |
 |
|
|
Kristen
Test
22859 Posts |
Posted - 2006-05-12 : 13:11:31
|
Well, I'd still use a SPLIT function, but you may be right.You could stick a few:SELECT @SplitTime1 = GetDate()...SELECT @SplitTime2 = GetDate()...then at the bottom:SELECT [@SplitTime1]=@SplitTime1, [@SplitTime2]=@SplitTime2, ...I always put PKs on tempTables, because I've found that they can be slow without, YMMVdeclare @ProductionTypesTable TABLE( ProductionTypeID int, PRIMARY KEY ( ProductionTypeID )) I have no idea whether "CONTAINS(tblEntry.*, @Name))" is fast or slow - you might like to try a run with that removed and see what the run time is.It might also be worth doing some individual queries to TempTable, and "merging them", rather than having the particular combination of OR and AND in your query - the optimiser is probably missing all sorts of opportunities!Kristen |
 |
|
|
rahul8346
Starting Member
21 Posts |
Posted - 2006-05-13 : 02:25:34
|
| This is a very open ended question and there could be a lot of reasons behind the poor performance of a query. But some general issues that you could see about would be: No indexes, table scans, missing or out of date statistics, blocking, excess recompilations of stored procedures, procedures and triggers without SET NOCOUNT ON, poorly written query with unnecessarily complicated joins, too much normalization, excess usage of cursors and temporary tables.Some of the tools/ways that help you troubleshooting performance problems are: SET SHOWPLAN_ALL ON, SET SHOWPLAN_TEXT ON, SET STATISTICS IO ON, SQL Server Profiler, Windows NT /2000 Performance monitor, Graphical execution plan in Query Analyzer.You can go through the white paper on performance tuning SQL Server from Microsoft web site. You can also check out www.sql-server-performance.com |
 |
|
|
RyanRandall
Master Smack Fu Yak Hacker
1074 Posts |
Posted - 2006-05-15 : 08:01:27
|
| I agree with rahul8346. Here are a couple of links which might help you (start to) learn how to work through the optimisation yourself...http://www.sqlservercentral.com/columnists/jsack/sevenshowplanredflags.asphttp://www.sql-server-performance.com/query_execution_plan_analysis.aspRyan Randallwww.monsoonmalabar.com London-based IT consultancy Solutions are easy. Understanding the problem, now, that's the hard part. |
 |
|
|
|
|
|
|
|