2010-07-28 4 views
26

Die Komplexität von Methoden in den meisten Programmiersprachen kann in zyklomatischer Komplexität mit statischen Quellcodeanalysatoren gemessen werden. Gibt es eine ähnliche Metrik zur Messung der Komplexität einer SQL-Abfrage?Messung der Komplexität von SQL-Anweisungen

Es ist einfach genug, um die Zeit zu messen, die eine Abfrage benötigt, um zurückzukehren, aber was, wenn ich nur in der Lage sein möchte zu quantifizieren, wie kompliziert eine Abfrage ist?

[Bearbeiten/Hinweis] Während der Ausführungsplan ist nützlich, das ist nicht unbedingt, was ich in diesem Fall zu identifizieren versuche. Ich suche nicht, wie schwierig es für den Server ist, die Abfrage auszuführen, ich suche nach einer Metrik, die angibt, wie schwierig es für den Entwickler war, die Abfrage zu schreiben, und wie wahrscheinlich es ist, einen Fehler zu enthalten.

[Edit/Note 2] Zugegebenermaßen gibt es Zeiten, in denen die Messung der Komplexität nicht sinnvoll ist, aber es gibt auch Zeiten, in denen dies der Fall ist. Weitere Informationen zu diesem Thema finden Sie unter this question.

+3

Ist es die Komplexität des Quellcodes oder die Komplexität der Verarbeitung, die Sie benötigen, die Sie messen möchten? –

+1

Ich frage mich, ob es einen Weg gibt, die Komplexität des Quellcodes zu messen. Mit C#/C++/Java habe ich oft Cyclomatic Complexity verwendet, um zu bestimmen, welche Methoden zuerst getestet werden sollten. Hier würde ich gerne wissen, welche Quests die meiste Aufmerksamkeit von Test benötigen. – epotter

+0

Haben Sie vor, unsere 'VIEW'-Definitionen in Abfragen zu erweitern? Ist die Verwendung einer benutzerdefinierten SQL-Funktion für den Code weniger komplex oder muss die Definition auch erweitert werden? – onedaywhen

Antwort

9

Gemeinsame Maße der Softwarekomplexität sind Cyclomatic Complexity (ein Maß dafür, wie kompliziert der Kontrollfluss ist) und Halstead complexity (ein Maß für die Komplexität der Arithmetik).

Der "Kontrollfluss" in einer SQL-Abfrage bezieht sich am besten auf die Operatoren "and" und "or" in der Abfrage.

Die "Rechenkomplexität" bezieht sich am besten auf Operatoren wie SUM oder implizite JOINS.

Sobald Sie entschieden haben, wie Sie jede Syntaxeinheit einer SQL-Abfrage kategorisieren, ob es sich um "Kontrollfluss" oder "Berechnung" handelt, können Sie direkt Cyclomatic- oder Halstead-Messungen berechnen.

Was der SQL-Optimierer mit Abfragen tut denken ist absolut irrelevant. Der Zweck von Komplexitätsmaßnahmen besteht darin, zu charakterisieren, wie schwer es für eine Person ist, die Abfrage zu verstehen, und nicht, wie effizient sie bewertet werden kann.

In ähnlicher Weise sollte das, was die DDL sagt oder ob Views involviert sind oder nicht, nicht in solche Komplexitätsmaßnahmen einbezogen werden. Die Annahme hinter diesen Metriken ist, dass die Komplexität von Maschinerie innerhalb einer gebrauchten Abstraktion nicht interessant ist, wenn man sie einfach aufruft, weil vermutlich diese Abstraktion etwas, was der Kodierer gut versteht. Das ist der Grund, warum Halstead- und Cyclomatic-Messungen keine aufgerufenen Subroutinen in ihrer Zählung enthalten, und ich denke, Sie können einen guten Fall machen, dass Ansichten und DDL-Informationen diese "aufgerufenen" Abstraktionen sind.

Schließlich, wie perfekt richtig oder wie falsch diese Komplexitätszahlen sind, spielt keine große Rolle, solange sie etwas Wahrheit über die Komplexität widerspiegeln und man sie relativ zueinander vergleichen kann. Auf diese Weise können Sie auswählen, welche SQL-Fragmente die komplexesten sind, also sortieren Sie sie alle und konzentrieren Sie sich auf die komplexesten Tests.

+0

Soweit Sie wissen, gibt es ein solches Tool? – epotter

+0

Nun, irgendwie ja. Meine Firma bietet eine Source Code Search Engine (SCSE) (http://www.semanticdesigns.com/Products/SearchEngine) an, die eine Reihe von Dateien scannt, um einen Index für die Suche vorzubereiten. Die SCSE berechnet während des Scans eine Reihe einfacher Metriken (SLOC, CommentCount, Cyclomatic, Halstead) über jede Datei als Ganzes * und * verarbeitet viele Sprachen, einschließlich PLSQL. PLSQL hat natürlich SQL als Subsprache, und IIRC, SCSE berechnet Software-Komplexität-Zahlen so ziemlich wie ich oben beschrieben habe. Wenn Sie Ihre SQL-Fragmente in Dateien einfügen, würde der SCSE das wahrscheinlich tun. –

+0

... Es gibt immer die Frage von * wo sind Ihre SQL-Fragmente? * Wenn sie in String-Fragmente in ODBC-Aufrufe eingebettet sind, wird es schwierig sein, sie zu extrahieren und zu messen, weil die Teile über den Code verstreut sind Es ist nicht sofort offensichtlich, dass ein bestimmtes String-Literal Teil einer Abfrage ist oder, wenn ja, wohin es geht. Wenn Ihre SQL-Abfragen in Stored Procedure-Sprache wie PLSQL eingebettet sind, sind sie offensichtlich viel einfacher zu extrahieren. Aber in diesem Fall ist das ideale Werkzeug, das die SQL-Abfragen separat in situ misst, so dass Sie sie nicht manuell extrahieren oder hacken müssen. –

1

SQL-Abfragen sind eher deklarativ als prozedural: Sie geben nicht an, wie sie ihr Ziel erreichen sollen. Die SQL-Engine erstellt einen prozeduralen Angriffsplan, und das ist ein guter Ort, um nach Komplexität zu suchen. Versuchen Sie, die Ausgabe der Anweisung EXPLAIN (oder EXPLAIN PLAN) zu untersuchen, es wird eine grobe Beschreibung der Schritte sein, die die Engine zum Ausführen Ihrer Abfrage verwendet.

+0

"SQL-Abfragen sind eher deklarativ als prozedural" - weshalb Sie die SQL-DML nicht isoliert von der SQL-DDL betrachten können. – onedaywhen

+0

Im Prinzip könnte dann die zyklomatische Komplexität für einen Ausführungsplan berechnet werden, wodurch indirekt die Komplexität der SQL-Quelle, die sie erzeugt hat, gemessen werden kann. Das Problem ist, dass Ausführungspläne typischerweise eine Verschmelzung sind, die die Ausführung enthält, die von allen "Unterroutinen" (in diesem Fall Ansichten, Tabellenwertfunktionen usw.) beschrieben wird, so dass dies auch nicht funktionieren würde! – redcalx

0

Nun, wenn Sie SQL Server verwenden, würde ich sagen, dass Sie die Kosten der Abfrage im Ausführungsplan (insbesondere die Teilbaumkosten) betrachten sollten.

Here ist ein Link, der einige der Dinge durchgeht, die Sie im Ausführungsplan betrachten sollten.

0

Abhängig von Ihrem RDBMS können Abfrageplan-Tools Ihnen helfen, die Schritte zu analysieren, die das RDBMS beim Abrufen Ihrer Abfrage ausführen wird.

SQL Server Management Studio Express verfügt über einen integrierten Abfrageausführungsplan. Pervasive PSQL hat seinen Abfrageplan-Finder. DB2 verfügt über ähnliche Tools (vergessen, wie sie heißen).

0

Eine gute Frage. Das Problem ist, dass für eine SQL-Abfrage wie:

SELECT * FROM foo; 

die Komplexität abhängen kann auf das, was „foo“ ist und auf der Datenbank-Implementierung. Für eine Funktion wie:

int f(int n) { 
    if (n == 42) { 
     return 0; 
    } 
    else { 
     return n; 
    } 
} 

gibt es keine solche Abhängigkeit.

Aber ich denke, es sollte möglich sein, einige nützliche Metriken für eine SELECT zu finden, auch wenn sie nicht sehr genau sind, und ich werde interessiert sein zu sehen, welche Antworten das bekommt.

+1

Ich bin etwas anderer Meinung über das 'foo' Beispiel. Das wäre vergleichbar mit der Komplexität der aufgerufenen Funktionen, wenn man die Komplexität eines prozeduralen Codes misst. – pascal

+0

Einverstanden. Die zyklomatische Komplexität beispielsweise sagt Ihnen über die Anzahl der möglichen Pfade durch einen Abschnitt des Quellcodes aus und berechnet im normalen Gebrauch nicht die zusätzlichen Teilpfade mit Unterroutinen, die aufgerufen werden. Es geht um die Komplexität des vorliegenden Codeabschnitts, d. H. Wie lesbar und damit wartbar es ist. – redcalx

10

Ich bin nicht sicher, ob das Abrufen der Abfragepläne die Frage beantworten wird: Die Abfragepläne verdecken einen Teil der Komplexität der Berechnung, die an den Daten vor der Rückgabe (oder Verwendung in einem Filter) durchgeführt wurde; Die Abfragepläne erfordern eine aussagekräftige Datenbank, um relevant zu sein. In der Tat sind Komplexität und Ausführungszeit etwas entgegengesetzt; etwas wie "Gut, schnell, billig - wählen Sie zwei".

Letztendlich geht es um die Chancen, einen Fehler zu machen oder den Code, den ich geschrieben habe, nicht zu verstehen?

So etwas wie:

  • Anzahl der Tabellen-mal (1
  • +1 pro Join-Ausdruck (+1 pro Outer-Joins)
  • +1 pro Prädikat nach WHERE oder HAVING
  • + 1 pro GROUP BY Ausdruck
  • +1 pro UNION oder INTERSECT
  • +1 pro Funktionsaufruf
  • +1 pro CASE Ausdruck
  • )
+0

Das ist genau die Art von was ich suche. Wenn ich keinen finden kann, könnte ich meinen eigenen ähnlich brauen. – epotter

+0

Sie könnten auch einige Punkte (einen halben Punkt?) Entfernen, um nach einem indizierten Feld zu suchen. Und vergiss deine Order By auch nicht. – MPelletier

+0

Wie jemand erwähnt hat, würde diese Maßnahme nicht die Effizienz der SQL-Anweisungen betreffen. Es geht um ihre Komplexität oder das Risiko, das sie den Tests entgegenbringen (z. B. ein Prädikat verpassen oder einen inneren statt linken Join verwenden oder den berüchtigten * warum dauert meine einfache Abfrage für immer? *, Aka der fehlende Join) . In diesem Sinne sehe ich nicht, warum das Vorhandensein eines Index berücksichtigt werden sollte. – pascal

1

Nun, ich weiß nicht, jedes Werkzeug, das so etwas tat, aber es scheint mir, dass das, was eine Abfrage machen würde die Anzahl der Joins die Zahl der, wo die Bedingungen die Anzahl der Funktionen die Anzahl der Unterabfragen die Anzahl der Würfe zu differnt Datentypen die Anzahl der Case-Anweisungen die Anzahl der Schleifen oder Cursor: komplizierter durch gemessen werden würdedie Anzahl der Schritte in einer Transaktion

Es stimmt zwar, dass die komplexeren Abfragen möglicherweise die mit den meisten möglichen Fehlern sind, aber ich finde, dass die einfachen sehr wahrscheinlich Defekte enthalten, so wie sie sind Es ist wahrscheinlicher, dass sie von jemandem geschrieben werden, der das Datenmodell nicht versteht und daher scheinbar korrekt funktioniert, aber tatsächlich die falschen Daten zurückgibt. Ich bin mir also nicht sicher, ob eine solche Metrik Ihnen viel erzählen wird.

+3

Wie bei jeder statischen Code-Analyse wäre die Nützlichkeit begrenzt. Ich stimme dem zu, was du sagst. Aber lassen Sie uns eine Situation in Betracht ziehen, in der ein einzelner Entwickler oder drei gleichermaßen fähige Entwickler 20 Abfragen geschrieben haben. Wenn es möglich wäre, zu bestimmen, welche Abfragen am komplexesten und daher am wahrscheinlichsten Fehler enthalten, könnte der Test zuerst und/oder die meisten dieser Abfragen fokussieren. Statische Code-Analysatoren sind nie Indikatoren oder Korrektheit, sie sind nur Indikatoren. Sie geben Ihnen etwas anderes, um nach "Code-Gerüchen" zu riechen. – epotter

0

In Ermangelung von Tools, die dies tun, wäre ein pragmatischer Ansatz, sicherzustellen, dass die Abfragen analysiert werden konsistent formatiert sind und dann die Codezeilen zählen.

Alternativ können Sie die Größe der Abfragen in Byte verwenden, wenn sie in Datei gespeichert werden (wobei darauf zu achten ist, dass alle Abfragen mit derselben Zeichencodierung gespeichert werden).

Nicht brillant, aber ein vernünftiger Proxy für Komplexität in der Abwesenheit von etwas anderem, denke ich.

4

Bitte zögern Sie nicht mein Skript, um zu versuchen, die einen Überblick über die gespeicherten Prozedur Größe gibt, die Anzahl der Objektabhängigkeiten und die Anzahl der Parameter -

Calculate TSQL Stored Procedure Complexity