[英]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.