SQL performance issue how to modify the below Script?

◇◆丶佛笑我妖孽 提交于 2019-12-11 01:12:50

问题


I have written a SQL query that involves INNER JOIN, LEFT OUTER JOIN, UNION and a subquery which is taking a long time to execute. My SQL skills are not that great and I would appreciate if someone can help me how can I optimize the following query to make it faster.

SELECT 
    Brand, 
    Quantity,  
    RegionNumber,  
    FinancialGroup,
    CustomerLocationNumber,  
    RecipientCode,  
    Company,  
    Contact,  
    Address1,  
    Address2,  
    City,  
    [State],  
    Zip,  
    Country,  
    SUM(CurrentYearSales) 'CurrentYearSales', 
    SUM(PriorYearSales) 'PriorYearSales'
FROM 
    (SELECT DISTINCT  
         B.BrandDescription AS Brand,   
         (CASE WHEN ISNULL(DS.FinancialGroup,'') = '' THEN 0 ELSE  ISNULL(DS.Quantity, MB.Quantity) END) As Quantity,  
         DS.RegionNumber AS RegionNumber,  
         DA.FinancialGroup 'FinancialGroup',  
         DA.CustomerGroup2 'CustomerLocationNumber',  
         RC.RecipientCode 'RecipientCode',  
         DA.Name AS Company,  
         'ATTN: KITCHEN DEPT' AS Contact,  
         DA.Address1 'Address1',  
         DA.Address2 'Address2',  
         DA.City,  
         DA.[State],  
         DA.Zip,  
         DA.Country,  
         ISNULL(CYearSales,0) 'CurrentYearSales',  
         ISNULL(PYearSales,0) 'PriorYearSales'  
     FROM 
         DealerLocator.DealerAddress DA   
     INNER JOIN 
         DealerLocator.MailingBrand MB ON DA.DealerAddessID = MB.DealerAddessID
     INNER JOIN  
         Brand B ON B.BrandCode = MB.BrandCode  
     INNER JOIN 
         [DealerLocator].[SalesRepCustomerGroup2] SR ON DA.FinancialGroup = SR.FinancialGroup 
                                                     AND DA.CustomerGroup2 = SR.CustomerGroup2  
     INNER JOIN 
         DealerLocator.RecipientCode RC ON DA.DealerAddessID = RC.DealerAddessID  
     INNER JOIN 
         DealerLocator.BrandException BE ON BE.BrandCode = MB.BrandCode 
                                         AND BE.BrandGroupID IS NOT NULL  
     INNER JOIN 
         DealerLocator.BrandGroup BGR ON BE.BrandGroupID = BGR.BrandGroupID   
     LEFT JOIN 
         #SalesSummaryData DS ON DA.FinancialGroup = DS.FinancialGroup 
                              AND DA.CustomerGroup2 = DS.CustomerGroup2  
                              AND DS.WebSiteName = BGR.WebsiteName  
     WHERE 
         DA.IsDeleted = 0 
        --Added below condition by senthil To get only active dealer locations-INC0115761    
         AND MB.IsActive = 1
         AND (DA.IsFedExAllowed = 1 AND DA.IsMailing = 1)  
         AND DS.RegionNumber = RC.RegionNumber 
         AND RC.FinancialGroup = DA.FinancialGroup
         AND RC.CustomerGroup2 = DA.CustomerGroup2
         AND (CASE WHEN ISNULL(DS.FinancialGroup,'') = '' THEN 0 ELSE ISNULL(DS.Quantity, MB.Quantity)END) != 0  
         AND (@UserID IS NULL OR SR.SalesRepID = @UserID)  
         AND (@BrandCodes IS NULL OR EXISTS (SELECT Top 1 1 FROM @BrandData WHERE Data = MB.BrandCode))  
         AND (@FinancialGroups IS NULL OR EXISTS (SELECT Top 1 1 FROM @FinancialData WHERE Data = DA.FinancialGroup))) temp
GROUP BY
    Brand,
    Quantity,  
    RegionNumber,  
    FinancialGroup,
    CustomerLocationNumber,  
    RecipientCode,  
    Company,  
    Contact,  
    Address1,  
    Address2,  
    City,  
    [State],  
    Zip,  
    Country 

Inside of the stored procedure, this query was taking a long time - can anyone help modify it to improve the performance? How to improve the performance and avoid timeout issues?


回答1:


There are a few things we need from you first, which is too long to comment.

  • Read getting help with a slow query by Brent Ozar's team.
  • Execute your query and give us the actual execution plan. Be sure to paste it here and provide the link.
  • Tell us more about your environment. Specifically CPU, Memory, MAXDOP Setting, Cost Threshold for Parallelism, etc.
  • See what else is going on when you are running your query. Maybe it's contending for resources. sp_whoisactive is a great script to help with this. Give us the results of it.
  • Provide the indexes of the tables
  • Read Aaron's post about Kitchen Sink queries, which is what you have with your optional parameters, for improvements.
  • Let us know the output of DBCC SHOW_STATISTICS

Here are some things that could be happening and would slow down your query, which having the details above would help focus:

  • You have a bad query plan due to parameter sniffing, or an array of other things.
  • You use DISTINCT when it's not necessary (it may be, just a guess). It can cause issues.
  • Your table statistics are off which is causing the optimizer to request a less than optimal query plan. Redgate's article has good info on this.
  • You have missing indexes causing table scans
  • You are querying millions of rows from a small server (CPU, RAM, etc)
  • There are other queries or processes that are sharing the resources, causing locks or blocks, etc
  • Your query is waiting on (whatever) but Paul Randal will help you to determine what they are and what to do about it.

Post Execution Plan Analysis

You have a table scan which could be mitigated with the suggest index

Missing Index (Impact 66.8326): CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>] ON [SalesView].[SalesDetail_History] ([CustomerGroup2]) INCLUDE ([AccountNumber],[BrandCode],[FiscalYear],[FiscalMonth],[cYMonthAmt]

Then you are getting a lot of table scans on your TEMP TABLES when you try to update your actual tables, SSD, CAB, etc... Adding indexes to your temp tables could help this, but will slow down the insert into the temp table. You'll just have to try it to see if it is worth it for this query.

Lastly, change your MAXDOP and COST settings, since there is a lot of parallelism in this query which may not be needed.



来源:https://stackoverflow.com/questions/52891959/sql-performance-issue-how-to-modify-the-below-script

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!