I have a stored procedure that used to run fine without any issues before we made this change last evening and now the performance is unacceptable.
The stored proc pulls data based on information in the contact_lookup table. I highlighted the areas of the code that we changed using **. Basically, when I added WHERE attempt = @attempt and contact_type = @contacttype (as opposed to just hardcoding the value of 1) the performance became unacceptable.
Can someone explain why the behavior changed and how to improve performance using the parameters passed through the stored proc.Also, can we get rid of the union and simplify the code a bit.
USE [Test]
GO
/****** Object: StoredProcedure [dbo].[sp_ODBGetContactForSingleLocation] Script Date: 04/21/2017 09:48:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[sp_ODBGetContactForSingleLocation]
@reportentityid [int]
, @attemptnumber [int]
, @contacttype [int]
, @clientid [int]
, @resultcode [int] OUT
AS
BEGIN
DECLARE @activerowcount [int] -- This is what we will use to store the number of contacts return after each query.
SELECT
cc.first_name
, cc.last_name
, ISNULL(cc.title, '') AS [title]
, cct.contact_type_description AS [contact_type]
, UPPER(re.friendly_name) AS [location]
, cl.attempt AS [attempt]
, re.report_entity_id AS [report_entity_id]
, (SELECT ct.description
FROM Test.dbo.communication_type ct
WHERE ct.communication_type_id = cc.preferred_method) AS [preferred_method]
, am.Email AS [email]
, cc.phone AS [phone]
, cc.cell_phone AS [cell_phone]
, cc.fax AS [fax]
, cc.department AS [department]
, cc.address1 AS [address1]
, cc.address2 AS [address2]
, cc.city AS [city]
, cc.state AS [state]
, cc.zip AS [zip]
, cc.contact_id AS [contact_id]
FROM Test.dbo.client_contacts cc
INNER JOIN Test.dbo.contact_lookup cl
ON cc.contact_id = cl.contact_id
INNER JOIN Test.dbo.contact_type_filter ctf
ON ctf.contact_lookup_id = cl.contact_lookup_id
INNER JOIN Test.dbo.contact_responsibility_filter crf
ON crf.contact_lookup_id = cl.contact_lookup_id
INNER JOIN Test.dbo.client_contact_type cct
ON cct.contact_type_id = ctf.contact_type_id
INNER JOIN C3Test.C3.report_entity re
ON re.report_entity_id = crf.report_entity_id
INNER JOIN C3SecondaryTest.dbo.aspnet_Membership am
ON am.UserId = cc.master_user_id
WHERE
**--cl.attempt = @attemptnumber
cl.attempt = 1**
AND cl.active = 1
**AND cct.contact_type_id = 1
--AND cct.contact_type_id = @contacttype**
AND cc.active = 1
AND (re.report_entity_id IN (SELECT report_entity_id FROM C3Test.C3.fn_getParentIDsForEntity(@reportentityid)) OR
re.report_entity_id IN (SELECT report_entity_id FROM C3Test.C3.fn_getReportEntityIDsForParent(@reportentityid)))
UNION
SELECT
cc.first_name
, cc.last_name
, ISNULL(cc.title, '') AS [title]
, cct.contact_type_description AS [contact_type]
, UPPER(re.friendly_name) AS [location]
, cl.attempt AS [attempt]
, re.report_entity_id AS [report_entity_id]
, (SELECT ct.description
FROM Test.dbo.communication_type ct
WHERE ct.communication_type_id = cc.preferred_method) AS [preferred_method]
, am.Email AS [email]
, cc.phone AS [phone]
, cc.cell_phone AS [cell_phone]
, cc.fax AS [fax]
, cc.department AS [department]
, cc.address1 AS [address1]
, cc.address2 AS [address2]
, cc.city AS [city]
, cc.state AS [state]
, cc.zip AS [zip]
, cc.contact_id AS [contact_id] FROM Test.dbo.client_contacts cc
INNER JOIN Test.dbo.contact_lookup cl
ON cc.contact_id = cl.contact_id
INNER JOIN Test.dbo.contact_type_filter ctf
ON ctf.contact_lookup_id = cl.contact_lookup_id
INNER JOIN Test.dbo.client_contact_type cct
ON cct.contact_type_id = ctf.contact_type_id
INNER JOIN C3SecondaryTest.dbo.aspnet_Membership am
ON am.UserId = cc.master_user_id
LEFT OUTER JOIN Test.dbo.contact_responsibility_filter crf
ON crf.contact_lookup_id = cl.contact_lookup_id
LEFT OUTER JOIN C3Test.C3.report_entity re
ON re.report_entity_id = crf.report_entity_id
WHERE
**--cl.attempt = @attemptnumber
cl.attempt = 1**
AND cl.active = 1
**AND cct.contact_type_id = 1
--AND cct.contact_type_id = @contacttype**
AND crf.contact_lookup_id IS NULL
AND cc.client_id = @clientid
AND cc.active = 1
SET @activerowcount = @@ROWCOUNT
-- Now check if the rowcount is > 0. If not you have no contact
-- so check for the primary_contact in the client_details table
IF @activerowcount > 0
BEGIN
SET @resultcode = 100
RETURN 1
END
ELSE
BEGIN
SELECT
cc1.first_name
, cc1.last_name
, ISNULL(cc1.title, '') AS [title]
, 'PRIMARY' AS [contact_type]
, 'DEFAULT' AS [location]
, 0 AS [attempt]
, NULL AS [report_entity_id]
, (SELECT ct.description
FROM Test.dbo.communication_type ct
WHERE ct.communication_type_id = cc1.preferred_method) AS [preferred_method]
, CASE ISNULL(am.Email, '')
WHEN '' THEN cc1.email2
ELSE am.Email
END AS [email]
, cc1.phone AS [phone]
, cc1.cell_phone AS [cell_phone]
, cc1.fax AS [fax]
, cc1.department AS [department]
, cc1.address1 AS [address1]
, cc1.address2 AS [address2]
, cc1.city AS [city]
, cc1.state AS [state]
, cc1.zip AS [zip]
, cc1.contact_id AS [contact_id]
FROM Test.dbo.client_contacts cc1
LEFT OUTER JOIN C3SecondaryTest.dbo.aspnet_Membership am
ON cc1.master_user_id = am.UserId
INNER JOIN Test.dbo.client_details cd
ON cd.client_id = cc1.client_id
WHERE cd.client_id = @clientid
AND cc1.contact_id = cd.primary_contact
AND cc1.active = 1
SET @activerowcount = @@ROWCOUNT
IF @activerowcount > 0
BEGIN
SET @resultcode = 100
RETURN 1
END
ELSE
-- Now check if we have a primary contact. If not,
-- escalate this to the AE
BEGIN
SELECT
cu.first_name,
cu.last_name
, 'ACCOUNT EXECUTIVE' AS [title]
, 'CCC AE' AS [contact_type]
, 'NOT ASSIGNED' AS [location]
, 0 AS [attempt]
, NULL AS [report_entity_id]
, 'EMAIL' AS [preferred_method]
, am.Email AS [email]
, cu.phone_main AS [phone]
, cu.phone_cell AS [cell_phone]
, cu.fax_main AS [fax]
, '' AS [department]
, '' AS [address1]
, '' AS [address2]
, '' AS [city]
, '' AS [state]
, '' AS [zip]
, 0 AS [contact_id]
FROM Test.dbo.C3_user cu
INNER JOIN C3SecondaryTest.dbo.aspnet_Membership am
ON cu.master_user_id = am.UserId
INNER JOIN Test.dbo.client_details cd
ON cd.client_id = @clientid
WHERE cu.c3_user_id = cd.account_executive
SET @activerowcount = @@ROWCOUNT
IF @activerowcount < 1
BEGIN
SET @resultcode = -130
RETURN -1
END
ELSE
BEGIN
SET @resultcode = 100
RETURN 1
END
END
END