it-swarm.com.de

Ist es besser, eine große Abfrage in mehrere kleinere Abfragen zu unterteilen?

Es gibt Situationen, in denen eine wirklich große Abfrage erforderlich ist, um mehrere Tabellen mit Unterauswahlanweisungen zu verknüpfen, um die gewünschten Ergebnisse zu erzielen.

Meine Frage ist, sollten wir in Betracht ziehen, mehrere kleinere Abfragen zu verwenden und die logischen Operationen in die Anwendungsschicht zu bringen, indem wir die Datenbank in mehr als einem Aufruf abfragen, oder ist es besser, sie alle auf einmal zu haben?
Betrachten Sie beispielsweise die folgende Abfrage:

SELECT *
FROM   `users`
WHERE  `user_id` IN (SELECT f2.`friend_user_id`
                     FROM   `friends` AS f1
                            INNER JOIN `friends` AS f2
                              ON f1.`friend_user_id` = f2.`user_id`
                     WHERE  f2.`is_page` = 0
                            AND f1.`user_id` = "%1$d"
                            AND f2.`friend_user_id` != "%1$d"
                            AND f2.`friend_user_id` NOT IN (SELECT `friend_user_id`
                                                            FROM   `friends`
                                                            WHERE  `user_id` = "%1$d"))
       AND `user_id` NOT IN (SELECT `user_id`
                             FROM   `friend_requests`
                             WHERE  `friend_user_id` = "%1$d")
       AND `user_image` IS NOT NULL
ORDER  BY Rand() 
LIMIT %2$d

Was ist der beste Weg, es zu tun?

13
Hamed Momeni

Ich werde hier bei großen und komplizierten Fragen mit datagod nicht einverstanden sein. Ich sehe diese nur als Probleme, wenn sie unorganisiert sind. In Bezug auf die Leistung sind diese fast immer besser, da der Planer viel mehr Freiheit beim Abrufen der Informationen hat. Große Abfragen müssen jedoch unter Berücksichtigung der Wartbarkeit geschrieben werden. Im Allgemeinen habe ich festgestellt, dass einfaches, gut strukturiertes SQL auch dann einfach zu debuggen ist, wenn eine einzelne Abfrage für mehr als 200 Zeilen ausgeführt wird. Dies liegt daran, dass Sie normalerweise eine ziemlich gute Vorstellung davon haben, mit welcher Art von Problem Sie sich befassen, sodass die Abfrage nur wenige Bereiche enthält, die Sie überprüfen müssen.

Die Wartungsprobleme, IME, treten auf, wenn die Struktur von SQL zusammenbricht. Lange, komplexe Abfragen in Unterauswahlen beeinträchtigen die Lesbarkeit und Fehlerbehebung ebenso wie Inline-Ansichten. Beides sollte bei langen Abfragen vermieden werden. Verwenden Sie stattdessen VIEWs, wenn Sie können (beachten Sie, dass Ansichten unter MySQL nicht so gut funktionieren, bei den meisten anderen DBs jedoch) und verwenden Sie allgemeine Tabellenausdrücke, bei denen diese nicht funktionieren (MySQL unterstützt diese nicht) übrigens).

Lange komplexe Abfragen funktionieren sowohl in Bezug auf die Wartbarkeit als auch in Bezug auf die Leistung recht gut, wenn Sie Ihre where-Klauseln einfach halten und wenn Sie so viel wie möglich mit Verknüpfungen anstelle von Unterauswahlen tun. Das Ziel ist es, es so zu gestalten, dass "Datensätze nicht angezeigt werden", dass Sie einige sehr spezifische Stellen in der Abfrage haben, die überprüft werden müssen (wird es in einem Join gelöscht oder in einer where-Klausel herausgefiltert?) Und damit das Wartungsteam kann tatsächlich Dinge pflegen.

Beachten Sie in Bezug auf die Skalierbarkeit, dass dies auch eine gute Sache ist, je flexibler der Planer ist.

Bearbeiten: Sie erwähnen, dass dies MySQL ist, sodass Ansichten wahrscheinlich nicht so gut funktionieren und CTEs nicht in Frage kommen. Außerdem ist das angegebene Beispiel nicht besonders lang oder komplex, sodass dies kein Problem darstellt.

14
Chris Travers

Als jemand, der diese großen und komplizierten Abfragen unterstützen/bereinigen muss, würde ich sagen, dass es weitaus besser ist, sie in mehrere kleine, leicht verständliche Teile aufzuteilen. Aus Sicht der Leistung ist es nicht nbedingt besser, aber Sie geben SQL zumindest eine bessere Chance, einen guten Abfrageplan zu erstellen.

Machen Sie den Menschen, die Ihnen folgen, das Leben leichter, und sie werden gute Dinge über Sie sagen. Mach es ihnen schwer und sie werden dich verfluchen.

8
datagod

Meine 2 Cent für die 2 Schlüsselwörter Abfrageleistung und Skalierbarkeit:

Abfrageleistung : Die SQL Server-Parallelität leistet bereits sehr gute Arbeit, indem Abfragen in Multithread-Suchvorgänge unterteilt werden. Daher bin ich mir nicht sicher, wie stark sich die Abfrageleistung verbessern wird, wenn Sie dies tun SQL Server. Sie müssen sich den Ausführungsplan ansehen, um festzustellen, wie viel Parallelität Sie erhalten, wenn Sie ihn ausführen, und die Ergebnisse in beide Richtungen vergleichen. Wenn Sie am Ende einen Abfragehinweis verwenden müssen, um die gleiche oder eine bessere Leistung zu erzielen, lohnt es sich IMO nicht, da der Abfragehinweis später möglicherweise nicht optimal ist.

Skalierbarkeit : Das Lesen der Abfragen ist möglicherweise einfacher, wie vom Datagod angegeben, und es ist sinnvoll, sie in separate Abfragen aufzuteilen, wenn Sie Ihre neuen Abfragen auch in anderen Bereichen verwenden können, diese aber nicht verwenden möchten Auch für andere Aufrufe werden noch mehr gespeicherte Prozesse für eine Aufgabe verwaltet, und IMO würde keinen Beitrag zur Skalierbarkeit leisten.

5
Ali Razeghi

Manchmal bleibt keine andere Wahl, als die große/komplexe Abfrage in kleine Abfragen aufzuteilen. Der beste Weg, dies festzustellen, besteht darin, die Anweisung EXPLAIN mit der Anweisung SELECT zu verwenden. Die Anzahl der Traces/Scans, die Ihre Datenbank zum Abrufen Ihrer Daten erstellen wird, ist das Produkt der von Ihrer EXPLAIN -Abfrage zurückgegebenen "Zeilen" -Werte. In unserem Fall hatten wir eine Abfrage, die 10 Tabellen verband. Für einen bestimmten Datensatz betrug die Ablaufverfolgung 409 Millionen, die unsere Datenbank bloggten und die CPU-Auslastung unseres DB-Servers um über 300% erhöhten. Wir konnten die gleichen Informationen abrufen, indem wir die Abfragen viel schneller aufteilten.

Kurz gesagt, in einigen Fällen ist die Aufteilung einer komplexen/großen Abfrage sinnvoll, in anderen Fällen kann dies jedoch zu vielen Leistungs- oder Wartbarkeitsproblemen führen, und dies sollte von Fall zu Fall behandelt werden.

2
user140665