Neden GraphQL yerine SQL kullanmıyorsunuz?


20

Geçenlerde RESTful'dan daha üstün olduğunu iddia eden GraphQL'i öğrendim. Ancak, neden SQL ifadelerini bir HTTP GET isteğine koymadığımızı merak etmeye başladım.

Örneğin, GraphQL'de

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

Hangi SQL karşılığı daha basit değil

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;

Belki sorguyu URL olarak kodlayabilir ve sunucuya gönderebiliriz

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

Evet, sorgu URL'si çok uzun olabilir, ancak REST uyumluluğunu önemsemiyorsanız bir POST isteğinin gövdesine koyabilirsiniz. (Bu arada, REST'in mantıklı olması için HTTP RFC'nin revize edilmesi gerektiğini düşünüyorum: sorgu dizelerinin uzunluğunu sınırlamak, uygulamayı en başta spesifikasyon ile karıştırıyor)

SQL'in istemciden doğrudan yayınlanması,

  1. GraphQL'i ayrıştırmak için sunucu tarafı kod / kütüphane gerekmez, bu da geliştirme süresini azaltır.
  2. GraphQL'i ayrıştırmak ve çalışma zamanını azaltmak için sunucu tarafı ek yüke gerek yoktur.
  3. SQL ifadeleri GraphQL'den çok daha esnektir, çünkü (çoğu durumda) ikincisi yine de SQL'e düşer.
  4. Herkes SQL'i bilir.

Peki, GraphQL'in SQL'e göre avantajları nelerdir?


41
Küçük Bobby Tablolar.
Philip Kendall

1
1. Hala size karmaşık karmaşık SQL sorguları ile DoS yapabilirsiniz. 2. Kötü niyetli bir oyuncunun geçerli bir anahtar edinme şansı yoktur ...
Philip Kendall

3
@PhilipKendall Haklısınız, ancak GraphQL (veya REST veya herhangi bir şekilde) kullanmak da bu sorunları çözmez, değil mi?
nalzok

7
@nalzok: SQL Turing tamamlandı, yani statik olarak doğrulamak imkansız.
Jörg W Mittag

3
Bunun neden korkunç bir fikir olduğunu anlamak çok basit. Kendiniz uygulayın. Bir noktada, zamanınızı çoğunlukla 1 şeyde yatırım yaptığınızı fark edeceksiniz: güvenlik. Çok geç değil, bir sinirli TOAD uyguladığınız için biraz üzüleceksiniz. Ardından, tüm sistemdeki satırları eşlemenin ne kadar zor olduğunu anlayacak ve her iki taraftaki ORM tekerleğini yeniden keşfetmeye çalışacaksınız: istemci ve sunucu. Vazgeçtiğiniz zaman, Başbakanınız sizden rapor isteyecektir: Kullanıcıların servisi nasıl gidiyor ? Yapıldı mı? "...
Laiv

Yanıtlar:


30

Temel olarak, soyutlama.

SQL, müşterilerinizin tam veritabanı yapınızı bilmelerini gerektirir ki bu da iyi değildir. Bunun da ötesinde, girdi olarak gönderilen değere dayalı özel işlemler gerçekleştirmek için SQL'i analiz etmek gerçekten zor bir şeydir. Sadece bundan sorumlu olan tüm yazılımlar var. Bunların ne olduğunu biliyor musun? Veritabanlarını tahmin ettiyseniz, haklısınız.

SQL'i doğrudan göstermediğiniz için, API tüketicisini veritabanınızın dahili sunumuyla sınırlamıyorsunuz. Sadece ortaya çıkarmak istediğiniz şeyi kolayca ortaya koyabilirsiniz.

API istemcileri yalnızca soyutlamaya bağlı olduğu için, API girişi ile gerçek veritabanı (güvenlik, önbellekleme, tek bir istek üzerine birden çok veritabanından veri yükleme, ...) arasında olabildiğince çok katmana sahip olmakta özgürsünüz.

Kamu hizmetleri için, bir veritabanını doğrudan ortaya koymak asla doğru bir yaklaşım değildir. Bununla birlikte, birkaç dahili sisteminiz varsa, yaklaşımınız mantıklı olabilir, ancak o zaman bile, gelmeye çalışmak yerine veritabanı kimlik bilgilerini Uygulama B'ye vererek Uygulama A'nın veritabanına doğrudan Uygulama B'den bağlanmak daha kolay olabilir. veritabanı SQL dili için özel bir HTTP arayüzü ile.


RDBMS'de gerçek sorguyu gerçekleştirmeden önce neden URL'yi (veya SQL sorgusunu) Redis'teki anahtarlarla karşılaştıramıyorum?

Çünkü kolay değil. Birisi çok basit bir sorgu kullansa bile, örneğin:

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'

sonucun doğru şekilde önbelleğe alındığından nasıl emin olursunuz? Bu sorgu yeni satırlar içerir, ancak birisi de sorguyu aşağıdaki şekilde yazabilir:

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'

ve yine de yukarıdaki ile aynı şekilde önbelleğe alınması gerekiyordu. Özellikle bir dize aramanın yeni bir satır içerdiği bir yer ekledim, bu yüzden sadece satır sonlarını bulmak ve bir boşlukla değiştirmek burada işe yaramayacak, isteği doğru ayrıştırma çok daha karmaşık olacaktır.

Ve bunu düzeltseniz bile, başka bir sorgu koşulların sırasını değiştirebilir ve sorgu aşağıdaki gibi görünür:

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'

ve başka bir istek aşağıdaki WHEREgibi yedekli bir argüman içerebilir :

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üm bu sorguların yine de aynı sonucu döndürmesi gerekiyor, aynı şekilde önbelleğe alınmalıdır. Ancak olası tüm seçeneklerin ele alınması neredeyse imkansızdır. Bu nedenle URL'yi Redis'teki anahtarlarla karşılaştıramazsınız.


Bu güzel bir cevap ama lütfen güncellemeye bakın.
nalzok

19

Teorik olarak, böyle bir SQL arabirimini açığa çıkarmamak için hiçbir neden yoktur.

Pratikte SQL, ortaya çıkarmak istediğiniz güvenlik kapsamıyla etkili bir şekilde sınırlandırılamayacak kadar güçlüdür.

Yalnızca okuma erişimine izin verseniz bile, kötü bir sorgu kaynakları yine de tutabilir.

GraphQL gibi diğer diller gösterilecek şekilde tasarlanmıştır. Sadece kullanıcılara zaten görebilecekleri bir filtre seçeneği sunuyorlar.

Bu dilleri kullanmanın yararı, kullanıcıların SQL'de çalışmasını durdurmak ve bunları tablodan çıkarmak istediğiniz her şeyi yapmalarıdır.


2
Cevabınız için teşekkürler, ancak GraphQL'in kaynak boşaltma problemini nasıl çözdüğünü açıklayabilir misiniz? Kaba bir GraphQL sorgusu hala “her film ve aktörleri hakkında her şeyi anlat” diyebilir, bu da büyük bir grafiğe neden olur ve DBMS ve ağımı tüketir.
nalzok

Ama ben tablonuzu kilitler ve diğer kullanıcıların hiç sorgu çalışmasını engelleyecek özyinelemeli bir SQL sorgusu yazabilirsiniz
Ewan

4
sorun tablolara erişimi kısıtlamak ya da silmek değil, SQL'in kesme karmaşıklığıdır. geçici tablo oluşturulmasına izin verecek misiniz? CLI yürütmeye ne dersiniz? döngüler? işlemler? alt seçimler? imleçleri? bu şeylerin kullanımının ne zaman kabul edilebilir olduğunu ve 'kötü' olduğunu ne zaman ayırt edeceksiniz
Ewan

2

Diğerlerinin de belirttiği gibi, SQL'i doğrudan api'de göstermek çok kötü bir seçenektir. GraphQL, adına rağmen, SQL için bir soyutlama değil, herhangi bir veri deposu ve hatta diğer hizmetler için bir soyutlamadır.

SQL'e daha yakın bir soyutlama arıyorsanız, odata'ya bakmak isteyebilirsiniz (.NET arka uçlarında çalışıyorsanız, belki de başka uygulamalar vardır).


0

SQL'i GraphQL gibi göstermek istiyorsanız, GraphQL gibi bir şeye ihtiyacınız olacaktır, çünkü önemli bilgileri gizlemeniz ve API'da ne göstermek istediğinizi seçmeniz gerekir, bu güvenlik için.

GraphQl ve SQL farklı şeylerdir, SQL, DataBase'i sorgulamak için kullanılan dildir ve GraphQL, yalnızca API'daki verileri yönetmek içindir, API'de, şemalarınızı göstermek için şemalar yapmanız ve bunları yönetmek için sorgular vb.

herhangi bir API'da bunları basitçe güvenlik için yapmanız gerekir, ancak ücretsiz veri erişimi olan bir şey istiyorsanız belki işe yarayabilir, yazılım dünyasında çok fazla alternatif biliyorsunuz

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.