Tại sao không sử dụng SQL thay vì GraphQL?


19

Gần đây tôi đã biết về GraphQL, tuyên bố là vượt trội so với RESTful. Tuy nhiên, tôi bắt đầu tự hỏi tại sao chúng ta không đơn giản đưa các câu lệnh SQL vào một yêu cầu HTTP GET.

Ví dụ, trong GraphQL tôi sẽ viết

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

Điều này không đơn giản hơn nhiều so với đối tác SQL của nó

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;

Có lẽ chúng ta có thể mã hóa URL truy vấn và gửi đến máy chủ

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

Có, URL truy vấn có thể quá dài, nhưng bạn có thể đặt nó vào phần thân của yêu cầu POST nếu bạn không quan tâm đến việc tuân thủ REST. (Nhân tiện, tôi nghĩ rằng RFC HTTP cần được sửa đổi cho REST để có ý nghĩa: giới hạn độ dài của chuỗi truy vấn trộn lẫn việc thực hiện với đặc tả ngay từ đầu)

Phát hành SQL trực tiếp từ máy khách cũng có lợi thế là

  1. Không có mã / thư viện phía máy chủ được yêu cầu để phân tích GraphQL, giảm thời gian phát triển.
  2. Không cần chi phí phía máy chủ để phân tích GraphQL, giảm thời gian chạy.
  3. Các câu lệnh SQL linh hoạt hơn nhiều so với GraphQL bởi vì (trong hầu hết các trường hợp), câu lệnh sau sẽ giảm xuống thành SQL.
  4. Mọi người đều biết SQL.

Vì vậy, những lợi thế của GraphQL so với SQL là gì?


41
Bàn Bobby nhỏ.
Philip Kendall

1
1. Tôi vẫn có thể DoS bạn với các truy vấn SQL phức tạp tùy ý. 2. Không có cơ hội một diễn viên độc hại nào có được khóa hợp lệ ...
Philip Kendall

3
@PhilipKendall Bạn đúng, nhưng sử dụng GraphQL (hoặc REST hoặc bất cứ điều gì) cũng không giải quyết được những vấn đề này, phải không?
nalzok

7
@nalzok: SQL là Turing-Complete, có nghĩa là không thể xác thực tĩnh.
Jörg W Mittag

3
Điều này rất đơn giản để hiểu tại sao nó là một ý tưởng khủng khiếp. Tự thực hiện nó. Đến một lúc nào đó, bạn sẽ nhận ra rằng bạn đang đầu tư thời gian chủ yếu vào 1 thứ: bảo mật. Không quá muộn bạn sẽ cảm thấy hơi khó chịu vì bạn đang thực hiện một TOAD có giới hạn. Sau đó, bạn sẽ nhận ra mức độ khó của việc ánh xạ các hàng trên toàn hệ thống và bạn sẽ cố gắng phát minh lại bánh xe ORM ở cả hai phía: máy khách và máy chủ. Khi bạn từ bỏ, PM của bạn sẽ yêu cầu bạn báo cáo: dịch vụ của người dùng sẽ thế nào? Xong chưa? "...
Laiv

Câu trả lời:


30

Về cơ bản, trừu tượng.

SQL yêu cầu khách hàng của bạn biết cấu trúc cơ sở dữ liệu chính xác của bạn, điều này không tốt. Trên hết, phân tích SQL để thực hiện các hoạt động đặc biệt dựa trên giá trị được gửi làm đầu vào là một điều thực sự khó khăn. Có toàn bộ phần mềm chỉ chịu trách nhiệm cho việc đó. Bạn có biết những thứ đó là gì không? Nếu bạn đã đoán được cơ sở dữ liệu, bạn đã đúng.

Nhờ không trực tiếp hiển thị SQL, bạn không giới hạn người tiêu dùng API đối với biểu diễn bên trong cơ sở dữ liệu của bạn. Bạn dễ dàng chỉ phơi bày những gì bạn muốn phơi bày.

Và vì các máy khách của API chỉ phụ thuộc vào sự trừu tượng, nên bạn có thể có càng nhiều lớp càng tốt giữa đầu vào API và cơ sở dữ liệu thực tế (bảo mật, lưu trữ, tải dữ liệu từ nhiều cơ sở dữ liệu trên một yêu cầu, ...).

Đối với các dịch vụ công cộng, việc phơi bày một cơ sở dữ liệu trực tiếp gần như không bao giờ là phương pháp đúng đắn. Tuy nhiên, nếu bạn có một vài hệ thống nội bộ, chắc chắn, cách tiếp cận của bạn có thể có ý nghĩa nhưng thậm chí sau đó có thể dễ dàng kết nối với cơ sở dữ liệu của ứng dụng A từ Ứng dụng B bằng cách cung cấp thông tin xác thực cơ sở dữ liệu cho Ứng dụng B, thay vì cố gắng đưa ra với giao diện HTTP tùy chỉnh cho ngôn ngữ SQL cơ sở dữ liệu.


Tại sao tôi không thể so sánh URL (hoặc truy vấn SQL) với các khóa trong Redis trước khi thực hiện truy vấn thực tế trên RDBMS?

Bởi vì nó không dễ dàng. Ngay cả khi ai đó sử dụng một truy vấn rất đơn giản, chẳng hạn như:

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'

Làm thế nào để bạn chắc chắn rằng kết quả được lưu trữ đúng cách? Truy vấn này bao gồm các dòng mới, nhưng ai đó cũng có thể viết truy vấn theo cách sau:

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'

và nó vẫn được cho là được lưu trữ theo cùng một cách như trên. Tôi đã đặc biệt bao gồm một nơi trong đó một tìm kiếm chuỗi chứa một dòng mới, vì vậy chỉ cần tìm kết thúc dòng và thay thế chúng bằng một khoảng trắng sẽ không hoạt động ở đây, phân tích chính xác yêu cầu sẽ phức tạp hơn nhiều.

Và ngay cả khi bạn khắc phục điều đó, một truy vấn khác có thể chuyển đổi thứ tự các điều kiện và truy vấn sẽ trông như thế này:

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'

và một yêu cầu khác có thể chứa một WHEREđối số dư thừa , như thế này:

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'

Tất cả các truy vấn đó vẫn được cho là trả về cùng một kết quả, nên được lưu trong cùng một cách. Nhưng xử lý tất cả các tùy chọn có thể là khá nhiều không thể. Đó là lý do tại sao bạn không thể so sánh URL với các khóa trong Redis.


Đây là một câu trả lời tốt đẹp, nhưng xin vui lòng xem cập nhật.
nalzok

19

Về lý thuyết, không có lý do gì bạn không thể trưng ra một giao diện SQL như thế này.

Trong thực tế, SQL quá mạnh để giới hạn hiệu quả trong phạm vi bảo mật mà bạn muốn đưa ra.

Ngay cả khi bạn chỉ cho phép đọc quyền truy cập, một truy vấn xấu vẫn có thể hog tài nguyên.

Các ngôn ngữ khác như graphQL được thiết kế để tiếp xúc. Họ chỉ đơn thuần cung cấp cho người dùng một tùy chọn bộ lọc về những gì họ có thể đã thấy.

Lợi ích của việc sử dụng các ngôn ngữ này là chúng đã trải qua tất cả những điều bạn muốn ngăn người dùng thực hiện trong SQL và loại bỏ chúng khỏi bàn.


2
Cảm ơn câu trả lời, nhưng bạn có thể giải thích cách GraphQL giải quyết vấn đề rút cạn tài nguyên không? Một truy vấn GraphQL lừa đảo vẫn có thể nói rằng, kể cho tôi mọi thứ về mỗi bộ phim và các diễn viên của họ, dẫn đến một biểu đồ khổng lồ và làm cạn kiệt DBMS và mạng của tôi.
nalzok

Nhưng tôi có thể viết một truy vấn SQL đệ quy sẽ khóa bảng của bạn và ngăn người dùng khác chạy bất kỳ truy vấn nào
Ewan

4
vấn đề không phải là hạn chế quá nhiều quyền truy cập vào các bảng hoặc xóa, mà là độ phức tạp cắt của SQL. bạn sẽ cho phép tạo bảng tạm thời? Còn việc thực hiện CLI thì sao? vòng lặp? giao dịch? chọn phụ? con trỏ? Làm thế nào bạn phân biệt được khi nào việc sử dụng những thứ này được chấp nhận và khi nào nó 'xấu'
Ewan

2

Như những người khác đã đề cập, phơi bày SQL trực tiếp trong api là một lựa chọn rất tồi. GraphQL, mặc dù tên của nó, không phải là một bản tóm tắt cho SQL, nhưng đối với bất kỳ kho lưu trữ dữ liệu hoặc thậm chí các dịch vụ khác.

Nếu bạn đang tìm kiếm một sự trừu tượng gần gũi hơn với SQL, bạn có thể muốn xem odata (nếu bạn tình cờ làm việc trong .NET backends, mặc dù có thể có các triển khai khác).


0

nếu bạn muốn phơi bày SQL như GraphQL, bạn sẽ cần một cái gì đó giống như GraphQL, vì bạn sẽ cần ẩn thông tin quan trọng và chọn những gì bạn muốn hiển thị trong API, điều này để bảo mật.

GraphQl và SQL là những thứ khác nhau, SQL là ngôn ngữ để truy vấn DataBase và GraphQL chỉ để quản lý dữ liệu từ API, trong API bạn sẽ cần tạo các lược đồ của mình để hiển thị và truy vấn để quản lý nó, v.v.

trong bất kỳ API nào bạn sẽ cần tạo những thứ đó để bảo mật đơn giản, nhưng nếu bạn muốn thứ gì đó truy cập dữ liệu miễn phí thì có thể nó sẽ hoạt động, bạn biết rất nhiều lựa chọn thay thế trong thế giới phần mềm

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.