Dlaczego nie użyć SQL zamiast GraphQL?

20

Ostatnio dowiedziałem się o GraphQL, który twierdzi, że jest lepszy od RESTful. Zacząłem się jednak zastanawiać, dlaczego po prostu nie umieszczamy instrukcji SQL w żądaniu HTTP GET.

Na przykład w GraphQL napisałbym

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

Co nie jest dużo prostsze niż jego odpowiednik 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;

Może możemy zakodować zapytanie i wysłać kod na serwer

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

Tak, adres URL zapytania może być zbyt długi, ale możesz go umieścić w treści żądania POST, jeśli nie zależy Ci na zgodności z REST. (Nawiasem mówiąc, myślę, że RFC HTTP musi zostać zmieniony, aby REST miał sens: ograniczenie długości ciągów zapytań powoduje mieszanie implementacji ze specyfikacją na samym początku)

Zaletą jest także bezpośrednie wydawanie kodu SQL od klienta

  1. Do analizowania GraphQL nie jest wymagany kod / biblioteka po stronie serwera, co skraca czas programowania.
  2. Do przeanalizowania GraphQL nie jest potrzebny narzut po stronie serwera, co skraca czas działania.
  3. Instrukcje SQL są znacznie bardziej elastyczne niż GraphQL, ponieważ (w większości przypadków) te ostatnie i tak zredukują się do SQL.
  4. Wszyscy znają SQL.

Jakie zalety ma GraphQL w stosunku do SQL?

nalzok
źródło
41
Małe stoły Bobby.
Philip Kendall,
1
1. Nadal mogę robić ci dowolnie skomplikowane zapytania SQL. 2. Nie ma szans, by złośliwy aktor kiedykolwiek uzyskał prawidłowy klucz ...
Philip Kendall,
3
@ PhilipKendall Masz rację, ale używanie GraphQL (lub REST lub cokolwiek innego) również nie rozwiązuje tych problemów, prawda?
nalzok
7
@nalzok: SQL jest zakończony metodą Turinga, co oznacza, że ​​niemożliwe jest sprawdzenie poprawności statycznej.
Jörg W Mittag
3
Bardzo łatwo jest zrozumieć, dlaczego to okropny pomysł. Zrealizuj to sam. W pewnym momencie zdasz sobie sprawę, że inwestujesz czas głównie w 1 rzecz: bezpieczeństwo. Nieco później poczujesz się trochę zdenerwowany, ponieważ wdrażasz kapsel TOAD. Wtedy zdasz sobie sprawę, jak trudne jest mapowanie wierszy w całym systemie i spróbujesz wynaleźć koło ORM po obu stronach: klienta i serwera. Zanim się poddasz, twój szef poprosi cię o raport: jak idzie usługa użytkowników ? Czy to jest zrobione? „...
Laiv

Odpowiedzi:

30

Zasadniczo abstrakcja.

SQL wymaga od klientów znajomości dokładnej struktury bazy danych, co nie jest dobre. Na dodatek analiza SQL w celu wykonania specjalnych operacji na podstawie wartości wysyłanej jako dane wejściowe jest naprawdę trudna. Istnieją całe programy, które są w zasadzie odpowiedzialne tylko za to. Czy wiesz co to są? Jeśli odgadłeś bazy danych, masz rację.

Dzięki temu, że SQL nie jest bezpośrednio ujawniany, użytkownik nie ogranicza konsumenta interfejsu API do wewnętrznej reprezentacji bazy danych. Z łatwością wystawiasz tylko to, co chcesz.

A ponieważ klienci interfejsu API zależą tylko od abstrakcji, możesz mieć jak najwięcej warstw między danymi wejściowymi API a rzeczywistą bazą danych (bezpieczeństwo, buforowanie, ładowanie danych z wielu baz danych na jedno żądanie, ...).

W przypadku usług publicznych bezpośrednie ujawnienie bazy danych prawie nigdy nie jest właściwym podejściem. Jeśli jednak masz kilka systemów wewnętrznych, jasne, twoje podejście może mieć sens, ale nawet wtedy łatwiejsze może być połączenie z bazą danych aplikacji A bezpośrednio z aplikacji B, podając poświadczenia bazy danych dla aplikacji B, zamiast próbować wymyślić z niestandardowym interfejsem HTTP dla języka SQL bazy danych.


Dlaczego nie mogę po prostu porównać adresu URL (lub zapytania SQL) z kluczami w Redis przed wykonaniem rzeczywistego zapytania w RDBMS?

Ponieważ to nie jest łatwe. Nawet jeśli ktoś używa bardzo prostego zapytania, takiego jak:

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'

jak upewnić się, że wynik jest odpowiednio buforowany? To zapytanie zawiera znaki nowej linii, ale ktoś równie dobrze mógłby napisać zapytanie w następujący sposób:

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'

i nadal powinien być buforowany w taki sam sposób jak powyższy. W szczególności podałem miejsce, w którym wyszukiwanie ciągów zawiera nową linię, więc po prostu znalezienie końcówek linii i zastąpienie ich spacją tutaj nie zadziała, prawidłowe przetworzenie żądania byłoby znacznie bardziej skomplikowane.

Nawet jeśli to naprawisz, kolejne zapytanie może zmienić kolejność warunków, a zapytanie będzie wyglądać następująco:

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'

a kolejne żądanie może zawierać zbędny WHEREargument, taki jak ten:

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'

Wszystkie te zapytania powinny nadal zwracać ten sam wynik, powinny być buforowane w ten sam sposób. Ale obsługa wszystkich możliwych opcji jest prawie niemożliwa. Dlatego nie można po prostu porównać adresu URL z kluczami w Redis.

Andy
źródło
To ładna odpowiedź, ale proszę zobaczyć aktualizację.
nalzok
19

Teoretycznie nie ma powodu, dla którego nie można ujawnić takiego interfejsu SQL.

W praktyce SQL jest zdecydowanie zbyt potężny, aby skutecznie ograniczać się do zakresu bezpieczeństwa, który chcesz ujawnić.

Nawet jeśli zezwolisz tylko na dostęp do odczytu, złe zapytanie może nadal przenosić zasoby.

Inne języki, takie jak graphQL, zostały zaprojektowane do ujawnienia. Dają jedynie użytkownikom opcję filtrowania tego, co już widzieli.

Zaletą używania tych języków jest to, że przeszli przez wszystkie rzeczy, których nie chcesz, aby użytkownicy robili w SQL i zdjęli je ze stołu.

Ewan
źródło
2
Dzięki za odpowiedź, ale czy możesz wyjaśnić, w jaki sposób GraphQL rozwiązuje problem drenowania zasobów? Nieuczciwe zapytanie GraphQL wciąż może powiedzieć „powiedz mi wszystko o każdym filmie i jego aktorach”, co powoduje powstanie ogromnego wykresu i wyczerpanie mojego DBMS i sieci.
nalzok
Ale mogę napisać rekurencyjne zapytanie SQL, które zablokuje twoją tabelę i uniemożliwi innym użytkownikom uruchamianie jakichkolwiek zapytań
Ewan
4
problemem nie jest tak bardzo ograniczenie dostępu do tabel, ani ich usuwanie, ale złożoność SQL podczas ścinania. zezwolisz na tworzenie tabel tymczasowych? co z uruchomieniem CLI? pętle? transakcje? sub wybiera? kursory? jak rozróżnisz, kiedy użycie tych rzeczy jest dopuszczalne i kiedy jest „złe”
Ewan
2

Jak wspomnieli inni, ujawnianie SQL bezpośrednio w interfejsie API jest bardzo złą opcją. GraphQL, pomimo swojej nazwy, nie jest abstrakcją dla SQL, ale dla dowolnego magazynu danych, a nawet innych usług.

Jeśli szukasz abstrakcji zbliżonej do SQL, możesz rzucić okiem na odata (jeśli akurat pracujesz w backendach .NET, choć może istnieją inne implementacje).

jannikb
źródło
0

jeśli chcesz wystawiać SQL jak GraphQL, możesz potrzebować czegoś takiego jak GraphQL, ponieważ będziesz musiał ukryć ważne informacje i wybrać to, co chcesz pokazać w interfejsie API, to dla bezpieczeństwa.

GraphQl i SQL to różne rzeczy, SQL to język zapytań do DataBase, a GraphQL służy tylko do zarządzania danymi z API, w API będziesz musiał stworzyć własne schematy do wyświetlenia i zapytania do zarządzania nimi itp.

w każdym interfejsie API będziesz musiał zrobić te rzeczy dla bezpieczeństwa, ale jeśli chcesz czegoś, co jest darmowym dostępem do danych, może zadziałałoby, znasz tak wiele alternatyw w świecie oprogramowania

Czarna dziura
źródło