ทำไมไม่ใช้ 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
โต๊ะบ๊อบบี้น้อย
Philip Kendall

1
1. ฉันยังสามารถ DoS คุณด้วยแบบสอบถาม SQL ที่ซับซ้อนโดยพลการ 2. ไม่มีโอกาสที่นักแสดงที่เป็นอันตรายจะได้รับกุญแจที่ถูกต้อง ...
Philip Kendall

3
@PhilipKendall คุณพูดถูก แต่การใช้ GraphQL (หรือ REST หรืออะไรก็ตาม) ไม่สามารถแก้ปัญหาเหล่านี้ได้ใช่ไหม?
nalzok

7
@nalzok: SQL เป็นทัวริงเสร็จสมบูรณ์ซึ่งหมายความว่ามันเป็นไปไม่ได้ที่จะตรวจสอบแบบคงที่
Jörg W Mittag

3
นี่ง่ายมากที่จะเข้าใจว่าทำไมจึงเป็นความคิดที่แย่มาก ใช้มันด้วยตัวคุณเอง ในบางจุดคุณจะรู้ว่าคุณลงทุนเวลาส่วนใหญ่ใน 1 สิ่ง: ความปลอดภัย ไม่ช้าคุณจะรู้สึกไม่สบายใจบ้างเพราะคุณกำลังใช้คางคกที่ถูกคลุม จากนั้นคุณจะรู้ว่าการแม็พแถวทั้งหมดในระบบนั้นยากเพียงใดและคุณจะพยายามสร้างวงล้อ ORM ทั้งสองฝั่ง: ไคลเอนต์และเซิร์ฟเวอร์ เมื่อถึงเวลาที่จะยอมแพ้ PM ของคุณจะขอรายงานจากคุณ: บริการของผู้ใช้เป็นอย่างไร มันเสร็จแล้วหรือ "...
Laiv

คำตอบ:


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 อันธพาลยังสามารถพูดว่า“ บอกทุกอย่างเกี่ยวกับภาพยนตร์แต่ละเรื่องและนักแสดงของพวกเขา” ซึ่งทำให้เกิดกราฟขนาดใหญ่และทำให้ DBMS และเครือข่ายของฉันหมดลง
nalzok

แต่ฉันสามารถเขียนแบบสอบถาม SQL recursive ที่จะล็อคตารางของคุณและป้องกันไม่ให้ผู้ใช้อื่น ๆ จากการทำงานคำสั่งใด ๆ เลย
อีแวน

4
ปัญหาไม่ได้ จำกัด การเข้าถึงตารางหรือการลบ แต่ความซับซ้อนของการเฉือนของ SQL คุณจะอนุญาตให้สร้างตารางชั่วคราวหรือไม่ สิ่งที่เกี่ยวกับการดำเนินการ CLI? ลูป? การทำธุรกรรม? เลือกย่อย เคอร์เซอร์? คุณจะแยกแยะได้อย่างไรเมื่อการใช้สิ่งเหล่านี้เป็นที่ยอมรับและเมื่อมัน 'ไม่ดี'
Ewan

2

ดังที่คนอื่น ๆ ได้กล่าวถึงการเปิดเผย SQL โดยตรงใน API เป็นตัวเลือกที่แย่มาก GraphQL แม้จะเป็นชื่อ แต่ไม่ได้เป็นนามธรรมสำหรับ SQL แต่สำหรับแหล่งข้อมูลใด ๆ หรือแม้แต่บริการอื่น ๆ

หากคุณกำลังมองหาสิ่งที่เป็นนามธรรมที่อยู่ใกล้กับ SQL คุณอาจต้องการดูodata (ถ้าคุณทำงานในแบ็กเอนด์. NET แม้ว่าอาจมีการใช้งานอื่นอยู่)


0

ถ้าคุณต้องการเปิดเผย SQL เช่น GraphQL คุณอาจต้องการ GraphQL เพราะคุณจะต้องซ่อนข้อมูลสำคัญและเลือกสิ่งที่คุณต้องการแสดงใน API สิ่งนี้เพื่อความปลอดภัย

GraphQl และ SQL เป็นสิ่งที่แตกต่างกัน SQL เป็นภาษาสำหรับสืบค้น DataBase และ GraphQL เป็นเพียงการจัดการข้อมูลจาก API ใน API คุณจะต้องทำให้ schema ของคุณแสดงและแบบสอบถามเพื่อจัดการ ฯลฯ

ใน API ใด ๆ ที่คุณจะต้องทำสิ่งเหล่านั้นเพื่อความปลอดภัย แต่ถ้าคุณต้องการสิ่งที่เข้าถึงข้อมูลฟรีบางทีมันอาจจะทำงานคุณรู้ทางเลือกมากมายในโลกของซอฟต์แวร์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.