内连接表和视图时性能显着降低

时间:2017-07-27 15:36:34

标签: sql-server

我的sql server中有三个视图:

CREATE VIEW [dbo].[v_CompanyLabelCreate]  
AS   
SELECT   
c.Id AS Id,  
c.[Name] AS CompanyName,   
CASE WHEN r.ApprovedPatentCreativeApplication > 2 OR r.ApprovedCopyRightBookApplication + r.ApprovedCopyRightSoftwareApplication > 4 OR NumberInProduction + NumberNotInProduction > 10 THEN N'创造型'  
ELSE NULL END AS Label  
FROM Company c INNER JOIN ResearchInfo r ON c.Id = r.CompanyID  
WHERE c.Submitted = 1



CREATE VIEW [dbo].[v_CompanyLabelHighPotential]  
AS   
SELECT   
c.Id AS Id,  
c.[Name] AS CompanyName,   
CASE WHEN si1.Income >= 1000000 AND si2.Income <> 0 AND ((si1.Income -si2.Income)/si2.Income) >= 1 THEN N'潜力型'  
     WHEN n1.TotalProfit >= 500000 AND n2.TotalProfit <> 0 AND ((n1.TotalProfit - n2.TotalProfit)/n2.TotalProfit) >= 1 THEN N'潜力型'  
     WHEN nfa1.AssetsTotal >= 5000000 AND nfa2.AssetsTotal <> 0 AND ((nfa1.AssetsTotal - nfa2.AssetsTotal)/nfa2.AssetsTotal) >= 1 THEN N'潜力型'  
ELSE NULL END AS Label  
FROM Company c INNER JOIN SaleIncome si1 ON c.Id = si1.CompanyID AND si1.YearQuarterID = 2  
           INNER JOIN SaleIncome si2 ON c.Id = si2.CompanyID AND si2.YearQuarterID = 1  
           INNER JOIN NetProfit n1 ON c.Id = n1.CompanyID AND n1.YearQuarterID = 2  
  INNER JOIN NetProfit n2 ON c.Id = n2.CompanyID AND n2.YearQuarterID = 1  
  INNER JOIN NonFloatingAsset nfa1 ON c.Id = nfa1.CompanyID AND nfa1.YearQuarterID = 2  
  INNER JOIN NonFloatingAsset nfa2 ON c.Id = nfa2.CompanyID AND nfa2.YearQuarterID = 1  
WHERE c.Submitted = 1




CREATE VIEW [dbo].[v_CompanyLabelHighTotalPolicies]  
AS  
SELECT   
c.Id AS Id,   
c.[Name] AS CompanyName,   
CASE WHEN p.NumberOfPolicies >= 4 AND cp.PolicyID IS NOT NULL THEN N'政策大户'  
ELSE NULL END AS Label  
FROM Company c LEFT JOIN (SELECT CompanyID, COUNT(*) AS NumberOfPolicies FROM CompanyPolicy GROUP BY CompanyID) p ON c.Id = p.CompanyID  
           LEFT JOIN (SELECT CompanyID, PolicyID FROM CompanyPolicy WHERE PolicyID = 7) cp ON c.Id = cp.CompanyID  
WHERE c.Submitted = 1

当我运行一个内部连接这三个视图的select查询时:

select * 
from  v_CompanyLabelCreate clc 
  INNER JOIN v_CompanyLabelHighPotential clhp ON clc.Id = clhp.Id  
  INNER JOIN v_CompanyLabelHighTotalPolicies chtp ON clc.Id = chtp.Id  

快速而顺畅。但是,当我尝试运行一个select查询时,内部将这三个视图与其他一些表连接起来:

select * 
FROM Company c 
  INNER JOIN BasicInfo b ON c.Id = b.CompanyID  
  INNER JOIN CompanyDimension cd ON c.Id = cd.CompanyID  
  INNER JOIN TotalProfit t ON c.Id = t.CompanyID AND t.YearQuarterID = 2  
  INNER JOIN SaleCost sc ON c.Id = sc.CompanyID AND sc.YearQuarterID = 2  
  INNER JOIN CompanyFinancialIndex cfi ON c.Id = cfi.CompanyID AND cfi.YearQuarterID = 6  
  INNER JOIN SaleIncome si1 ON c.Id = si1.CompanyID AND si1.YearQuarterID = 2  
  INNER JOIN SaleIncome si2 ON c.Id = si2.CompanyID AND si2.YearQuarterID = 1  
  INNER JOIN NetProfit n1 ON c.Id = n1.CompanyID AND n1.YearQuarterID = 2  
  INNER JOIN NetProfit n2 ON c.Id = n2.CompanyID AND n2.YearQuarterID = 1  
  INNER JOIN v_CompanyLabelCreate clc ON c.Id = clc.Id  
  INNER JOIN v_CompanyLabelHighPotential clhp ON clc.Id = clhp.Id  
  INNER JOIN v_CompanyLabelHighTotalPolicies chtp ON clc.Id = chtp.Id  
WHERE c.Submitted = 1

看起来需要永远获得结果(在此处下载执行计划:the execution plan)。现在,如果我只运行查询而没有内部加入三个视图,如下所示:

select * 
FROM Company c 
  INNER JOIN BasicInfo b ON c.Id = b.CompanyID  
  INNER JOIN CompanyDimension cd ON c.Id = cd.CompanyID  
  INNER JOIN TotalProfit t ON c.Id = t.CompanyID AND t.YearQuarterID = 2  
  INNER JOIN SaleCost sc ON c.Id = sc.CompanyID AND sc.YearQuarterID = 2  
  INNER JOIN CompanyFinancialIndex cfi ON c.Id = cfi.CompanyID AND cfi.YearQuarterID = 6  
  INNER JOIN SaleIncome si1 ON c.Id = si1.CompanyID AND si1.YearQuarterID = 2  
  INNER JOIN SaleIncome si2 ON c.Id = si2.CompanyID AND si2.YearQuarterID = 1  
  INNER JOIN NetProfit n1 ON c.Id = n1.CompanyID AND n1.YearQuarterID = 2  
  INNER JOIN NetProfit n2 ON c.Id = n2.CompanyID AND n2.YearQuarterID = 1  
WHERE c.Submitted = 1

再次快速而平稳。

关于使用的表格:

  1. 公司:存储公司ID和公司名称的表格。当然c.Id是PK,稍后会被称为公司ID。
  2. ResearchInfo BasicInfo CompanyDimension CompanyFinancialIndex :CompanyID是外键,每家公司最多只有一个这张表中的一行。
  3. SaleIncome,SaleCost,NetProfit,NonFloatingAsset,TotalProfit :CompanyID和YearQuarterID的组合作为主键,尽管每个表都有一个定义为PK的标识字段。

1 个答案:

答案 0 :(得分:0)

您也可能有错过的索引问题,但您的查询有点复杂。您可以尝试使用cte表来降低复杂性(您需要字段名称在CTE中是唯一的):

WITH cte_tb1 
     AS (SELECT * -- UNIQUE NAMES FIELDS IS REQUIRED 
         FROM   company c 
                INNER JOIN basicinfo b 
                        ON c.id = b.companyid 
                INNER JOIN companydimension cd 
                        ON c.id = cd.companyid 
                INNER JOIN totalprofit t 
                        ON c.id = t.companyid 
                           AND t.yearquarterid = 2 
                INNER JOIN salecost sc 
                        ON c.id = sc.companyid 
                           AND sc.yearquarterid = 2 
                INNER JOIN companyfinancialindex cfi 
                        ON c.id = cfi.companyid 
                           AND cfi.yearquarterid = 6 
                INNER JOIN saleincome si1 
                        ON c.id = si1.companyid 
                           AND si1.yearquarterid = 2 
                INNER JOIN saleincome si2 
                        ON c.id = si2.companyid 
                           AND si2.yearquarterid = 1 
                INNER JOIN netprofit n1 
                        ON c.id = n1.companyid 
                           AND n1.yearquarterid = 2 
                INNER JOIN netprofit n2 
                        ON c.id = n2.companyid 
                           AND n2.yearquarterid = 1 
         WHERE  c.submitted = 1), 
     cte_tb2 
     AS (SELECT * -- UNIQUE NAMES FIELDS IS REQUIRED 
         FROM   v_companylabelcreate clc 
                INNER JOIN v_companylabelhighpotential clhp 
                        ON clc.id = clhp.id 
                INNER JOIN v_companylabelhightotalpolicies chtp 
                        ON clc.id = chtp.id) 
SELECT * 
FROM   cte_tb1 a 
       INNER JOIN cte_tb2 b 
               ON a.id = b.id