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 |
keyursoni85
Posting Yak Master
233 Posts |
Posted - 2012-02-02 : 02:37:40
|
Hi, I wrote below query in procedure with multiple filters in it but it is taking too much time when i filter with all criteria specified.My table structure:Partmaster>> Part part reference table holds part id and part referenceid for single part>> Units (which will include part reference id for parts)>> Part reference table will store part reference information.Requirements:>> I want part's unit count by its number of part reference specified in part part reference table.>> I also want last sold price from unit table and also min and max price for that part from unit table.-------------------ALTER PROCEDURE [dbo].[usp_getUnitSalesSummary]@PartCategoryID INT = 0,@Manufacturers VARCHAR(1000) = '',@PartReferences VARCHAR(1000) = '',@PartID INT = 0,@PartReferenceID INT = 0,@PropertyCodeValuesFilters VARCHAR(1000) = '',@Grades VARCHAR(100) = '',@CustomerID INT = 0ASBEGIN -- List of manufacturer passed in string with comma seperated manufactuerer names DECLARE @TblManufacturers AS TABLE(ManufacturerID INT) IF (@Manufacturers <> '') BEGIN INSERT INTO @TblManufacturers (ManufacturerID) SELECT M.ID FROM dbo.fnSplitString(@Manufacturers, ',') tmpM INNER JOIN tbl_Manufacturer M ON LTRIM(RTRIM(M.manufacturer)) = LTRIM(RTRIM(tmpM.Data)) END DECLARE @ObjectTypeID AS INT; SELECT @ObjectTypeID = ObjectTypeID FROM tbl_ObjectTypes WHERE archived = 0 AND ObjectTypeCode = 'Part'; -- List part ids for filter. DECLARE @TblPart AS TABLE(PartId INT) INSERT INTO @TblPart (PartId) SELECT ObjectID FROM dbo.fn_getPropertyValueObjects (@PropertyCodeValuesFilters, @ObjectTypeID) SELECT top 10 pm.ID AS 'PartID', PartNumber, PartDescription, isnull(pm.CreatedUserID , 0) AS 'CreatedUserID', ISNULL(pm.AuthorisedUserID, 0) AS 'AuthorisedUserID', ISNULL(pm.AuthorisedDate, '') AS 'AuthorisedDate', ISNULL(pm.Authorised, 0) AS 'Authorised', m.ID AS 'ManufacturerID', m.man AS 'ManufacturerCode', m.manufacturer AS 'ManufacturerName', pc.PartCategoryID AS 'PartCategoryID', pc.PartCategoryCode AS 'PartCategoryCode', pc.PartCategoryName AS 'PartCategoryName', pc.CertifyDataSafe AS 'CertifyDataSafe', pc.InterfaceID AS 'InterfaceID', '-' AS 'InterfaceCode', '-' AS 'InterfaceName', '-' AS 'interfacedesc', '' OEM1, '' OEM2, '' OEM3, '' OEM4, TotalUnitCount FROM -- get a distinct list of Part IDs that meet our filter criteria ( select pm.ID, COUNT(1) OVER (PARTITION BY pm.id) TotalUnitCount from tbl_PartsMaster AS pm INNER JOIN @TblPart tblPartIds ON tblPartIds.PartId = pm.ID INNER JOIN tbl_PartCategories AS pc ON pc.PartCategoryID = pm.PartCategoryID INNER JOIN tbl_PartPartReferences AS ppr ON pm.ID = ppr.PartID INNER JOIN tbl_PartReferences AS pr ON ppr.PartReferenceID = pr.PartReferenceID INNER JOIN tbl_Manufacturer AS m ON pr.ManufacturerID = m.ID INNER JOIN dbo.fnSplitString(@PartReferences, ',') PRIDs ON (LTRIM(RTRIM(PRIDs.Data)) = pr.Reference OR @PartReferences = '') LEFT JOIN tbl_Units AS u ON u.PartReferenceID = ppr.PartReferenceID LEFT JOIN tbl_ActivityRequest AR ON AR.ActID = u.ACTID --LEFT JOIN @TblManufacturers tblManu ON (tblManu.ManufacturerID = pm.[OEM] OR @Manufacturers = '') INNER JOIN dbo.fnSplitString(@Grades, ',') tbGrades ON (LTRIM(RTRIM(tbGrades.Data)) = u.Grade OR @Grades = '') -- u.Grade IN (SELECT LTRIM(RTRIM(Data)) FROM dbo.fnSplitString(@Grades, ',')) -- pr.Reference IN (SELECT LTRIM(RTRIM(Data)) FROM dbo.fnSplitString(@PartReferences, ',')) where pm.archived = 0 AND pr.archived = 0 AND ppr.archived = 0 AND pc.archived = 0 AND ( pm.ID = @PartID OR @PartID = 0 ) AND ( pm.PartCategoryID = @PartCategoryID OR @PartCategoryID = 0 ) AND ( pr.PartReferenceID = @PartReferenceID OR @PartReferenceID = 0 ) AND ( AR.OID = @CustomerID OR @CustomerID = 0 ) ) AS p INNER JOIN tbl_PartsMaster AS pm ON p.ID = pm.ID INNER JOIN tbl_Manufacturer AS m ON pm.OEM = m.ID INNER JOIN tbl_PartCategories AS pc ON pm.PartCategoryID = pc.PartCategoryID WHERE ISNULL(pm.archived, 0) = 0 group by pm.ID, PartNumber, PartDescription, isnull(pm.CreatedUserID , 0), ISNULL(pm.AuthorisedUserID, 0), ISNULL(pm.AuthorisedDate, ''), ISNULL(pm.Authorised, 0), m.ID, m.man, m.manufacturer, pc.PartCategoryID, pc.PartCategoryCode, pc.PartCategoryName, pc.CertifydataSafe, pc.InterfaceID, TotalUnitCount ORDER BY PartNumber;END/*-- testing-- usp_getUnitSalesSummary @CustomerID = 308, @manufacturers = 'dell', @grades = 'D'-- usp_getUnitSalesSummary @partid = 138013*/GO Please help. |
|
GilaMonster
Master Smack Fu Yak Hacker
4507 Posts |
Posted - 2012-02-02 : 04:32:52
|
http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/--Gail ShawSQL Server MVP |
 |
|
keyursoni85
Posting Yak Master
233 Posts |
Posted - 2012-02-02 : 04:49:31
|
Hi,Thanks but I also tried with dynamic query..And found cause that unit table join takes too much timeIs it due to reason that.. part master .. to part part references and part references to unit table's part reference id join??That join only takes time in query upto 20+ seconds.. If I remove that condition and then it retuns upto 500 rows in 1 second.Can I do anything with that unit table join and its unit count for any part differently? |
 |
|
Kristen
Test
22859 Posts |
Posted - 2012-02-02 : 05:12:32
|
[code]LEFT JOIN tbl_Units AS u ON u.PartReferenceID = ppr.PartReferenceID[/code] That one? Have you got an index on tbl_Units.PartReferenceID ? what about tbl_PartPartReferences.PartReferenceID ?Does SSMS recommend any additional indexes?[code]INNER JOIN dbo.fnSplitString(@PartReferences, ',') PRIDs ON (LTRIM(RTRIM(PRIDs.Data)) = pr.Reference OR @PartReferences = '')[/code]Personally I would put the TRIM functions inside the fnSplitString function, and possibly use an OUTER JOIN??[code]LEFT OUTER JOIN dbo.fnSplitString(@PartReferences, ',') PRIDs ON PRIDs.Data...WHERE...AND (PRIDs.Data IS NOT NULL OR @PartReferences = '')[/code]dunno if that will make any difference though.You're doing the same TRIMming with fnSplitString on tbl_Manufacturer :[code]INNER JOIN tbl_Manufacturer M ON LTRIM(RTRIM(M.manufacturer)) = LTRIM(RTRIM(tmpM.Data))[/code]only that one is even worse because you are also doing "LTRIM(RTRIM((M.manufacturer))" - you need to get all those superfluous spaces out of your stored data so you can just JOIN the columns without functions. SQL won't use an index if you wrap a column with a function.[code]WHERE ISNULL(pm.archived, 0) = 0[/code]changing that to[code](pm.archived = 0 OR pm.archived IS NULL)[/code]might give you better index selection (but that's not going to be highly relevant to the issue at hand). SQL may "unwind" that function anyway.What's the point of your OVER ... PARTITION BY? You aren't checking the ROWNO (it doesn't even have an alias name ...), you could just as easily use DISTINCT or GROUP BY there, or move all the columns required for the SELECT into the OVER ... PARTITION BY section.[code]DECLARE @TblManufacturers AS TABLE(ManufacturerID INT)[/code]Probably worth putting a Primary key on @TblManufacturers[code]GROUP BY isnull(pm.CreatedUserID , 0), ISNULL(pm.AuthorisedUserID, 0), ISNULL(pm.AuthorisedDate, ''), ISNULL(pm.Authorised, 0),[/code]Can any of these columns, such as [CreatedUserID], actually have a ZERO value? If not then skip the ISNULL and the GROUP BY will group them on NULL or their value. If you DO need GROUP BY to treat CreatedUserID =NULL and CreatedUserID = 0 as one-and-the-same then I think you should look at your data and NOT store BOTH Null and Zero in that column - one-or-the-other.If those columns can be a ZERO value what about these?[code] pm.ID = @PartID OR @PartID = 0[/code]if pm.ID can ALSO be a Zero Value then you have no means of just selecting pm.ID = 0 (because it is your wildcard value ...). For this reason we always use NULL as our wildcard @parameter value[code]ISNULL(pm.AuthorisedDate, '')[/code]Is [AuthorisedDate] column NOT a DateTime (or DATE) datatype? If so surely it should be? If not then you can't use a blank-string as the second parameter, its not a valid date "value". |
 |
|
keyursoni85
Posting Yak Master
233 Posts |
Posted - 2012-02-02 : 05:30:44
|
Thank you,I applied some changes in my sp suggested above and also applied outer apply for unit table due to performance issue and query now takes appx 3-4 seconds but ..when I include filter for manufacturers (with join) or with part references (with join) it takes so much time..I also gathered IDs for those comma seperated values seperately at start of sp and then applied join..Because I want to use join in that way if manufacturers not passed then it simple returns results therefor I wrote or condition. |
 |
|
Kristen
Test
22859 Posts |
Posted - 2012-02-02 : 09:27:21
|
So: Answers to these earlier questions pls:"Have you got an index on tbl_Units.PartReferenceID ? what about tbl_PartPartReferences.PartReferenceID ?Does SSMS recommend any additional indexes?" |
 |
|
keyursoni85
Posting Yak Master
233 Posts |
Posted - 2012-02-02 : 10:20:07
|
yes, i created non clustered index on that column unit table. and it is working fine now with small amount of time.But still I think query can be optimized more. |
 |
|
Kristen
Test
22859 Posts |
Posted - 2012-02-02 : 11:54:55
|
I look to see what the logical I/O and Scans are, and try to reduce those (well ... I look at the ones with highest numbers first!)I also look at query plan to see where PKey is being used where I would expect an index to be used, and then try to work out why the index is not being used, or if a better index could be created.Then I look at whether the indexes that ARE being used could (sensibly) be changed to COVER more of the query. |
 |
|
|
|
|
|
|