我有一个非常复杂的视图,它使用层次结构表结构,它使用层次结构数据类型,并返回丢失的位置。位置是层次结构表。
视图在CTE中执行一个数据透视,然后将其与一些额外的连接一起使用,以便为开发人员生成有用的数据列表。
以下是观点:
CREATE VIEW [dbo].[vwLocations] WITH SCHEMABINDING
AS
WITH p AS
(
SELECT ID,
[1] AS Facility,
[2] AS Community,
[3] AS Unit,
[4] AS Pod,
[5] AS Cell,
[6] AS Bed,
[7] AS Zone,
[8] AS Building,
[9] AS Room
FROM (
SELECT
p.ID,
l.[Name],
l.[Level] + CASE WHEN l.LocationTypeID IN(11,12,13) THEN 5 ELSE 0 END AS Level -- Note, 11,12 and 13 are Non-Accomodation types, so the level needs to move to the Non-Accomodation area
FROM dbo.Location AS l
INNER JOIN dbo.Location AS p
ON p.[Path].IsDescendantOf(l.[Path]) = 1
) AS p
PIVOT (
MAX(Name)
FOR [Level] IN (
[1],
[2],
[3],
[4],
[5],
[6],
[7],
[8],
[9]
)
) AS pvt
)
SELECT ISNULL(l.ID,-999) AS LocationID, -- Done to allow EF to use the view. A view needs something that looks like a KEY.
l.ParentID AS ParentID,
LocationTypeID,
lt.Description AS LocationType,
l.GeoLocation,
l.Name,
p.Facility,
p.Community,
p.Unit,
p.Pod,
p.Cell,
p.Bed,
p.Zone,
p.Building,
p.Room
FROM dbo.Location l
INNER JOIN p
ON p.ID = l.id
INNER JOIN ref.LocationType lt
ON lt.ID = l.LocationTypeID
GO
SELECT * FROM vwLocations在大约60ms内运行。我很高兴。当我将视图连接到某些表以生成结果集时,此查询也很快:
SELECT
Per.Firstname,
per.Surname,
v.*
FROM person per
INNER JOIN dbo.Prisoner pri
ON pri.PersonID = per.ID
LEFT JOIN dbo.vwLocations v
ON v.LocationID = pri.CurrentAccommodationLocationID
运行时间不到半秒,返回800行。
然而,当我在查询中添加一个非常基本的WHERE子句时 - 时间会爆发4到6秒。
SELECT
Per.Firstname,
per.Surname,
v.*
FROM person per
INNER JOIN dbo.Prisoner pri
ON pri.PersonID = per.ID
LEFT JOIN dbo.vwLocations v
ON v.LocationID = pri.CurrentAccommodationLocationID
WHERE per.IsActive = 1
我很困惑为什么WHERE语句在与VIEW不同的表上会导致如此大幅度的速度损失。
我错过了一个索引吗?不是,如果我通过它自己运行View,它很快。并返回所有行。所以我不确定这个观点是否有问题 - 尽管如此,这是唯一复杂的事情。
: Execution plan WITH the where clause
Execution plan WITHOUT the where clause
编辑:
这是奇怪的事情。如果我在Person表中的另一列上进行过滤(此时,我在IsActive = 1上过滤),我会得到快速响应!所以,当我跑:
SELECT
Per.Firstname,
per.Surname,
v.*,
*
FROM person per
INNER JOIN dbo.Prisoner pri
ON pri.PersonID = per.ID
LEFT JOIN dbo.vwLocations v
ON v.LocationID = pri.CurrentAccommodationLocationID
WHERE per.PersonTypeID = 7
返回相同的行数(因为我知道所有活动人都是PersonType 7)。只有当我过滤IsActive(BIT NOT NULL)时,它才会变慢。