Warum nicht SQL anstelle von GraphQL verwenden?

19

Kürzlich habe ich GraphQL kennengelernt, das RESTful überlegen sein soll. Ich habe mich jedoch gefragt, warum wir nicht einfach SQL-Anweisungen in eine HTTP-GET-Anforderung einfügen.

Zum Beispiel würde ich in GraphQL schreiben

{
  Movie(id: "cixos5gtq0ogi0126tvekxo27") {
    id
    title
    actors {
      name
    }
  }
}

Das ist nicht viel einfacher als sein SQL-Gegenstück

SELECT id, title FROM movies WHERE id = cixos5gtq0ogi0126tvekxo27;
SELECT actors.name FROM actors, actors_movies WHERE actors.id == movies.actor_id AND movie.id == cixos5gtq0ogi0126tvekxo27;

Vielleicht können wir die Anfrage per URL verschlüsseln und an den Server senden

GET endpoint?q=SELECT%20id%2C%20title%20FROM%20movies%20WHERE%20id%20%3D%20cixos5gtq0ogi0126tvekxo27%3B%0ASELECT%20actors.name%20FROM%20actors%2C%20actors_movies%20WHERE%20actors.id%20%3D%3D%20movies.actor_id%20AND%20movie.id%20%3D%3D%20cixos5gtq0ogi0126tvekxo27%3B HTTP/1.1

Ja, die Abfrage-URL kann zu lang sein, Sie können sie jedoch in den Text einer POST-Anforderung einfügen, wenn Sie sich nicht um die REST-Konformität kümmern. (Übrigens, ich denke, der HTTP-RFC muss überarbeitet werden, damit REST Sinn macht: Das Begrenzen der Länge von Abfragezeichenfolgen mischt die Implementierung mit der Spezifikation am Anfang.)

Das direkte Ausgeben von SQL vom Client hat auch den Vorteil von

  1. Zum Parsen von GraphQL ist kein serverseitiger Code / keine serverseitige Bibliothek erforderlich, wodurch die Entwicklungszeit verkürzt wird.
  2. Zum Parsen von GraphQL ist kein serverseitiger Overhead erforderlich, wodurch die Laufzeit verringert wird.
  3. SQL-Anweisungen sind viel flexibler als GraphQL, da letztere (in den meisten Fällen) ohnehin auf SQL reduziert werden.
  4. Jeder kennt SQL.

Welche Vorteile hat GraphQL gegenüber SQL?

nalzok
quelle
41
Kleine Bobby Tische.
Philip Kendall
1
1. Ich kann Sie noch mit beliebig komplizierten SQL-Abfragen erledigen. 2. Es gibt keine Chance, dass ein böswilliger Schauspieler jemals einen gültigen Schlüssel erhält ...
Philip Kendall,
3
@PhilipKendall Sie haben Recht, aber die Verwendung von GraphQL (oder REST oder was auch immer) löst diese Probleme auch nicht, oder?
Nalzok
7
@nalzok: SQL ist Turing-vollständig, was bedeutet, dass eine statische Validierung nicht möglich ist.
Jörg W Mittag
3
Das ist sehr einfach zu verstehen, warum es eine schreckliche Idee ist. Implementieren Sie es selbst. Irgendwann werden Sie feststellen, dass Sie die Zeit hauptsächlich in eine Sache investieren: Sicherheit. Nicht zu spät werden Sie sich etwas verärgert fühlen, weil Sie eine gekappte TOAD implementieren. Dann werden Sie feststellen, wie schwer es ist, Zeilen im gesamten System zuzuordnen, und Sie werden versuchen, das ORM-Rad auf beiden Seiten neu zu erfinden: Client und Server. Wenn Sie aufgeben, werden Sie von Ihrem PM um einen Bericht gebeten: Wie läuft der Dienst der Benutzer ? Ist es fertig? "...
Laiv

Antworten:

30

Grundsätzlich Abstraktion.

SQL erfordert, dass Ihre Clients Ihre genaue Datenbankstruktur kennen, was nicht gut ist. Darüber hinaus ist es sehr schwierig, die SQL zu analysieren, um spezielle Operationen basierend auf dem als Eingabe gesendeten Wert auszuführen. Es gibt ganze Software, die so ziemlich nur dafür verantwortlich sind. Weißt du was das sind? Wenn Sie die Datenbanken erraten haben, haben Sie Recht.

Da Sie SQL nicht direkt verfügbar machen, beschränken Sie den Benutzer der API nicht auf die interne Darstellung Ihrer Datenbank. Sie belichten einfach nur das, was Sie belichten möchten.

Und da Clients der API nur von der Abstraktion abhängen, können Sie so viele Schichten wie möglich zwischen der API-Eingabe und der tatsächlichen Datenbank haben (Sicherheit, Zwischenspeicherung, Laden von Daten aus mehreren Datenbanken in einer einzigen Anforderung, ...).

Für öffentliche Dienste ist die direkte Bereitstellung einer Datenbank so gut wie nie der richtige Ansatz. Wenn Sie jedoch über einige wenige interne Systeme verfügen, ist Ihr Ansatz möglicherweise sinnvoll, aber selbst dann ist es möglicherweise einfacher, eine Verbindung zur Datenbank von Anwendung A direkt von Anwendung B aus herzustellen, indem Sie der Anwendung B die Datenbankanmeldeinformationen geben, anstatt zu versuchen, diese aufzurufen mit einer benutzerdefinierten HTTP-Schnittstelle für die Datenbank-SQL-Sprache.


Warum kann ich die URL (oder SQL-Abfrage) nicht einfach mit Schlüsseln in Redis vergleichen, bevor ich die eigentliche Abfrage im RDBMS durchführe?

Weil es nicht einfach ist. Selbst wenn jemand eine sehr einfache Abfrage verwendet, wie zum Beispiel:

SELECT st.id, jt.name
FROM some_table st
INNER JOIN join_table jt ON jt.some_table_id = st.id
WHERE st.name = 'hello
world' AND st.type = 'STANDARD'

Wie stellen Sie sicher, dass das Ergebnis ordnungsgemäß zwischengespeichert wird? Diese Abfrage enthält Zeilenumbrüche, aber jemand könnte die Abfrage genauso gut folgendermaßen schreiben:

SELECT st.id, jt.name FROM some_table st INNER JOIN join_table jt ON jt.some_table_id = st.id WHERE st.name = 'hello
world' AND st.type = 'STANDARD'

und es soll immer noch auf die gleiche Weise wie oben zwischengespeichert werden. Ich habe speziell eine Stelle eingefügt, an der eine Zeichenfolgensuche eine neue Zeile enthält. Das einfache Finden und Ersetzen von Zeilenenden durch ein Leerzeichen wird hier also nicht funktionieren. Das korrekte Parsen der Anforderung wäre viel komplizierter.

Und selbst wenn Sie das korrigieren, könnte eine andere Abfrage die Reihenfolge der Bedingungen ändern, und die Abfrage würde folgendermaßen aussehen:

SELECT st.id, jt.name
FROM some_table st
INNER JOIN join_table jt ON jt.some_table_id = st.id
WHERE st.type = 'STANDARD' AND st.name = 'hello
world'

und eine andere Anfrage könnte ein redundantes WHEREArgument enthalten :

SELECT st.id, jt.name
FROM some_table st
INNER JOIN join_table jt ON jt.some_table_id = st.id
WHERE st.type = 'STANDARD' AND st.name = 'hello
world' AND st.stype = 'STANDARD'

Alle diese Abfragen sollen immer noch das gleiche Ergebnis liefern und sollten auf die gleiche Weise zwischengespeichert werden. Es ist jedoch so gut wie unmöglich, mit allen möglichen Optionen umzugehen. Aus diesem Grund können Sie die URL nicht einfach mit Schlüsseln in Redis vergleichen.

Andy
quelle
Dies ist eine nette Antwort, aber bitte schauen Sie sich das Update an.
Nalzok
19

Theoretisch gibt es keinen Grund, eine SQL-Schnittstelle wie diese nicht verfügbar zu machen.

In der Praxis ist SQL viel zu leistungsfähig, um effektiv auf den Sicherheitsbereich beschränkt zu sein, den Sie verfügbar machen möchten.

Selbst wenn Sie nur Lesezugriff zulassen, kann eine fehlerhafte Abfrage dennoch Ressourcen belasten.

Andere Sprachen wie graphQL sind so konzipiert, dass sie verfügbar gemacht werden. Sie geben den Benutzern lediglich eine Filteroption für das, was sie bereits sehen konnten.

Der Vorteil der Verwendung dieser Sprachen besteht darin, dass sie alle Dinge durchlaufen haben, die Sie von Benutzern in SQL erwarten würden, und sie vom Tisch genommen haben.

Ewan
quelle
2
Vielen Dank für die Antwort, aber können Sie erklären, wie GraphQL das Problem der Ressourcenentleerung löst? Eine falsche GraphQL-Abfrage kann immer noch sagen: "Erzählen Sie mir alles über jeden Film und seine Darsteller", was zu einer riesigen Grafik führt und mein DBMS und Netzwerk erschöpft.
Nalzok
Aber ich kann eine rekursive SQL-Abfrage schreiben, die Ihre Tabelle sperrt und verhindert, dass andere Benutzer überhaupt Abfragen
Ewan,
4
Das Problem ist nicht so sehr, den Zugriff auf Tabellen einzuschränken oder zu löschen, sondern die Scherkomplexität von SQL. Erlauben Sie die Erstellung von temporären Tabellen? Was ist mit der Ausführung von CLI? Schleifen? Transaktionen? Unter wählt? Cursor? Wie werden Sie unterscheiden, wann die Verwendung dieser Dinge akzeptabel ist und wann es "schlecht" ist
Ewan
2

Wie andere bereits erwähnt haben, ist es eine sehr schlechte Option, SQL direkt in der API verfügbar zu machen. Trotz seines Namens ist GraphQL keine Abstraktion für SQL, sondern für jeden Datenspeicher oder sogar für andere Dienste.

Wenn Sie eine Abstraktion suchen, die SQL näher kommt, sollten Sie sich Odata ansehen (wenn Sie zufällig in .NET-Backends arbeiten, obwohl möglicherweise andere Implementierungen existieren).

jannikb
quelle
0

Wenn Sie SQL wie GraphQL verfügbar machen möchten, benötigen Sie möglicherweise etwas wie GraphQL, da Sie die wichtigen Informationen ausblenden und aus Sicherheitsgründen auswählen müssen, was in der API angezeigt werden soll.

GraphQl und SQL sind verschiedene Dinge, SQL ist die Sprache zum Abfragen der Datenbank und GraphQL dient nur zum Verwalten der Daten von der API. In der API müssen Sie Ihre Schemata anzeigen und Abfragen durchführen, um sie zu verwalten.

In jeder API müssen Sie diese Dinge einfach für die Sicherheit machen, aber wenn Sie etwas wollen, das freien Datenzugriff bietet, funktioniert es vielleicht, Sie kennen so viele Alternativen in der Software-Welt

Schwarzes Loch
quelle