最近、RESTfulより優れていると主張するGraphQLについて学びました。しかし、なぜ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を直接発行することには、次の利点もあります。
では、GraphQLがSQLよりも優れている点は何でしょうか。
基本的に、抽象化です。
SQLでは、クライアントが正確なデータベース構造を知っている必要がありますが、これは良くありません。その上、入力として送信された値に基づいて特別な操作を実行するためにSQLを分析することは、本当に難しいことです。それだけにかなり責任があるソフトウェア全体があります。それらが何であるか知っていますか?あなたがデータベースを推測した場合、あなたは正しいです。
SQLを直接公開しないことにより、APIのコンシューマーをデータベースの内部表現に制限することはありません。公開したいものだけを簡単に公開できます。
また、APIのクライアントは抽象化のみに依存しているため、API入力と実際のデータベースの間に可能な限り多くのレイヤーを自由に配置できます(セキュリティ、キャッシュ、単一の要求での複数のデータベースからのデータのロードなど)。
公共サービスの場合、データベースを直接公開することは、適切なアプローチとは言えません。ただし、内部システムがいくつかある場合、確かにあなたのアプローチは意味があるかもしれませんが、それでも、データベースの資格情報をアプリケーションBに与えることで、アプリケーションBから直接アプリケーションAのデータベースに接続する方が簡単な場合があります。データベースSQL言語用のカスタムHTTPインターフェイス。
RDBMSで実際のクエリを実行する前に、RedisのキーとURL(またはSQLクエリ)を比較できないのはなぜですか?
それは簡単ではないからです。誰かが次のような非常に単純なクエリを使用する場合でも、
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'
これらのクエリはすべて同じ結果を返すはずですが、同じ方法でキャッシュする必要があります。しかし、可能なすべてのオプションを処理することはほとんど不可能です。そのため、RedisでURLをキーと単純に比較することはできません。
理論的には、このようなSQLインターフェースを公開できない理由はありません。
実際には、SQLは非常に強力であるため、公開するセキュリティスコープに効果的に限定できません。
読み取りアクセスのみを許可する場合でも、不正なクエリはリソースを占有する可能性があります。
GraphQLなどの他の言語は公開されるように設計されています。それらは単に、ユーザーがすでに見ることができるものにフィルターオプションを与えるだけです。
これらの言語を使用する利点は、ユーザーがSQLで行うのをやめたいと思うすべてのことを経験し、それらをテーブルから削除したことです。
他の人が述べたように、APIでSQLを直接公開することは非常に悪いオプションです。 GraphQLは、その名前にもかかわらず、SQLの抽象概念ではなく、データストアやその他のサービスの抽象概念です。
SQLに近い抽象化を探している場合は、 odata を確認することをお勧めします(.NETバックエンドで作業している場合でも、他の実装が存在する可能性があります)。
sQLをGraphQLのように公開する場合は、重要な情報を非表示にし、APIに表示するものを選択する必要があるため、GraphQLのようなものが必要になる可能性があります。これはセキュリティのためです。
GraphQlとSQLは別物です。SQLはデータベースにクエリを実行するための言語であり、GraphQLはAPIからのデータを管理するためだけです。APIでは、スキーマを表示し、クエリを実行して管理する必要があります。
どのAPIでも、セキュリティのためだけにこれらを作成する必要がありますが、無料のデータアクセスが必要な場合は機能するかもしれませんが、ソフトウェアの世界には非常に多くの選択肢があります。