SQL Server 2005 Volltextsuche Forum
-
03-07-2019 - |
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
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.