Cra*_*aig 4 sql sql-server sql-server-2016
我有一个查询,运行时,结果是即时的。
However, I paste the exact same query into VIEW, and the results take 6 seconds to reply.
For example,
SELECT ... FROM MyTables WHERE PersonID = x
Run Code Online (Sandbox Code Playgroud)
runs fast.
But create a view with:
SELECT ... FROM MyTables
Run Code Online (Sandbox Code Playgroud)
And then call the view:
SELECT * FROM MyView WHERE PersonID = x
Run Code Online (Sandbox Code Playgroud)
And it runs slow.
Actual Query:
select ROW_NUMBER() over(partition by h.Id order by h.[SysStartTime]) as VersionNUmber,
h.Id,
fac.HIC,
... plus 18 other columns from the joined tables.
from [hist].[A_View] as h
inner join [dbo].[Facilities] as fac
on fac.Id = h.FacilityId
inner join ref.FormStatus as r_fs
on r_fs.Id = h.FormStatusId
inner join TableA as data
on data.Id = h.dataId
inner join Consultants as c
on c.Id = h.ConsultantId
inner join dbo.Specialties spec
on spec.Id = h.SpecialtyId
inner join dbo.Users modifieduser
on modifieduser.Id = h.ModifiedByUserId
left join ref.ARefTable as r_uc
on r_uc.Id = h.refId
cross apply [dbo].[getPersonUrn](h.PersonId, h.AnotherIdId) as PersonURN
Run Code Online (Sandbox Code Playgroud)
(Note, I am changing some table names and columns as we're in quite a confidential area)
I notice that 97% of the time, it's in a Sort (Top N Sort), when executing the view. In the query, that 34%, but the plans are completely different.
I suspected parameter sniffing, but don't think that's an issue with Views.
I've actually just 'fixed' it, but no idea why.
My first column in my select is a ROW_NUMBER.
SELECT ROW_NUMBER() over(partition by h.Id order by h.[SysStartTime]) as` VersionNumber,
Run Code Online (Sandbox Code Playgroud)
Removing that, and I get instant results. Not sure why, as both the columns I order by and partition by, are already in the result set.
1) 这里 ROW_NUMBER 仅适用于过滤数据:
SELECT ROW_NUMBER(), ... FROM MyTables WHERE PersonID = x
Run Code Online (Sandbox Code Playgroud)
首先它按 PersonID 过滤,然后计算 ROW_NUMBER
2) 这里 ROW_NUMBER 适用于所有数据:
CREATE VIEW MyView as
select ROW_NUMBER(), ... FROM MyTables
SELECT * FROM MyView WHERE PersonID = x
Run Code Online (Sandbox Code Playgroud)
并且只有在处理完完整数据后,才会应用 PersonID 过滤器
它和
SELECT * FROM
(SELECT ROW_NUMBER(), ... FROM MyTables
) t
WHERE t.PersonID = x
Run Code Online (Sandbox Code Playgroud)
查看示例:
GO
CREATE VIEW dbo.test_view
AS
SELECT ROW_NUMBER() OVER (ORDER BY NAME) rn, o.name, o.[object_id]
FROM sys.objects o
GO
SET SHOWPLAN_XML ON
GO
SELECT rn, o.name, o.[object_id] FROM dbo.test_view o
WHERE OBJECT_ID < 100
GO
SELECT ROW_NUMBER() OVER (ORDER BY NAME) rn, o.name, o.[object_id] FROM sys.objects o
WHERE OBJECT_ID < 100
GO
SET SHOWPLAN_XML OFF
GO
DROP VIEW dbo.test_view
GO
Run Code Online (Sandbox Code Playgroud)
与视图filter操作是到底。所以计划实际上是不同的。
| 归档时间: |
|
| 查看次数: |
2990 次 |
| 最近记录: |