Чому б не використовувати 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 RFC потрібно переглянути для REST, щоб мати сенс: обмеження довжини рядків запитів змішує реалізацію із специфікацією на самому початку)

Перевага видачі SQL від клієнта також має перевагу

  1. Не потрібен код / ​​бібліотека на сервері для розбору GraphQL, скорочуючи час розробки.
  2. Не потрібні накладні на стороні сервера для розбору GraphQL, скорочуючи час виконання.
  3. Операції SQL набагато гнучкіші, ніж GraphQL, оскільки (у більшості випадків) останні в будь-якому випадку зменшаться до SQL.
  4. Усі знають SQL.

Отже, які переваги має GraphQL перед SQL?


41
Столики маленького Бобі.
Філіп Кендалл

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

3
@PhilipKendall Ви маєте рацію, але використання GraphQL (або REST або будь-якого іншого) також не вирішує цих проблем, правда?
nalzok

7
@nalzok: SQL завершений Тьюрінгом, що означає, що неможливо статично перевірити.
Йорг W Міттаг

3
Це дуже просто, щоб зрозуміти, чому це жахлива ідея. Реалізуйте це самостійно. В якийсь момент ви зрозумієте, що витрачаєте свій час переважно на одну річ: безпеку. Не пізніше ви відчуєте дещо засмучення, оскільки реалізуєте обмежену TOAD. Тоді ви зрозумієте, наскільки складно відображати рядки по всій системі, і спробуєте винаходити колесо ORM з обох сторін: клієнта та сервера. Коли ви відмовитесь, ваш прем'єр-міністр запитає вас про звіт: як проходить служба користувачів ? Це зроблено? "...
Лаїв

Відповіді:


30

В основному, абстракція.

SQL вимагає від ваших клієнтів знати вашу точну структуру бази даних, що не добре. Крім того, аналіз SQL з метою виконання спеціальних операцій на основі значення, що надсилається як вхідне, - дійсно складна річ. Є цілі програмні засоби, які в основному відповідають за це. Чи знаєте ви, що це? Якщо ви вгадали бази даних, ви маєте рацію.

Завдяки не підданню впливу SQL безпосередньо, ви не обмежуєте споживача API внутрішнім представленням вашої бази даних. Ви легко виставляєте лише те, що хочете викрити.

А оскільки клієнти API залежать лише від абстракції, ви можете мати якомога більше шарів між входом API та фактичною базою даних (безпека, кешування, завантаження даних із декількох баз даних за одним запитом, ...).

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


Чому я не можу просто порівняти URL-адресу (або SQL-запит) з ключами в Redis, перш ніж виконувати фактичний запит на RDBMS?

Тому що це непросто. Навіть якщо хтось використовує дуже простий запит, наприклад:

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 все ще може сказати: "розкажи мені все про кожен фільм та його акторів", в результаті чого з'явився величезний графік та виснажив мою СУБД та мережу.
nalzok

Але я можу написати рекурсивний SQL-запит, який заблокує вашу таблицю і не дозволить іншим користувачам взагалі виконувати будь-які запити
Ewan,

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

2

Як вже згадували інші, відкриття SQL безпосередньо в api - це дуже поганий варіант. GraphQL, незважаючи на своє ім'я, не є абстракцією для SQL, але для будь-якого сховища даних або навіть інших служб.

Якщо ви шукаєте абстракцію, яка наближається до SQL, ви, можливо, захочете ознайомитись із одатою (якщо у вас є випадки, коли ви працюєте в .NET Bakend, хоча, можливо, існують інші реалізації).


0

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

GraphQl і SQL - це різні речі, SQL - це мова для запиту DataBase, а GraphQL - лише для управління даними з API, в API вам знадобляться скласти ваші схеми для показу та запити для керування ними тощо.

в будь-якому API вам потрібно зробити ці речі для простої безпеки, але якщо ви хочете щось, що є вільним доступом до даних, можливо, воно б спрацювало, ви знаєте так багато альтернатив у світі програмного забезпечення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.