我有一个表,其中包含UserIds到磁盘上某些路径(例如\\UNCserver\path或C:\user\has\a\folder)的映射。我控制数据,数据库中没有尾随的\符号。
定期地,我需要选择具有指定路径的父路径的用户in。例如,如果我在\\superserver\cluster\2中有一个事件,我希望获得所有具有以下任一或全部路径的用户ID:
\\superserver\cluster\2
\\superserver\cluster
\\superserver我有一个存储过程就是这样做的,但由于我使用的字符串上的操作效率极低--仅对10000条UserPaths记录,我就可以将CPU加载到50%,只连续调用几百次。
我如何优化这个程序?
CREATE PROCEDURE [dbo].[SelectUserIdsWithPath]
@Path nvarchar(MAX)
AS
BEGIN
SET NOCOUNT ON;
IF (@Path IS NOT NULL)
BEGIN
DECLARE @TempPath NVARCHAR(MAX)
SET @TempPath = SUBSTRING(@Path, 0, LEN(@Path) + 1 - CHARINDEX('\', REVERSE(@Path)))
IF (LEN(@Path) - LEN(REPLACE(@Path, '\', '')) = 1) --we need to process path C:\
BEGIN
SET @TempPath = @TempPath + '\';
END
INSERT INTO Results(UserId)
SELECT DISTINCT UserId FROM UserPaths
WHERE
UserId NOT IN (SELECT UserId FROM Results)
AND (Path = @Path
OR CHARINDEX(Path, @TempPath, 0) <> 0)
END
END更新我现在已经改变了我的应用程序中的逻辑,以便在应用程序中完成父路径的计算,这可能改进了一些东西,但是性能仍然很差。下面是更新的proc清单:
CREATE PROCEDURE [dbo].[SelectUserIdsWithPath]
@Path NVARCHAR(MAX),
@ParentPath NVARCHAR(MAX)
AS
BEGIN
SET NOCOUNT ON;
IF (@Path IS NOT NULL AND @ParentPath IS NOT NULL)
BEGIN
INSERT INTO Results(UserId)
SELECT DISTINCT UserId FROM UserPaths
WHERE
UserId NOT IN (SELECT UserId FROM Results)
AND (Path = @Path
OR CHARINDEX(Path, @ParentPath, 0) <> 0)
END
END所以罪魁祸首显然是CHARINDEX()呼叫。不幸的是,我仍然在等待基础设施来确认我们是否可以打开全文索引,但是还有其他的选择吗?
发布于 2014-03-09 06:38:09
也许使用cte来提取父文件夹。就像这样:
create procedure SelectUserIdsWithPath
@path varchar(250)
as begin
With c
As
(Select cast(path as varchar(500)) path
from (Select @path path) t
Union all select
Cast(substring(path,0,len(path)-charindex('\',reverse(path),0)+1) as varchar(500))
From c
where charindex('\',reverse(substring(path,0,len(path)-charindex('\',reverse(path),0)+1) ),0)>1)
Select distinct userid from userpaths up where exists(select * from c where c.path=up.path)
endhttps://stackoverflow.com/questions/22267574
复制相似问题