0

もっと効率的にしたい機能があります。コストの大部分はインデックスを探すことにあることを私は知っています。これら2つのインデックスシークを1つにマージする方法があるかどうか知りたいです。

これが私の機能です

ALTER FUNCTION [dbo].[Search]
(
    @Query nvarchar(150)        
)
RETURNS @result TABLE 
(
    ID int,
    ResultPhrase nvarchar(max),
    Domain nvarchar(50)
)
AS

BEGIN

declare  @id int,
         @OffsetArticle nvarchar(50),
         @OffsetProfile nvarchar(50),
         @index int,
         @domain nvarchar(50),
         @StringResult nvarchar(max),
         @substrIndex int,
         @substrCount int,
         @field nvarchar(40),
         @begin int,
         @end int

        DECLARE pidCursor CURSOR FAST_FORWARD
        FOR select id,OffsetArticle,OffsetProfile from PerfTest where contains (data,@Query)

        open pidCursor
        FETCH NEXT FROM pidCursor INTO @id,@OffsetArticle,@OffsetProfile

        while (@@FETCH_STATUS = 0)
        begin

        select @index = CHARINDEX(@Query,data) from PerfTest where ID=@id

        exec @domain =  dbo.FindDomain @id=@id ,@index=@index, @offsetArticle=@OffsetArticle, @offsetProfile=@OffsetProfile


        if(@domain = N'Profile')
            set @end = SUBSTRING(@offsetProfile,CHARINDEX(N'-',@offsetProfile)+1,len(@offsetProfile)-CHARINDEX(N'-',@offsetProfile))
            set @begin = SUBSTRING(@offsetProfile,1,CHARINDEX(N'-',@offsetProfile)-1)

        if(@domain = N'Article')
            set @end = SUBSTRING(@OffsetArticle,CHARINDEX(N'-',@OffsetArticle)+1,len(@OffsetArticle)-CHARINDEX(N'-',@OffsetArticle))
            set @begin = SUBSTRING(@OffsetArticle,1,CHARINDEX(N'-',@OffsetArticle)-1)



        if(@index - 20 < CAST(@begin as int))
            set @substrIndex = @index
        else
            set @substrIndex = @index - 20

        if(@index + 150 > CAST(@end as int))
            set @substrCount = @end
        else
            set @substrCount = @index + 150 


        select @StringResult = SUBSTRING(data,@substrIndex,@substrCount) from PerfTest where ID=@id

        insert @result (id,ResultPhrase,Domain) values (@id,@StringResult,@domain)


        if(@@FETCH_STATUS = 0)
            FETCH NEXT FROM pidCursor INTO @id,@OffsetArticle,@OffsetProfile

        end
        CLOSE pidCursor
        DEALlOCATE pidCursor

RETURN      
END
4

2 に答える 2

0

含む

  CHARINDEX(@Query,data)

ループ内で最初に計算するのではなく、カーソルで。これにより、シークの約半分が削減されるはずです。シークは SQL Server の最も効率的なアクセス方法ですが、シークの半分をなくしても、クエリは役に立ちます。

カーソルにデータを含め、その値を使用して @StringResult を計算することもできます。それが役立つかどうかは、データ列の平均サイズに大きく依存します。それが十分に小さい場合は、物事を大幅に高速化する必要があります。「十分に小さい」とは、多くのことに依存しているため、試してみてください。データが VARCHAR(1000) である場合は、カーソルでそれを引っ張るのに役立つ可能性が最も高くなりますが、平均長が 2 MB の VARCHAR(MAX) である場合は、問題になる可能性が最も高くなります。

最後に、Pete が述べたように、最善の解決策はこれをセットベースの方法で記述することですが、単一の select ステートメント内からストアド プロシージャを呼び出すことはできないため、より複雑になる可能性があります。

于 2012-10-20T19:36:02.887 に答える