Почему бы не использовать SQL вместо GraphQL?


20

Недавно я узнал о GraphQL, который утверждает, что превосходит RESTful. Тем не менее, я начал задаваться вопросом, почему бы нам просто не поместить операторы SQL в запрос HTTP GET.

Например, в GraphQL я бы написал

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

Что не намного проще, чем его аналог 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;

Может быть, мы можем URL-кодировать запрос и отправить на сервер

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

Да, URL-адрес запроса может быть слишком длинным, но вы можете поместить его в тело запроса POST, если вас не заботит соответствие REST. (Кстати, я думаю, что HTTP RTC необходимо пересмотреть, чтобы REST имел смысл: ограничение длины строк запроса смешивает реализацию со спецификацией в самом начале)

Непосредственная выдача SQL от клиента также имеет преимущество

  1. Не требуется серверный код / ​​библиотека для анализа GraphQL, что сокращает время разработки.
  2. Для анализа GraphQL не требуются служебные данные на стороне сервера, что сокращает время выполнения.
  3. SQL-операторы гораздо более гибкие, чем GraphQL, потому что (в большинстве случаев) последний в любом случае сведется к SQL.
  4. Все знают SQL.

Итак, каковы преимущества GraphQL перед SQL?


41
Маленькие Бобби Столы.
Филипп Кендалл

1
1. Я все еще могу DoS вас с произвольно сложными SQL-запросами. 2. Нет никакого шанса, что злой актер когда-либо получит действительный ключ ...
Филипп Кендалл

3
@PhilipKendall Вы правы, но использование GraphQL (или REST или что-то еще) тоже не решает эти проблемы, верно?
nalzok

7
@nalzok: SQL завершен по Тьюрингу, что означает, что статическая проверка невозможна.
Йорг Миттаг

3
Это очень просто понять, почему это ужасная идея. Реализуй это сам. В какой-то момент вы поймете, что вкладываете время в основном в одну вещь: безопасность. Не слишком поздно вы будете чувствовать себя несколько расстроенным, потому что вы внедрили caped TOAD. Затем вы поймете, как сложно отображать строки во всей системе, и попытаетесь заново изобрести колесо ORM с обеих сторон: клиента и сервера. К тому времени, когда вы сдадитесь, ваш премьер-министр попросит вас сообщить: как продвигается обслуживание пользователей ? Готово? "...
Laiv

Ответы:


30

В основном абстракция.

SQL требует, чтобы ваши клиенты знали вашу точную структуру базы данных, что не очень хорошо. Кроме того, анализ SQL для выполнения специальных операций на основе значения, отправляемого в качестве входных данных, является действительно сложной задачей. Есть целые программы, которые в значительной степени ответственны только за это. Вы знаете, что это такое? Если вы угадали базы данных, вы правы.

Благодаря отсутствию прямого доступа к SQL вы не ограничиваете потребителя API внутренним представлением вашей базы данных. Вы легко выставляете только то, что хотите разоблачить.

А поскольку клиенты API зависят только от абстракции, вы можете иметь как можно больше слоев между входом API и реальной базой данных (безопасность, кэширование, загрузка данных из нескольких баз данных по одному запросу, ...).

Для публичных служб непосредственное раскрытие базы данных почти никогда не является правильным подходом. Однако если у вас есть несколько внутренних систем, конечно, ваш подход может иметь смысл, но даже тогда может быть проще подключиться к базе данных приложения A непосредственно из приложения B, передав учетные данные базы данных приложению B, чем пытаться найти с пользовательским интерфейсом HTTP для языка баз данных SQL.


Почему я не могу просто сравнить URL (или SQL-запрос) с ключами в Redis перед выполнением фактического запроса в СУБД?

Потому что это не легко. Даже если кто-то использует очень простой запрос, такой как:

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'

как убедиться, что результат правильно кэширован? Этот запрос включает переводы строки, но кто-то может написать запрос следующим образом:

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'

и он все еще должен кэшироваться так же, как и выше. Я специально включил где, где поиск строки содержит новую строку, поэтому простой поиск окончаний строки и замена их пробелом здесь не сработает, правильно проанализировать запрос будет гораздо сложнее.

И даже если вы это исправите, другой запрос может изменить порядок условий, и запрос будет выглядеть так:

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'

и другой запрос может содержать избыточный WHEREаргумент, например:

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'

Все эти запросы все еще должны возвращать один и тот же результат и должны кэшироваться одинаково. Но обработка всех возможных вариантов практически невозможна. Вот почему вы не можете просто сравнить URL с ключами в Redis.


Это хороший ответ, но, пожалуйста, смотрите обновление.
nalzok

19

В теории нет причин, по которым вы не можете выставить такой интерфейс SQL.

На практике SQL слишком мощен, чтобы эффективно ограничиваться областью безопасности, которую вы хотите раскрыть.

Даже если вы разрешите доступ только для чтения, неправильный запрос все равно может забрать ресурсы.

Другие языки, такие как graphQL, предназначены для демонстрации. Они просто дают пользователям возможность фильтровать то, что они уже могли видеть.

Преимущество использования этих языков состоит в том, что они прошли через все то, что вы хотели бы помешать пользователям делать в SQL, и сняли их со стола.


2
Спасибо за ответ, но не могли бы вы объяснить, как GraphQL решает проблему истощения ресурсов? Мошеннический запрос GraphQL все еще может сказать «расскажи мне все о каждом фильме и его актерах», что приводит к огромному графику и исчерпанию моей СУБД и сети.
Нальзок

Но я могу написать рекурсивный SQL-запрос, который заблокирует вашу таблицу и не позволит другим пользователям вообще выполнять какие-либо запросы
Ewan

4
проблема не столько в ограничении доступа к таблицам или их удалении, сколько в сложном сдвиге SQL. Вы позволите создание временной таблицы? как насчет выполнения CLI? петли? сделки? саб выбирает? курсоры? как вы будете различать, когда использование этих вещей является приемлемым, а когда это «плохо»
Ewan

2

Как уже упоминали другие, выставление SQL непосредственно в API является очень плохим вариантом. GraphQL, несмотря на свое название, является не абстракцией для SQL, а для любого хранилища данных или даже других сервисов.

Если вы ищете абстракцию, которая ближе к SQL, вы, возможно, захотите взглянуть на odata (если вы работаете в бэкэндах .NET, хотя, возможно, существуют и другие реализации).


0

если вы хотите представить SQL, такой как GraphQL, вам может понадобиться что-то вроде GraphQL, потому что вам нужно будет скрыть важную информацию и выбрать то, что вы хотите показать в API, это для безопасности.

GraphQl и SQL - это разные вещи, SQL - это язык для запросов к базе данных, а GraphQL - только для управления данными из API, в API вам нужно будет создавать свои схемы для отображения и запрашивать управление ими и т. Д.

в любом API вам нужно будет делать все это просто для обеспечения безопасности, но если вы хотите что-то с бесплатным доступом к данным, возможно, это сработает, вы знаете так много альтернатив в мире программного обеспечения

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.