我开发了一个存储过程,它从表VisitorsInfluences中获取数据,并在每个星系的中间构建五个星系,其中“受影响最大的访问者”,以及每个星系周围受它们影响最大的访问者。到目前为止这是否清楚?
我不知道为什么,存储过程有时需要大约6或7或10秒才能运行,并且在网站上显示的速度非常慢。
你可以帮我解决这个问题吗?我不知道花了这么长时间,但我知道哪个查询是,所以我将在下面评论。谢谢,
布赖恩
存储过程:
ALTER proc [dbo].[XInfluencedByYCloudGetXml] (@VisitorId int, @VisitorIdLogged int, @mindTopicId varchar(17))
as
set nocount on
declare @threshold decimal(6,2),
@FirstObj varchar(17),
@GalaxyId int,
@MainObjTitle varchar(255),
@MyMindTopicId varchar(17),
@CoId varchar(17)
set @threshold = 0.0001
set @GalaxyId = 1
select @MyMindTopicId = topicid from MyMindTopicVisitor where visitorid = @visitoridLogged
declare @MMIV table
(
VisitorId int not null,
AuthorId varchar(17) not null,
MMIV decimal(6,4),
PRIMARY KEY(VisitorId, AuthorId)
)
declare @Universe table
(
GalaxyId int,
VisitorId int,
CoId varchar(20),
ObjType varchar(35),
ObjTitle varchar(255),
ObjFontSize tinyint,
ObjPosition tinyint
)
/* Get the most influencing authors for the visitor */
insert into @MMIV
select distinct top 5
vi.VisitorIdX,
vi.AuthorIdY,
vi.[value]
from
VisitorsInfluences vi
inner join
tblcontentobjects co on co.coid = vi.authoridy
where
vi.visitoridx = @visitorid
and co.visitorid <> @visitorid
and vi.[value] >= @threshold
group by
vi.VisitorIdX,
vi.AuthorIdY,
vi.[value]
order by
vi.[value] desc
/* Loop until MMIV is empty */
WHILE (select count(*) from @MMIV) > 0
BEGIN
select top 1
@FirstObj = authorid
from
@MMIV
order by
MMIV desc
--Insert the center object in the current galaxy
/* DEBUG: En esta query tenes que hacer lo mismo que te dije para la font. Chequear el valor de influencia para el visitorLogged
y dependiendo de ese valor setear el tamaño de fuente */
insert into @Universe
select
@GalaxyId,
tco.visitorid,
@FirstObj,
'Person',
tco.firstname + ' ' + tco.lastname,
case
when
(
select
[value]
from
visitorsinfluences vi
where
vi.visitoridx = @visitorIdLogged
and vi.authoridy = tco.coid
) >= 0.66
then 5
else
case
when
(
select
[value]
from
visitorsinfluences vi
where
vi.visitoridx = @visitorIdLogged
and vi.authoridy = tco.coid
) >= 0.33
then 3
else 1
end
end as font,
4
from
@MMIV mm
inner join
tblcontentobjects tco on tco.coid = mm.authorid
where
mm.authorid = @FirstObj
delete from @MMIV where authorid = @FirstObj
--Insert the cluster objects in the current galaxy
/* DEBUG: En esta query tenes que hacer lo que te dije para la font. Chequear el valor de influencia para el visitorLogged
y dependiendo de ese valor setear el tamaño de fuente */
**insert into @Universe
select top 5
@GalaxyId as galaxyid,
vi.visitoridx as visitoridx,
co.coid as coid,
'Person' as cotype,
co.firstname + ' ' + co.lastname as visitorname,
case
when
(
select
[value]
from
visitorsinfluences vi
where
vi.visitoridx = @visitorIdLogged
and vi.authoridy = co.coid
) >= 0.66
then 5
else
case
when
(
select
[value]
from
visitorsinfluences vi
where
vi.visitoridx = @visitorIdLogged
and vi.authoridy = co.coid
) >= 0.33
then 3
else 1
end
end as font,
case when vi.[value] >= 0.66 then 3 else case when vi.[value] >= 0.33 then 2 else 1 end end as position
from
VisitorsInfluences vi
inner join
tblcontentobjects co on vi.visitoridx = co.visitorid
left join
@universe u on u.coid = co.coid
left join
@mmiv mm on mm.authorid = co.coid
where
vi.authoridy = @FirstObj
and [value] >= convert(real,@threshold)
and vi.visitoridx <> @visitorid
--and vi.visitoridx not in (select visitorid from @Universe)
--and co.coid not in (select coid from @Universe)
--and co.coid not in (select authorid from @mmiv)
and u.coid is null
and mm.authorid is null
and u.visitorid is null
/*group by
vi.visitoridx,
co.coid,
v.firstname,
v.lastname,
case when vi.[value] = 1 then 5 else case when vi.[value] >= (@threshold / 2) then 3 else 1 end end,
case when vi.[value] >= 0.66 then 3 else case when vi.[value] >= 0.33 then 2 else 1 end end*/
order by
vi.[value] desc**
if ((select count(*) from @Universe where GalaxyId = @GalaxyId) = 1) and @GalaxyId <= 5
begin
insert into @Universe
select top 5
@GalaxyId as galaxyid,
-- convert(varchar, vi.visitoridx) as visitoridx,
vi.visitoridx as visitoridx,
co.coid as coid,
'Person' as cotype,
v.firstname + ' ' + v.lastname as visitorname,
0 as font,
case when vi.[value] >= 0.66 then 3 else case when vi.[value] >= 0.33 then 2 else 1 end end as position
from
VisitorsInfluences vi
inner join
tblvisitor v on v.visitorid = vi.visitoridx
inner join
tblcontentobjects co on v.visitorid = co.visitorid
left join
@universe u on u.coid = co.coid
left join
@mmiv mm on mm.authorid = co.coid
where
vi.authoridy=@FirstObj-- and vi.visitoridx = v.visitorid
and vi.visitoridx <> @visitorid
-- and convert(varchar, vi.visitoridx) not in (select objid from @Universe)
--and vi.visitoridx not in (select visitorid from @Universe)
--and co.coid not in (select coid from @Universe)
--and co.coid not in (select authorid from @mmiv)
and u.coid is null
and mm.authorid is null
and u.visitorid is null
order by
vi.[value] desc
end
-- delete from @MMIV where authorid in (select ObjId from @Universe)
delete from @MMIV where visitorid in (select visitorid from @Universe)
set @GalaxyId = @GalaxyId + 1
END
--Getting the XML output
select
@MainObjTitle = rtrim(ltrim(firstname)) + ' ' + ltrim(rtrim(lastname))
from
tblcontentobjects
where
visitorid = @visitorid
select
@CoId = co.coid
from
tblcontentobjects co
where
co.visitorid = @visitorid
SELECT
@MainObjTitle as '@MainObjTitle',
@CoId as '@CoId',
(
SELECT
s.GalaxyID AS [@Id],
(
SELECT
U.VisitorId AS [@VisitorId],
U.CoId AS [@CoId],
U.ObjType AS [@Type],
U.ObjTitle AS [Title],
U.ObjFontSize as [FontSize],
U.ObjPosition as [Position],
co.[role] as [Role],
co.Affiliation as [Org],
case when ctr.topicid is null then 0 else 1 end as [IsInMyMind],
isnull(imgs.coviewurllink, '') as [coPicture],
case
when co.visitorid is null then ''
when exists (
select *
from visitorrequests vrs
where vrs.RequestDate > dateadd(mi, -10, getdate()) and
vrs.visitorid = co.visitorid
) then '_online'
else '_offline'
end as [IsOnline],
case when mctr.topicid is null then 0 else 1 end as [HasSocialNetworkProfile]
FROM
@Universe AS U
inner join tblcontentobjects co
-- on convert(varchar, co.visitorid) = U.ObjId or co.coid = U.ObjId
on co.visitorid = U.VisitorId or co.coid = U.CoId
inner join tblvisitor v
on v.visitorid = co.visitorid
left join
(
select img.*, cir.coidb
from tblcointerrelations cir
inner join tblcontentobjects img
on img.coid = cir.coida
where img.cotype='images'
) imgs
on co.coid = imgs.coidb
left join tblCoTopicRelations ctr
on ctr.coid = co.coid and ctr.topicid = @MyMindTopicId
left join tblCoTopicRelations mctr
on mctr.coid = co.coid and mctr.topicid = @mindTopicId
WHERE
U.GalaxyID = s.GalaxyID
ORDER BY
U.ObjPosition DESC
FOR XML PATH('Object'), TYPE
)
FROM
(
SELECT GalaxyID
FROM @Universe
GROUP BY GalaxyID
) AS s
ORDER BY
GalaxyId
FOR XML PATH('Galaxy'), TYPE
)
FOR XML PATH('Universe')`
答案 0 :(得分:4)
似乎有很多东西可供选择来解释存储过程缓慢的原因。这是一些想法。
您需要查看执行计划并寻找高额费用。对过程进行小的更改,并比较之前和之后的执行计划,以查看更改如何影响性能。做基准。知道你从哪里开始,你就可以衡量你走了多远。
运行此语句,然后运行该过程 SET STATISTICS IO ON 走 查看结果,对于每个触摸的表,请查看“逻辑读取”。具有最高逻辑读取的那些需要您的注意。它们可以松散地转换为对该对象的索引的需求。
答案 1 :(得分:2)
首先我输了:
while (select count(*) from @mmiv) > 0
并将其替换为:
declare @temp_count int
select @temp_count = count(*) from @mmiv
while @temp_count > 0
以下是从@mmiv删除记录的地方:
select @temp_count = (@temp_count - 1)
这样可以减少开销,因为每次循环执行序列时都不会执行count()。您还可以考虑将一些具有多个联接的选择放入视图中, here is why 。
答案 2 :(得分:0)
感谢各位的回答。
我终于解决了它。问题是缺少索引(例如在值字段上),现在效果很好。
谢谢,
布赖恩