簡體   English   中英

查詢SQL Server上的視圖時出現性能問題

[英]Performance issues while querying a view on SQL Server

我目前遇到了一些SQL Server 2016 Enterprise上出現奇怪行為的性能問題。

我在數據庫中創建了一個新模式,然后在這個模式中創建了一個視圖。

現在,當我直接連接到數據庫時,它包含這個模式和視圖,並編寫一個簡單的查詢

SELECT * FROM SCHEMA.VIEW

完成需要大約30分鍾(!)。 完全合格的查詢也是如此

SELECT * FROM DB_NAME.SCHEMA.VIEW

但是現在,如果我首先將數據庫更改為主數據庫或另一個用戶數據庫,然后再跨數據庫再次運行查詢,它將在大約10秒內完成(!)。 兩個數據庫的數據庫屬性相同,以及數據庫文件和日志文件的已用驅動器。

有沒有人知道可能導致這種巨大性能問題的原因?

我在視圖中使用了以下代碼:

CREATE VIEW [controlling].[UnitLoginHistory]
AS

    WITH    cte 
            ( 
                    Jahr, UnityId, Unit_UnityId, Analytical_Code, Unit_Code, Unit_Name, Active
            ,       Show_in_org_chart, Begin_Date, End_Date, Unit_Owner_First_Name, Unit_Owner_Last_Name
            ,       Unit_Owner_Login, Unit_Owner_CorporateID, UnityParentId, UnityTypeId, Unit_Level
            ,       Magnitude_Code, ImportDate, ReplicationLevel 
            ) 
    AS
    (
            SELECT
                    dt.Jahr
            ,       a.UnityId 
            ,       a.UnityId 
            ,       a.Analytical_Code 
            ,       a.Unit_Code 
            ,       a.Unit_Name 
            ,       cast(case when a.Active = 'True' then 1 else 0 end as bit)
            ,       a.Show_in_org_chart 
            ,       a.Begin_Date 
            ,       a.End_Date 
            ,       a.Unit_Owner_First_Name 
            ,       a.Unit_Owner_Last_Name 
            ,       a.Unit_Owner_Login 
            ,       a.Unit_Owner_CorporateID 
            ,       a.UnityParentId 
            ,       a.UnityTypeId 
            ,       a.Unit_Level 
            ,       a.Magnitude_Code
            ,       a.ImportDate
            ,       1
            FROM    [Staging_INPUT].[DBO].[OBS_Workunit]    a
            JOIN    (
                            SELECT
                                    YEAR(IMPORTDATE)        Jahr
                            ,       MAX(IMPORTDATE)         Datum
                            FROM    [Staging_INPUT].[DBO].[OBS_Workunit]
                            GROUP   BY
                                    YEAR(IMPORTDATE) 
                    )                                       dt
            ON      a.ImportDate                    =       dt.datum
            WHERE   a.unitytypeid                   =       12
            UNION   ALL
            SELECT
                    b.Jahr
            ,       b.UnityId 
            ,       a.UnityId 
            ,       b.Analytical_Code 
            ,       a.Unit_Code 
            ,       a.Unit_Name 
            ,       cast(case when a.Active = 'True' then 1 else 0 end as bit)
            ,       a.Show_in_org_chart 
            ,       a.Begin_Date 
            ,       a.End_Date 
            ,       a.Unit_Owner_First_Name 
            ,       a.Unit_Owner_Last_Name 
            ,       a.Unit_Owner_Login      
            ,       a.Unit_Owner_CorporateID 
            ,       a.UnityParentId 
            ,       a.UnityTypeId   
            ,       a.Unit_Level 
            ,       a.Magnitude_Code
            ,       a.ImportDate 
            ,       b.ReplicationLevel + 1
            FROM    [Staging_INPUT].[DBO].[OBS_Workunit]    a
            JOIN    cte                                     b
            ON      a.UnityId                       =       b.UnityParentId
            AND     a.ImportDate                    =       b.ImportDate
            AND     a.UnityTypeId                   >=      6 
    )
    ,       Company
    AS
    (
            SELECT  DISTINCT 
                    Jahr
            ,       UnityId
            ,       LEFT(REPLACE(Magnitude_Code,'XE','U'),4) CompanyUID
            FROM    cte
            WHERE   UnityTypeId     =       7
            AND     Active          =       1

    )
    ,       BUs 
    AS
    (
            SELECT  DISTINCT 
                    a.Jahr                          JAHR
            ,       a.UnityId                       UnityId
            ,       c.Analytical_Code               BU_CODE
            ,       c.Unit_Name                     BU_NAME
            ,       b.CompanyUID
            FROM    cte                     a

            JOIN    Company                 b
            ON      a.Jahr          =       b.Jahr
            AND     a.UnityId       =       b.UnityId
            AND     a.Active        =       1

            JOIN    cte                     c
            ON      a.Jahr          =       c.Jahr
            AND     a.UnityId       =       c.Unit_UnityId
            AND     c.Active        =       1

            WHERE   ISNULL(c.Analytical_Code,'') != ''
    )
    SELECT  DISTINCT
            a.JAHR                          JAHR
    ,       a.BU_CODE                       BU_CODE
    ,       a.BU_NAME                       BU_NAME
    ,       'EUROPE\'
    +       b.Unit_Owner_Login              BU_LOGIN
    ,       b.Unit_Owner_Last_Name 
    +       ', '
    +       b.Unit_Owner_First_Name         BU_LOGIN_NAME
    ,       a.CompanyUID                    COMPANY_UID
    FROM    BUs                             a

    JOIN    cte                             b
    ON      a.Jahr                  =       b.Jahr
    AND     a.UnityId               =       b.UnityId
    AND     b.Active                =       1

    UNION   

    SELECT  DISTINCT
            a.Jahr                          JAHR
    ,       a.BU_CODE                       BU_CODE
    ,       a.BU_NAME                       BU_NAME
    ,       c.BU_LOGIN                      BU_LOGIN
    ,       c.BU_LOGIN_NAME                 BU_LOGIN_NAME
    ,       a.CompanyUID                    COMPANY_UID
    FROM    BUs                             a

    CROSS   JOIN (
                    SELECT  DISTINCT
                            [Last Name]     COLLATE Latin1_General_100_CI_AS
                    +       ', '
                    +       [First Name]    COLLATE Latin1_General_100_CI_AS BU_LOGIN_NAME   
                    ,       'EUROPE\'
                    +       [User Id]       COLLATE Latin1_General_100_CI_AS BU_LOGIN  
                    FROM    NAVISION.dbo.Employee
                    WHERE   [Global Dimension 2 Code]       IN      (
                                                                            10061
                                                                    ,       10062
                                                                    )
                    AND     ISNULL([User Id],'')            !=      ''
                 )                          c

GO 

執行時間和統計數據:

use NAVISION

GO

set statistics io on 
set statistics time on

select * 
from NAVISION.dbo.UnitLoginHistory 
where Jahr = 2017 
order by 1,2

SQL Server解析和編譯時間:CPU時間= 0 ms,經過時間= 0 ms。

(34119行受影響)表'工作台'。 掃描計數1607,邏輯讀取253696,物理讀取0,預讀讀取1238,lob邏輯讀取0,lob物理讀取0,lob預讀讀取0.表'U415 Altran Engineering GmbH $ Employee'。 掃描計數1,邏輯讀取128,物理讀取0,預讀讀取0,lob邏輯讀取0,lob物理讀取0,lob預讀讀取0.表'U388 Altran Aviation GmbH $ Employee'。 掃描計數1,邏輯讀取42,物理讀取0,預讀讀取0,lob邏輯讀取0,lob物理讀取0,lob預讀讀取0.表'U354 Altran Service GmbH $ Employee'。 掃描計數1,邏輯讀取210,物理讀取0,預讀讀取0,lob邏輯讀取0,lob物理讀取0,lob預讀讀取0.表'U353 AIH Holding GmbH Co KG $ Employee'。 掃描計數1,邏輯讀取934,物理讀取0,預讀取讀取0,lob邏輯讀取0,lob物理讀取0,lob預讀取讀取0.表'OBS_Workunit'。 掃描計數46286,邏輯讀取10430933,物理讀取0,預讀取讀取0,lob邏輯讀取0,lob物理讀取0,lob預讀讀取0。

SQL Server執行時間:CPU時間= 1363546毫秒,已用時間= 1455980毫秒。

use Staging_INPUT
GO

set statistics io on 
set statistics time on

select * 
from NAVISION.dbo.UnitLoginHistory 
where Jahr = 2017 
order by 1,2

SQL Server解析和編譯時間:CPU時間= 0 ms,經過時間= 0 ms。

(34119行受影響)表'工作台'。 掃描計數582,邏輯讀取576096,物理讀取0,預讀讀取146,lob邏輯讀取0,lob物理讀取0,lob預讀讀取0.表'Workfile'。 掃描計數0,邏輯讀取0,物理讀取0,預讀取讀取0,lob邏輯讀取0,lob物理讀取0,lob預讀取讀取0.表'OBS_Workunit'。 掃描計數53573,邏輯讀取485656,物理讀取0,預讀讀取0,lob邏輯讀取0,lob物理讀取0,lob預讀讀取0.表'U415 Altran Engineering GmbH $ Employee'。 掃描計數1,邏輯讀取128,物理讀取0,預讀讀取0,lob邏輯讀取0,lob物理讀取0,lob預讀讀取0.表'U388 Altran Aviation GmbH $ Employee'。 掃描計數1,邏輯讀取42,物理讀取0,預讀讀取0,lob邏輯讀取0,lob物理讀取0,lob預讀讀取0.表'U354 Altran Service GmbH $ Employee'。 掃描計數1,邏輯讀取210,物理讀取0,預讀讀取0,lob邏輯讀取0,lob物理讀取0,lob預讀讀取0.表'U353 AIH Holding GmbH Co KG $ Employee'。 掃描計數1,邏輯讀取934,物理讀取0,預讀取讀取0,lob邏輯讀取0,lob物理讀取0,lob預讀讀取0。

SQL Server執行時間:CPU時間= 15047 ms,已用時間= 28007 ms。

不同的性能必須歸因於不同的執行計划。 由於計划因數據庫環境而異,因此這表明了影響計划的不同設置。 有許多默認的SET選項和屬性可能因數據庫而異,您錯過了一兩個。

我建議為2個數據庫生成CREATE DATABASE腳本並比較腳本。

編輯:

數據庫兼容級別設置的差異可能會影響執行計划。 SQL Server將使用110(SQL Server 2012)級別的數據庫的舊基數估計器,而除非打開LEGACY_CARDINALITY_ESTIMATION數據庫作用域設置,否則較新的CE將用於120及更高版本的數據庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM