当我使用非null参数执行某个存储过程(从非索引视图中选择)时,它在大约10ms时快速闪电。当我使用NULL参数执行它(导致FKColumn = NULL查询)时,它在大约1200ms处慢得多。
我已经用实际执行计划执行了它,看起来查询中最昂贵的部分是聚集索引扫描,在fk列上有谓词IS NULL - 59%!该专栏的索引是(AFAIK)好。
那么我该怎样做才能提高性能呢?将fk列更改为NOT NULL并使用默认值填充空值?
SELECT top 20 dbo.vwStreamItems.ItemId
,dbo.vwStreamItems.ItemType
,dbo.vwStreamItems.AuthorId
,dbo.vwStreamItems.AuthorPreviewImageURL
,dbo.vwStreamItems.AuthorThumbImageURL
,dbo.vwStreamItems.AuthorName
,dbo.vwStreamItems.AuthorLocation
,dbo.vwStreamItems.ItemText
,dbo.vwStreamItems.ItemLat
,dbo.vwStreamItems.ItemLng
,dbo.vwStreamItems.CommentCount
,dbo.vwStreamItems.PhotoCount
,dbo.vwStreamItems.VideoCount
,dbo.vwStreamItems.CreateDate
,dbo.vwStreamItems.Language
,dbo.vwStreamItems.ProfileIsFriendsOnly
,dbo.vwStreamItems.IsActive
,dbo.vwStreamItems.LocationIsFriendsOnly
,dbo.vwStreamItems.IsFriendsOnly
,dbo.vwStreamItems.IsDeleted
,dbo.vwStreamItems.StreamId
,dbo.vwStreamItems.StreamName
,dbo.vwStreamItems.StreamOwnerId
,dbo.vwStreamItems.StreamIsDeleted
,dbo.vwStreamItems.RecipientId
,dbo.vwStreamItems.RecipientName
,dbo.vwStreamItems.StreamIsPrivate
,dbo.GetUserIsFriend(@RequestingUserId, vwStreamItems.AuthorId) as IsFriend
,dbo.GetObjectIsBookmarked(@RequestingUserId, vwStreamItems.ItemId) as IsBookmarked
from dbo.vwStreamItems WITH (NOLOCK)
where 1 = 1
and vwStreamItems.IsActive = 1
and vwStreamItems.IsDeleted = 0
and vwStreamItems.StreamIsDeleted = 0
and (
StreamId is NULL
or
ItemType = 'Stream'
)
order by CreateDate desc
答案 0 :(得分:2)
当它不为空时,你有吗
and vwStreamItems.StreamIsDeleted = 0
and (
StreamId = 'xxx'
or
ItemType = 'Stream'
)
或
and vwStreamItems.StreamIsDeleted = 0
and (
StreamId = 'xxx'
)
你有一个OR子句很可能是问题,而不是IS NULL。
计划将说明原因:OR强制扫描,但可以使用StreamId ='xxx'进行管理。使用IS NULL时,会失去选择性。
我建议更改您的索引,使StreamId成为最右侧的列。
但是,视图只是一个扩展的宏,因此基表上的基础查询可能很复杂且不易优化...
答案 1 :(得分:0)
最大的性能提升是您尝试释放GetUserIsFriend和GetObjectIsBookmarked函数并使用JOIN来实现相同的功能。在查询中使用函数或存储过程与使用FOR循环基本相同 - 项目被逐个调用以确定函数的值。如果您使用连接表,则所有项目值将在1遍中一起确定为一组。