Pourquoi ne pas utiliser SQL au lieu de GraphQL?

20

Récemment, j'ai découvert GraphQL qui prétend être supérieur à RESTful. Cependant, j'ai commencé à me demander pourquoi ne mettons-nous pas simplement des instructions SQL dans une requête HTTP GET.

Par exemple, dans GraphQL j'écrirais

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

Ce qui n'est pas beaucoup plus simple que son homologue SQL

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;

Peut-être pouvons-nous encoder la requête par URL et l'envoyer au serveur

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

Oui, l'URL de la requête peut être trop longue, mais vous pouvez la placer dans le corps d'une demande POST si vous ne vous souciez pas de la conformité REST. (Soit dit en passant, je pense que le RFC HTTP doit être révisé pour que REST ait un sens: le plafonnement de la longueur des chaînes de requête mélange l'implémentation avec la spécification au tout début)

L'émission directe de SQL à partir du client présente également l'avantage de

  1. Aucun code / bibliothèque côté serveur n'est requis pour analyser GraphQL, ce qui réduit le temps de développement.
  2. Aucune surcharge côté serveur n'est nécessaire pour analyser GraphQL, ce qui réduit le temps d'exécution.
  3. Les instructions SQL sont beaucoup plus flexibles que GraphQL car (dans la plupart des cas) ce dernier se réduira de toute façon à SQL.
  4. Tout le monde connaît SQL.

Alors, quels sont les avantages de GraphQL sur SQL?

nalzok
la source
41
Petites tables Bobby.
Philip Kendall
1
1. Je peux toujours vous faire du DoS avec des requêtes SQL arbitrairement compliquées. 2. Il n'y a aucune chance qu'un acteur malveillant obtienne une clé valide ...
Philip Kendall
3
@PhilipKendall Vous avez raison, mais l'utilisation de GraphQL (ou REST ou autre) ne résout pas non plus ces problèmes, non?
nalzok
7
@nalzok: SQL est Turing-complete, ce qui signifie qu'il est impossible de valider statiquement.
Jörg W Mittag
3
C'est très simple de comprendre pourquoi c'est une terrible idée. Mettez-le en œuvre vous-même. À un moment donné, vous vous rendrez compte que vous investissez le temps principalement dans 1 chose: la sécurité. Pas trop tard, vous vous sentirez un peu contrarié parce que vous implémentez un TOAD plafonné. Ensuite, vous réaliserez à quel point il est difficile de mapper les lignes sur tout le système et vous essaierez de réinventer la roue ORM des deux côtés: client et serveur. Au moment où vous abandonnez, votre PM vous demandera un rapport: comment se passe le service aux utilisateurs ? C'est fini? "...
Laiv

Réponses:

30

Fondamentalement, l'abstraction.

SQL exige que vos clients connaissent votre structure de base de données exacte, ce qui n'est pas bon. En plus de cela, l'analyse du SQL afin d'effectuer des opérations spéciales en fonction de la valeur envoyée en entrée est une chose vraiment difficile à faire. Il existe des logiciels entiers qui ne sont à peu près responsables que de cela. Savez-vous ce que c'est? Si vous avez deviné les bases de données, vous avez raison.

Grâce à ne pas exposer directement le SQL, vous ne limitez pas le consommateur de l'API à la représentation interne de votre base de données. Vous exposez facilement uniquement ce que vous souhaitez exposer.

Et puisque les clients de l'API ne dépendent que de l'abstraction, vous êtes libre d'avoir autant de couches que possible entre l'entrée API et la base de données réelle (sécurité, mise en cache, chargement des données de plusieurs bases de données sur une seule demande, ...).

Pour les services publics, exposer directement une base de données n'est pratiquement pas la bonne approche. Si vous avez cependant quelques systèmes internes, bien sûr, votre approche pourrait avoir un sens, mais même alors, il pourrait être plus facile de se connecter à la base de données de l'application A directement à partir de l'application B en donnant les informations d'identification de la base de données à l'application B, plutôt que d'essayer de trouver avec une interface HTTP personnalisée pour le langage SQL de la base de données.


Pourquoi ne puis-je pas simplement comparer l'URL (ou la requête SQL) aux clés dans Redis avant d'exécuter la requête réelle sur le SGBDR?

Parce que ce n'est pas facile. Même si quelqu'un utilise une requête très simple, telle que:

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'

comment vous assurez-vous que le résultat est correctement mis en cache? Cette requête comprend des sauts de ligne, mais quelqu'un pourrait tout aussi bien écrire la requête de la manière suivante:

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'

et il est toujours censé être mis en cache de la même manière que celui ci-dessus. J'ai spécifiquement inclus un où dans lequel une recherche de chaîne contient une nouvelle ligne, donc simplement trouver des fins de ligne et les remplacer par un espace ne fonctionnera pas ici, analyser correctement la demande serait beaucoup plus compliqué.

Et même si vous résolvez cela, une autre requête pourrait changer l'ordre des conditions et la requête ressemblerait à ceci:

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'

et une autre demande pourrait contenir un WHEREargument redondant , comme ceci:

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'

Toutes ces requêtes sont toujours censées retourner le même résultat, doivent être mises en cache de la même manière. Mais gérer toutes les options possibles est quasiment impossible. C'est pourquoi vous ne pouvez pas simplement comparer l'URL avec des clés dans Redis.

Andy
la source
C'est une bonne réponse, mais veuillez consulter la mise à jour.
nalzok
19

En théorie, il n'y a aucune raison pour laquelle vous ne pouvez pas exposer une interface SQL comme celle-ci.

En pratique, SQL est beaucoup trop puissant pour être efficacement limité à l'étendue de sécurité que vous souhaitez exposer.

Même si vous autorisez uniquement l'accès en lecture, une mauvaise requête peut toujours monopoliser les ressources.

D'autres langages tels que graphQL sont conçus pour être exposés. Ils donnent simplement aux utilisateurs une option de filtrage sur ce qu'ils peuvent déjà voir.

L'avantage de l'utilisation de ces langages est qu'ils sont passés par toutes les choses que vous voudriez empêcher les utilisateurs de faire en SQL et les ont retirés de la table.

Ewan
la source
2
Merci pour la réponse, mais pourriez-vous expliquer comment GraphQL résout le problème de la vidange des ressources? Une requête GraphQL escroc peut toujours dire «dis-moi tout sur chaque film et leurs acteurs», ce qui donne un graphique énorme et épuise mon SGBD et mon réseau.
nalzok
Mais je peux écrire une requête SQL récursive qui verrouillera votre table et empêchera les autres utilisateurs d'exécuter des requêtes
Ewan
4
le problème n'est pas tant de restreindre l'accès aux tables ou de supprimer, mais la complexité de cisaillement de SQL. autoriserez-vous la création d'une table temporaire? qu'en est-il de l'exécution de CLI? boucles? transactions? sous sélection? curseurs? comment allez-vous distinguer quand l'utilisation de ces choses est acceptable et quand son «mauvais»
Ewan
2

Comme d'autres l'ont mentionné, exposer SQL directement dans l'API est une très mauvaise option. GraphQL, malgré son nom, n'est pas une abstraction pour SQL, mais pour n'importe quel magasin de données ou même d'autres services.

Si vous recherchez une abstraction plus proche de SQL, vous voudrez peut-être jeter un œil aux odata (si vous travaillez dans des backends .NET, bien qu'il existe peut-être d'autres implémentations).

jannikb
la source
0

si vous voulez exposer du SQL comme GraphQL, vous aurez peut-être besoin de quelque chose comme GraphQL, car vous aurez besoin de cacher les informations importantes et de sélectionner ce que vous voulez afficher dans l'API, ceci pour des raisons de sécurité.

GraphQl et SQL sont des choses différentes, SQL est le langage pour interroger DataBase et GraphQL est uniquement pour gérer les données de l'API, dans l'API, vous devrez créer vos schémas à afficher et des requêtes pour les gérer, etc.

dans n'importe quelle API, vous aurez besoin de faire ces choses simplement pour la sécurité, mais si vous voulez quelque chose qui soit un accès gratuit aux données, cela pourrait fonctionner, vous connaissez tellement d'alternatives dans le monde du logiciel

Trou noir
la source