Pergunta

Eu estou trabalhando em um procedimento de busca armazenados para os nossos fóruns existentes.

Eu escrevi o seguinte código que usa índices de texto completo SQL padrão, porém tenho certeza que estou há uma maneira melhor de fazê-lo e gostaria de um ponto na direção certa.

Para dar algumas informações sobre como ele precisa funcionar, a página tem caixa de 1 pesquisa de texto que quando clicado irá procurar títulos de rosca, descrições de linha e texto post e deve retornar os resultados com o título corresponde em primeiro lugar, em seguida, descrições, em seguida, postar dados .

Abaixo está o que eu escrevi até agora, que funciona, mas não é elegante ou tão rápido quanto eu gostaria. Para dar um exemplo de desempenho com 20K fios e 80K mensagens que leva cerca de 12 segundos para procurar 5 palavras aleatórias.

ALTER PROCEDURE [dbo].[SearchForums]
(
    --Input Params
    @SearchText VARCHAR(200),
    @GroupId INT = -1,
    @ClientId INT,
    --Paging Params
    @CurrentPage INT,
    @PageSize INT,           
    @OutTotalRecCount INT OUTPUT
)
AS

--Create Temp Table to Store Query Data
CREATE TABLE #SearchResults
(
    Relevance INT IDENTITY,
    ThreadID INT,
    PostID INT,
    [Description] VARCHAR(2000),
    Author BIGINT
)

--Create and populate table of all GroupID's This search will return from
CREATE TABLE #GroupsToSearch
(
GroupId INT
)
IF @GroupId = -1
    BEGIN
        INSERT INTO #GroupsToSearch
        SELECT GroupID FROM SNetwork_Groups WHERE ClientId = @ClientId
    END
ELSE
    BEGIN
        INSERT INTO #GroupsToSearch
        VALUES(@GroupId)
    END

--Get Thread Titles
INSERT INTO #SearchResults
    SELECT 
        SNetwork_Threads.[ThreadId],
        (SELECT NULL) AS PostId,
        SNetwork_Threads.[Description],
        SNetwork_Threads.[OwnerUserId]
    FROM 
        SNetwork_Threads
        INNER JOIN SNetwork_Groups ON SNetwork_Groups.GroupId = SNetwork_Threads.GroupId        
    WHERE 
        FREETEXT(SNetwork_Threads.[Description], @SearchText) AND
        Snetwork_Threads.GroupID IN (SELECT GroupID FROM #GroupsToSearch) AND
        SNetwork_Groups.ClientId = @ClientId


--Get Thread Descriptions
INSERT INTO #SearchResults
    SELECT 
        SNetwork_Threads.[ThreadId],
        (SELECT NULL) AS PostId,
        SNetwork_Threads.[Description],
        SNetwork_Threads.[OwnerUserId]
    FROM 
        SNetwork_Threads
        INNER JOIN SNetwork_Groups ON SNetwork_Groups.GroupId = SNetwork_Threads.GroupId        
    WHERE 
        FREETEXT(SNetwork_Threads.[Name], @SearchText) AND
        Snetwork_Threads.GroupID IN (SELECT GroupID FROM #GroupsToSearch) AND
        SNetwork_Groups.ClientId = @ClientId


--Get Posts
INSERT INTO #SearchResults
    SELECT 
        SNetwork_Threads.ThreadId,
        SNetwork_Posts.PostId,
        SNetwork_Posts.PostText,
        SNetwork_Posts.[OwnerUserId]
    FROM 
        SNetwork_Posts 
        INNER JOIN SNetwork_Threads ON SNetwork_Threads.ThreadId = SNetwork_Posts.ThreadId
        INNER JOIN SNetwork_Groups ON SNetwork_Groups.GroupId = SNetwork_Threads.GroupId        
    WHERE 
        FREETEXT(SNetwork_Posts.PostText, @SearchText) AND
        Snetwork_Threads.GroupID IN (SELECT GroupID FROM #GroupsToSearch) AND
        SNetwork_Groups.ClientId = @ClientId


--Return Paged Result Sets
SELECT @OutTotalRecCount =  COUNT(*) FROM #SearchResults
SELECT  
    #SearchResults.[ThreadID],
    #SearchResults.[PostID],
    #SearchResults.[Description],
    #SearchResults.[Author]
FROM  
    #SearchResults          
WHERE  
    #SearchResults.[Relevance] >= (@CurrentPage - 1) * @PageSize + 1 AND 
    #SearchResults.[Relevance] <= @CurrentPage*@PageSize
ORDER BY Relevance ASC


--Clean Up
DROP TABLE #SearchResults
DROP TABLE #GroupsToSearch

Eu sei que é um pouco prolixo, mas apenas uma cutucada na direção certa seria bem apreciado.

Incase ajuda de 80% do tempo de consulta é retomada quando a busca de mensagens e de acordo com teh plano de consulta é gasto em "Clustered Index Scan" na tabela de mensagens. Eu não posso ver qualquer maneira de contornar isso.

Graças

Gavin

Foi útil?

Solução

Eu realmente tenho que ver um plano de saber onde as partes lentas foram explicar, como eu não vejo nada de particularmente desagradável em seu código. Muito primeira coisa - garantir que todos os seus índices estão em boa forma, eles estão sendo usados, as estatísticas estão atualizados, etc

.

Uma outra idéia seria fazer a pesquisa no título do thread em primeiro lugar, em seguida, usar os resultados do que para podar as buscas na descrição da linha e texto post. Da mesma forma, usar os resultados da pesquisa descrição thread para podar a pesquisa pós texto.

A idéia básica aqui é que se você encontrar as palavras-chave no título fio, por que se preocupar pesquisando na descrição e mensagens? Sei que isso pode não funcionar, dependendo de como você está apresentando os resultados da pesquisa para o usuário, e ele não pode fazer uma diferença enorme, mas é algo para se pensar.

Outras dicas

80k registros que não é muito. Eu recomendo não inserir os dados resultantes em sua tabela temporária e, em vez única inserir os IDs, então se juntar a essa tabela depois. Isto vai poupar em escrever para a tabela temporária, como você pode armazenar 10000 ints, em vez de 10000 mensagens completas (dos quais você descartar tudo, mas uma página de). Isto pode reduzir a quantidade de tempo gasto mensagens de digitalização, bem.

Parece que você precisaria de duas tabelas temporárias, um para tópicos e outro para mensagens. Você faria união los no seleto final.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top