Uploaded image for project: 'CFA MX '
  1. CFA MX
  2. CFAMX-10239

Implement DB optimization specialists suggestions

    Details

    • Type: Story
    • Status: Closed (View Workflow)
    • Resolution: Won't Develop
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None
    • SCRUM Team:
      Watchmen
    • Work Type Classification:
      Sustaining

      Description

      Ryan Thomson (a SQL optimization consultant with Fourth) suggested this for this SQL statement:

      Declare @tmp_Forecasts table ( ForecastID bigint primary key clustered )
      Insert into @tmp_Forecasts
      Select ForecastId
      FROM (
      	SELECT ForecastId, ROW_NUMBER() OVER (PARTITION BY EntityId, BusinessDay ORDER BY GenerationDate DESC) RowNumber 
      	FROM Forecasting.Forecast WITH(NOLOCK)
      	WHERE EntityId = @p0
      		And BusinessDay between CONVERT(date, @p1) AND CONVERT(date, @p2)
      	) f WHERE RowNumber = 1
      
      SELECT 
      		i.InventoryItemId,
      		CAST(CASE WHEN i.ServiceType IN ('' + @p3 + '') THEN 1 ELSE 0 END AS bit) AS Excluded,
      		Sum(i.RawTransactionCount) AS RawTransactionCount,
      		Sum(i.SystemTransactionCount) AS SystemTransactionCount,
      		Sum(i.ManagerTransactionCount) AS ManagerTransactionCount,
      		Sum(i.LastYearTransactionCount) AS LastYearTransactionCount
      FROM	Forecasting.InventoryItemMetricDetail i WITH(NOLOCK)
      		Inner Join @tmp_Forecasts Fore on ( i.ForecastId = Fore.ForecastId )
      WHERE	i.IntervalStart between @p1 AND @p2
      GROUP BY i.InventoryItemId, CASE WHEN i.ServiceType IN ('' + @p3 + '') THEN 1 ELSE 0 END
      

      And his explanation:

      1. For SQL to use a better estimation plan, pre-select the ForecastIDs into a temp table variable, instead of storing it as a comma separated value in a local variable.
        i.e :
        From :
        SELECT @IDList = COALESCE(@IDList +'','', '''') + CONVERT(varchar(20),ForecastId)
        

        To :

        Insert into @tmp_Forecasts
        Select ForecastID 
        FROM Forecasting.Forecast F WITH(NOLOCK)
        
      2. Dynamic SQL : This query has a dynamic SQL statement within a Dynamic Statement ( 2 levels ). When joining tables and trying to use the Partition Keys / Indexes, try to remove concatenations & dynamic queries as much as possible. By pre-selecting the ForecastIDs into a temp table variable and joining with the Main Forecasting.InventoryItemMetricDetail table, SQL can better estimate the plan.
        i.e :
        From :
        FROM Forecasting.InventoryItemMetricDetail i WITH(NOLOCK)
            WHERE i.ForecastId IN ('' + @IDList + '')
                    AND i.IntervalStart >= @p0 
                    AND i.IntervalStart <= @p1
        

        To :

        FROM	Forecasting.InventoryItemMetricDetail i WITH(NOLOCK)
        		Inner Join @tmp_Forecasts Fore on ( i.ForecastId = Fore.ForecastId )
        WHERE	i.IntervalStart between @p0 AND @p1
        
      3. When searching on DateTime columns for a date range, use “between” operator instead of >, >=, <, <=
      4. Type Conversions when comparing columns and variables. Previously the ID list was a varchar variable. ForecastId column is a bigint and this was being compared to the IDList varchar column. Sometimes due to type conversions, SQL isn’t able to estimate the right index to use. By storing the required ForecastIds in a temptable variable, with bigint field, and comparing this to the ForecastID column in the table, the Query optimizer is able to estimate and use the right index. Hence the drop in Cost by 99%
      5. If it’s possible to get rid of the dynamic SQL, and instead convert this query into a Stored Procedure, that would be ideal. Will need to check the application code to see where this is called from and if this is feasible.

        Attachments

          Issue Links

          1.
          Review Test Scripts QA Task Ready for QA Unassigned

          0%

          Original Estimate - 0.5h
          Remaining Estimate - 0.5h
          2.
          Deploy QA Task Ready for QA Unassigned

          0%

          Original Estimate - 0.5h
          Remaining Estimate - 0.5h
          3.
          Functional Review with QA Dev Task Ready for Developer Unassigned

          0%

          Original Estimate - 0.5h
          Remaining Estimate - 0.5h
          4.
          DIT Dev Task Ready for Developer Unassigned

          0%

          Original Estimate - 0.5h
          Remaining Estimate - 0.5h

            Activity

              People

              • Assignee:
                Corey.Amend Corey Amend (Inactive)
                Reporter:
                Corey.Amend Corey Amend (Inactive)
              • Watchers:
                0 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:

                  Time Tracking

                  Estimated:
                  Original Estimate - 2h
                  2h
                  Remaining:
                  Remaining Estimate - 2h
                  2h
                  Logged:
                  Time Spent - Not Specified
                  Not Specified

                    PagerDuty

                    Error rendering 'com.pagerduty.jira-server-plugin:PagerDuty'. Please contact your Jira administrators.