9 Stimmen

Ist Rekursion in SQL Server gut?

Ich habe eine Tabelle in SQL Server, die die normale Baumstruktur von Item_ID, Item_ParentID hat. Angenommen, ich möchte alle KINDER eines bestimmten Item_ID (auf jeder Ebene) durchlaufen und abrufen.

Rekursion scheint ein intuitiver Kandidat für dieses Problem zu sein, und ich kann eine SQL Server-Funktion schreiben, um dies zu tun.

Wird sich die Leistung beeinträchtigen, wenn meine Tabelle sehr viele Datensätze enthält? Wie kann ich Rekursion vermeiden und einfach die Tabelle abfragen? Bitte um Vorschläge?

5voto

Ilya Kochetov Punkte 17577

Mit dem neuen MS SQL 2005 könnten Sie das WITH-Schlüsselwort verwenden

Schauen Sie sich diese Frage und insbesondere diese Antwort an.

Mit Oracle könnten Sie das CONNECT BY-Schlüsselwort verwenden, um hierarchische Abfragen zu generieren (Syntax).

Soweit ich weiß, müssen Sie mit MySQL die Rekursion verwenden.

Alternativ könnten Sie immer eine Cache-Tabelle für die Eltern-Kind-Beziehungen Ihrer Datensätze erstellen

2voto

Im Allgemeinen ist es möglich, mit SQL Server einige ziemlich ausgefeilte Dinge zu tun, die normalerweise Rekursion erfordern, einfach durch Verwendung eines iterativen Algorithmus. Mir ist es gelungen, einen XHTML-Parser in Transact SQL zu erstellen, der überraschend gut funktionierte. Der von mir geschriebene Code-Verfeinerer wurde in einer gespeicherten Prozedur erstellt. Es ist nicht elegant, es ist eher wie Büffel beim Ballett zuzusehen. aber es funktioniert.

1voto

AlexCuse Punkte 17778

Verwenden Sie SQL 2005?

Wenn ja, können Sie Common Table Expressions dafür verwenden. In etwa so:

;
with CTE (Some, Columns, ItemId, ParentId) as 
(
    select Some, Columns, ItemId, ParentId
    from myTable 
    where ItemId = @itemID
    union all
    select a.Some, a.Columns, a.ItemId, a.ParentId
    from myTable as a
    inner join CTE as b on a.ParentId = b.ItemId
    where a.ItemId <> b.ItemId
)
select * from CTE

1voto

jjacka Punkte 513

Das Problem, dem Sie bei Rekursion und Leistung gegenüberstehen werden, ist, wie viele Male sie rekursiv sein müssen, um die Ergebnisse zurückzugeben. Jeder rekursive Aufruf ist ein weiterer separater Aufruf, der in die Gesamtergebnisse einbezogen werden muss.

In SQL 2k5 können Sie eine CTE verwenden, um diese Rekursion zu behandeln:

WITH Managers AS 
( 
--initialization 
SELECT EmployeeID, LastName, ReportsTo  
FROM Employees 
WHERE ReportsTo IS NULL 
UNION ALL 
--recursive execution 
SELECT e.employeeID,e.LastName, e.ReportsTo 
FROM Employees e INNER JOIN Managers m  
ON e.ReportsTo = m.employeeID 
) 
SELECT * FROM Managers  

Oder eine andere Lösung ist, die Hierarchie in eine andere Tabelle zu überführen.

Employee_Managers
ManagerId (PK, FK für Employee-Tabelle)
EmployeeId (PK, FK für Employee-Tabelle)

Alle Eltern-Kind-Beziehungen werden in dieser Tabelle gespeichert, so dass, wenn Manager 1 Manager 2 Mitarbeiter 3 verwaltet, die Tabelle wie folgt aussieht:

ManagerId EmployeeId
1         2
1         3
2         1

Dies ermöglicht es, die Hierarchie einfach abzufragen:

select * from employee_managers em 
inner join employee e on e.employeeid = em.employeeid and em.managerid = 42

Das würde alle Mitarbeiter zurückgeben, die Manager 42 haben. Der Vorteil wird eine höhere Leistung sein, aber der Nachteil wird die Wartung der Hierarchie sein

1voto

Tom H Punkte 45699

Joe Celko hat ein Buch (<- Link zu Amazon) speziell über Baumstrukturen in SQL-Datenbanken. Obwohl Sie Rekursion für Ihr Modell benötigen und es definitiv potenzielle Leistungsprobleme gibt, gibt es alternative Möglichkeiten, eine Baumstruktur je nachdem, was Ihr spezifisches Problem beinhaltet, zu modellieren, die Rekursion vermeiden und bessere Leistung bieten könnten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X