Frage

Ich bin auf der Suche gespeicherte Prozedur für unsere bestehenden Foren.

Ich habe den folgenden Code geschrieben, die Standard-SQL-Volltextindizes verwendet, aber ich bin sicher, dass es einen besseren Weg, es zu tun und würde einen Punkt in die richtige Richtung mögen.

einigen Informationen zu geben, wie es arbeiten muß, Die Seite hat ein Suchfeld, die angeklickt, wenn Thread Titel suchen, fade Beschreibungen und Post Text und soll die Ergebnisse zurück mit dem Titel zuerst übereinstimmt, dann Beschreibungen dann Daten schreiben .

Im Folgenden finden Sie, was ich bisher geschrieben habe, das funktioniert aber nicht elegant oder so schnell wie ich möchte. Um ein Beispiel für die Leistung mit 20K Fäden zu geben und 80K Beiträgen dauert es etwa 12 Sekunden für 5 zufällige Worte zu suchen.

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

Ich weiß, es ist ein bisschen langatmig, sondern nur ein Schub in der richtigen Richtung wäre gut geschätzt.

Incase es 80% der Abfragezeit hilft aufgenommen wird, wenn Such Beiträge und nach teh Abfrage-Plan auf „Clustered Index Scan“ auf den Beiträgen Tabelle ausgegeben wird. Ich kann sowieso um dies sehen.

Danke

Gavin

War es hilfreich?

Lösung

Ich muß wirklich einen Plan sehen erklären zu wissen, wo die langsamen Teile waren, als ich nichts besonders böse in Ihrem Code sehen. Sehr erste Sache -. Sicherstellen, dass alle Ihre Indizes in guter Form sind, werden sie verwendet, Statistiken auf dem neuesten Stand sind, etc

Eine andere Idee wäre es, die Suche auf Thread-Titel zu tun, zuerst, dann die Ergebnisse verwenden aus, dass die Durchsuchung auf Diskussionsthema und nach Text zu beschneiden. In ähnlicher Weise die Ergebnisse der Diskussionsthema-Suche, um die Post Textsuche zu beschneiden.

Die Grundidee dabei ist, dass, wenn Sie die Keywords in dem Thread-Titel finden, warum die Beschreibung und Beiträge plagt die Suche? Ich weiß, dies nicht funktionieren kann, je nachdem, wie Sie die Suchergebnisse den Benutzer präsentieren, und es kann nicht einen großen Unterschied machen, aber es ist etwas zu denken.

Andere Tipps

80k Datensätze ist nicht so viel. Ich würde empfehlen, die resultierenden Daten in der temporären Tabelle nicht einfügen, und stattdessen nur die IDs einfügen, dann später an diesen Tisch verbindet. Dies wird sich auf das Schreiben auf die temporäre Tabelle speichern, wie Sie 10000 Ints speichern, statt 10000 vollen Beiträge (von denen Sie verwerfen alle bis auf eine Seite von). Dies kann die Menge Zeit damit verbracht, Scan-Beiträge reduzieren, wie gut.

Es sieht aus wie Sie zwei temporäre Tabellen benötigen würde, eine für Themen und eine für Beiträge. Sie würden Vereinigung sie im Finale wählen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top