【问题标题】:Slow Query when Joined View contains PIVOT加入视图包含 PIVOT 时的慢查询
【发布时间】:2013-08-13 11:50:14
【问题描述】:

我有以下包含 PIVOT 的视图:

CREATE VIEW [vwPhoneNumberByPref]
AS
SELECT * FROM(
    SELECT ObjectKey, ObjectTypeName,r_id,MaskedNumber FROM (
        SELECT * ,ROW_NUMBER() OVER (PARTITION BY ObjectKey, ObjectTypeName ORDER BY preference) as r_id
        FROM vwPhoneNumberMasked  ) AS a WHERE r_id<=3
    )AS P
PIVOT(
    MAX(MaskedNumber) FOR r_id in ([1],[2],[3])
)AS Pvt

当我使用WHERE ObjectKey = 1234 运行它时,它会立即返回结果。当我在连接中使用此查询时:

Select * 
from tblPerson p 
inner join 
    vwPhoneNumberByPref ph on p.PersonID = ph.ObjectKey

大约需要 10 秒,在执行计划中,对超过 200,000 行进行排序。

当不用于连接时,它会在单行上进行“排序”。我尝试使用CROSS APPLY 进行连接,这使它稍微快了一点,但仍然需要很长时间并且仍在对 200,000 奇数行进行排序。

如何提高性能?


附加信息:

CREATE VIEW [vwPhoneNumberMasked] AS
SELECT ph.ObjectTypeName, ph.ObjectKey, dbo.ApplyMask(ph.PhoneNumber, pt.Mask), ph.Preference
FROM tblPhoneNumber ph inner join tblPhoneType pt on
ph.PhoneTypeName = pt.Name
WHERE ph.isDeleted = 0
GO

CREATE TABLE tblPhoneType
Name varchar(20) NOT NULL,
Mask varchar(20) NOT NULL
GO

tblPhoneNumber 上有一个索引,ObjectTypeName, ObjectKey, Preference, isDeleted

函数dbo.ApplyMask将PhoneType中的Mask应用于PhoneNumber,掩码为(##) #### ####

我实际上并没有运行Select * from tblPerson,但即使运行SELECT PersonID from tblPerson INNER JOIN .... 也会导致查询花费很长时间。这只是一个例子。

【问题讨论】:

  • 你为什么要使用 ROW_NUMBER 函数,对不起,我觉得这里不需要分配行号,如果我错了,请纠正我,你可以通过删除分配行号来提高效率。
  • @surajsingh 行号仅用于返回三个值,然后将这三个值转换为数据透视表中的列。
  • 您能否发布您的表结构、vwPhoneNumberMasked 的视图定义并显示您拥有的任何索引?
  • 我已经添加了依赖表和索引,很抱歉省略了这些。
  • @Molloch 你能发布函数dbo.ApplyMask的创建语句吗?

标签: sql sql-server


【解决方案1】:

在您提供更多信息后,我建议您尝试关注。对表tblPhoneNumber添加索引:

create index ix_tblPhoneNumber_1
    on tblPhoneNumber (isDeleted, ObjectKey, ObjectTypeName, Preference)
        include (PhoneNumber, PhoneTypeName)

在桌子上tblPhoneType添加(如果没有的话)

create unique clustered index ix_tblPhoneType
    on tblPhoneType (PhoneTypeName)

create unique index ix_tblPhoneType
    on tblPhoneType (PhoneTypeName) include (Mask)

将您的vwPhoneNumberMasked 视图更改为:

ALTER VIEW [vwPhoneNumberMasked] AS
SELECT ph.ObjectTypeName, ph.ObjectKey, mp.Value as MaskedNumber, ph.Preference
FROM tblPhoneNumber ph
    inner /*loop*/ join tblPhoneType pt on ph.PhoneTypeName = pt.Name
    cross apply ftMaskPhone(ph.PhoneNumber, pt.Mask) mp
WHERE ph.isDeleted = 0

ftMaskPhonethis answer 中的那个(请使用 Approach 2 版本)。

【讨论】:

  • 感谢您的建议,我正在审查它们,同时我已在原始问题中添加了更多信息。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-20
  • 2012-02-20
  • 2011-11-24
  • 2014-05-03
  • 1970-01-01
相关资源
最近更新 更多