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 |
SQL_SSIS_Dev
Starting Member
10 Posts |
Posted - 2014-10-09 : 10:31:15
|
Hello,Below is the query:UPDATE [RFRL_CGN_CFQ].[CashForQuotes].CFQ_ReferralsSET [RFRL_CGN_CFQ].[CashForQuotes].CFQ_Referrals.RecKey = dbo.BuildRecordKey(A.ReferralCode, A.[RetentionID],A.[ClientFName],A.[ClientLName], IIf(A.Qt_Grp='MOAT',A.[QuotePolicyType],A.[ClientZip]),A.[QuoteType])FROM(select CFRQ.RecChangeID, CFRQ.RetentionID, CFRQ.RecKey, CFRQ.ReferralCode, CFRQ.ClientFName, CFRQ.ClientLName, QTtypes.Qt_Grp, CFRQ.QuotePolicyType, CFRQ.ClientZip, CFRQ.QuoteTypefrom [RFRL_CGN_CFQ].[CashForQuotes].CFQ_Referrals as CFRQLEFT JOIN [RFRL_CGN_CFQ].[CashForQuotes].t_Chg_Rsns as CHGRSNSON CFRQ.RecChangeID = CHGRSNS.Chg_ReasIDINNER JOIN [RFRL_CGN_CFQ].[CashForQuotes].t_Qt_Typs QTtypesON CFRQ.QuoteType = QTtypes.Qt_Typ WHERE (((CFRQ.RecProcessed)=0) AND ((CFRQ.RecChange)=1) AND ((CHGRSNS.ImpactsRecKey)=1)) OR (((CFRQ.RecKey) Is Null)) OR (((CFRQ.RecKey)=''))) AWHERE [RFRL_CGN_CFQ].[CashForQuotes].CFQ_Referrals.RecChangeID = A.RecChangeIDHowever, when I run the below statement, it returns values in less than a second.select dbo.BuildRecordKey ('93572','220116K2831808','PHILIP', 'CONGDON', IIf('AUTO'='MOAT','A','78132'),'aSNAP');How to decrease the execution time of this query? I am using this query in one of my SSIS packages.Any help is highly appreciated.... |
|
gbritton
Master Smack Fu Yak Hacker
2780 Posts |
Posted - 2014-10-10 : 09:04:15
|
what about the subquery? Run that on its own and observer the performance. Good? Bad? Are the columns in the JOIN and WHERE predicates indexed? also, fwiw, use a SQL formatter! Here's what poorsql.com does with your query (with a few adjustments):UPDATE [RFRL_CGN_CFQ].[CashForQuotes].CFQ_ReferralsSET [RFRL_CGN_CFQ].[CashForQuotes].CFQ_Referrals.RecKey = dbo.BuildRecordKey(A.ReferralCode, A.[RetentionID], A.[ClientFName], A.[ClientLName], IIf(A.Qt_Grp = 'MOAT', A.[QuotePolicyType], A.[ClientZip]), A.[QuoteType])FROM ( SELECT CFRQ.RecChangeID ,CFRQ.RetentionID ,CFRQ.RecKey ,CFRQ.ReferralCode ,CFRQ.ClientFName ,CFRQ.ClientLName ,QTtypes.Qt_Grp ,CFRQ.QuotePolicyType ,CFRQ.ClientZip ,CFRQ.QuoteType FROM [RFRL_CGN_CFQ].[CashForQuotes].CFQ_Referrals AS CFRQ LEFT JOIN [RFRL_CGN_CFQ].[CashForQuotes].t_Chg_Rsns AS CHGRSNS ON CFRQ.RecChangeID = CHGRSNS.Chg_ReasID INNER JOIN [RFRL_CGN_CFQ].[CashForQuotes].t_Qt_Typs QTtypes ON CFRQ.QuoteType = QTtypes.Qt_Typ WHERE ( ((CFRQ.RecProcessed) = 0) AND ((CFRQ.RecChange) = 1) AND ((CHGRSNS.ImpactsRecKey) = 1) ) OR (((CFRQ.RecKey) IS NULL)) OR (((CFRQ.RecKey) = '')) ) AWHERE [RFRL_CGN_CFQ].[CashForQuotes].CFQ_Referrals.RecChangeID = A.RecChangeID easier to read, don't you think? |
|
|
lazerath
Constraint Violating Yak Guru
343 Posts |
Posted - 2014-10-24 : 14:52:47
|
Here are a couple things you can do:1.) Your where clause is a problem because you have OR with different columns involved in the expressions. The db engine can't optimize index utilization with this. I would advocate splitting this into multiple statements to handle the different conditions and ensuring you have proper indexing in place to support these filters.Condition 1:WHERE CFRQ.RecProcessed = 0AND CFRQ.RecChange = 1AND CHGRSNS.ImpactsRecKey = 1 Condition 2:WHERE CFRQ.RecKey IS NULL OR CFRQ.RecKey = '' To see the difference, look at the execution plan for the following statments:-- I know this isn't the complete criteria, but want to show you the effect on the exection planSELECT COUNT(*)FROM [RFRL_CGN_CFQ].[CashForQuotes].CFQ_Referrals AS CFRQ WITH (NOLOCK)WHERE CFRQ.RecKey IS NULLOR CFRQ.RecKey = ''OR ( CFRQ.RecProcessed = 0AND CFRQ.RecChange = 1 );SELECT COUNT(*)FROM [RFRL_CGN_CFQ].[CashForQuotes].CFQ_Referrals AS CFRQ WITH (NOLOCK)WHERE CFRQ.RecProcessed = 0AND CFRQ.RecChange = 1;SELECT COUNT(*)FROM [RFRL_CGN_CFQ].[CashForQuotes].CFQ_Referrals AS CFRQ WITH (NOLOCK)WHERE CFRQ.RecKey IS NULLSELECT COUNT(*)FROM [RFRL_CGN_CFQ].[CashForQuotes].CFQ_Referrals AS CFRQ WITH (NOLOCK)WHERE CFRQ.RecKey = ''SELECT COUNT(*)FROM [RFRL_CGN_CFQ].[CashForQuotes].CFQ_Referrals AS CFRQ WITH (NOLOCK)WHERE CFRQ.RecKey = '' OR CFRQ.RecKey IS NULL 2.) Regarding condition 2, while it is a small optimization, ask yourself if you really expect either NULL or '' in the data set. Many times I have seen a similar condition, the application can reliably expect one or the other and not both. If you can eliminate one condition, it saves the engine some work. If you employ a technique such as COALESCE(CFRQ.RecKey,'') = '', it will be non-SARGable and force a scan.3.) Check for proper indexing. You want your index to start with filter criteria. In this case, you would want one on CFQ_Referrals (RecProcessed,RecChange) and one on CFQ_Referrals (RecKey). You would probably want to INCLUDE at the minimum (RecChangeID,QuoteType) in both as they are used in the join criteria. If you still want it to be faster, you can include all the columns in your output list that you use in the SET section, but keep in mind there is a storage cost as well as a write cost to that. Also, you would want an index on t_Chg_Rsns (Chg_ReasID,ImpactsRecKey) [maybe reverse those, test both] and one on t_Qt_Typs (Qt_Typ) INCLUDE(Qt_Grp). Note that if you already have a CLUSTERED index on any of these, the leaf level automatically includes all columns in the table, so you don't need another NONCLUSTERED index with the include columns.4.) If you are indexed properly, double-check all columns involved in join criteria are the same datatypes on both side of each expression. An implicit datatype conversion will force the terms to be non-SARGable and require a scan.Clean-up / best practices:5.) Don't put parentheses around things that don't actually need them. It just makes it harder to read, which will increase maintenance costs.In the worst case example:WHERE ( ((CFRQ.RecProcessed) = 0) AND ((CFRQ.RecChange) = 1) AND ((CHGRSNS.ImpactsRecKey) = 1) ) OR (((CFRQ.RecKey) IS NULL)) OR (((CFRQ.RecKey) = '')) should be:WHERE ( CFRQ.RecProcessed = 0 AND CFRQ.RecChange = 1 AND CHGRSNS.ImpactsRecKey = 1 ) OR CFRQ.RecKey IS NULL OR CFRQ.RecKey = '' This brings up another point that goes with #1: if you need to use parentheses, reevaluate why. Most of the time there is a performance problem that can be eliminated by finding a way to eliminate the parentheses.6.) Eliminate the derived table and just use ANSI compliant join syntax. This simplifies your query and reduces your code:UPDATE CFRQSET CFRQ.RecKey = dbo.BuildRecordKey(A.ReferralCode, A.[RetentionID], A.[ClientFName], A.[ClientLName], IIf(A.Qt_Grp = 'MOAT', A.[QuotePolicyType], A.[ClientZip]), A.[QuoteType])FROM [RFRL_CGN_CFQ].[CashForQuotes].CFQ_Referrals AS CFRQ LEFT JOIN [RFRL_CGN_CFQ].[CashForQuotes].t_Chg_Rsns AS CHGRSNS ON CFRQ.RecChangeID = CHGRSNS.Chg_ReasID INNER JOIN [RFRL_CGN_CFQ].[CashForQuotes].t_Qt_Typs QTtypes ON CFRQ.QuoteType = QTtypes.Qt_Typ WHERE CFRQ.RecProcessed = 0 AND CFRQ.RecChange = 1 AND CHGRSNS.ImpactsRecKey = 1UPDATE CFRQSET CFRQ.RecKey = dbo.BuildRecordKey(A.ReferralCode, A.[RetentionID], A.[ClientFName], A.[ClientLName], IIf(A.Qt_Grp = 'MOAT', A.[QuotePolicyType], A.[ClientZip]), A.[QuoteType])FROM [RFRL_CGN_CFQ].[CashForQuotes].CFQ_Referrals AS CFRQ LEFT JOIN [RFRL_CGN_CFQ].[CashForQuotes].t_Chg_Rsns AS CHGRSNS ON CFRQ.RecChangeID = CHGRSNS.Chg_ReasID INNER JOIN [RFRL_CGN_CFQ].[CashForQuotes].t_Qt_Typs QTtypes ON CFRQ.QuoteType = QTtypes.Qt_Typ WHERE CFRQ.RecKey IS NULL OR CFRQ.RecKey = '' |
|
|
|
|
|
|
|