web-dev-qa-db-fra.com

Pourquoi ne pas utiliser SQL au lieu de GraphQL?

Récemment, j'ai appris à propos de 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 REST pour avoir du sens: limiter 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?

21
nalzok

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 inclut 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 requête pourrait contenir un argument WHERE 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.

30
Andy

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 n'autorisez que 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 d'utiliser 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.

19
Ewan

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 à odata (si vous travaillez dans des backends .NET, bien qu'il existe peut-être d'autres implémentations).

2
jannikb

si vous voulez exposer du SQL comme GraphQL, vous aurez peut-être besoin de quelque chose comme GraphQL, car vous devrez masquer les informations importantes et 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

0
Black Hole