Merhaba arkadaşlar. Mayıs tatilinin ikinci bölümüne gitmeden önce, parkurda yeni bir akışın başlaması beklentisiyle tercüme ettiğimiz materyali sizlerle paylaşıyoruz.
Uygulama geliştiricileri, amaçlanan iş yüküne en uygun olanı seçmek için birden fazla operasyonel veritabanını karşılaştırarak çok zaman harcarlar. İhtiyaçlar, basitleştirilmiş veri modellemeyi, işlem garantilerini, okuma/yazma performansını, yatay ölçeklendirmeyi ve hata toleransını içerebilir. Geleneksel olarak seçim veritabanı kategorisiyle (SQL veya NoSQL) başlar, çünkü her kategori net bir ödünleşimler dizisi sunar. Düşük gecikme süresi ve yüksek verim açısından yüksek performans, genellikle tavizsiz bir gereklilik olarak görülür ve bu nedenle herhangi bir örnek veritabanı için gereklidir.
Bu makalenin amacı uygulama geliştiricilerinin uygulama veri modellemesi bağlamında SQL ve NoSQL arasında doğru seçimi yapmasına yardımcı olmaktır. Tablo oluşturma, bunları doldurma, tablodan veri okuma ve silme gibi veritabanı tasarımının temellerini kapsamak için PostgreSQL adlı bir SQL veritabanına ve Cassandra ve MongoDB adlı iki NoSQL veritabanına bakacağız. Bir sonraki makalede indekslere, işlemlere, JOIN'lere, TTL direktiflerine ve JSON tabanlı veritabanı tasarımına mutlaka bakacağız.
SQL ve NoSQL arasındaki fark nedir?
SQL veritabanları, ACID işlem garantileri aracılığıyla uygulama esnekliğinin yanı sıra, mevcut normalleştirilmiş ilişkisel veritabanı modellerinin üzerinde JOIN'leri beklenmedik şekillerde kullanarak verileri sorgulama yeteneklerini artırır.
Monolitik/tek düğümlü mimarileri ve artıklık için ana-bağımlı çoğaltma modelinin kullanımı göz önüne alındığında, geleneksel SQL veritabanları iki önemli özellikten yoksundur: doğrusal yazma ölçeklenebilirliği (yani birden fazla düğüm arasında otomatik bölümleme) ve otomatik/sıfır veri kaybı. Bu, alınan veri miktarının tek bir düğümün maksimum yazma verimini geçemeyeceği anlamına gelir. Ayrıca, hata toleransında (hiçbir şey paylaşılmayan mimaride) bazı geçici veri kayıplarının da dikkate alınması gerekir. Burada son taahhütlerin henüz köle kopyaya yansıtılmadığını aklınızda tutmanız gerekir. SQL veritabanlarında kesinti gerektirmeyen güncellemelerin elde edilmesi de zordur.
NoSQL veritabanları genellikle doğası gereği dağıtılır; içlerinde veriler bölümlere ayrılır ve birkaç düğüme dağıtılır. Denormalizasyon gerektirirler. Bu, gönderdiğiniz belirli isteklere yanıt vermek için girilen verilerin birkaç kez kopyalanması gerektiği anlamına gelir. Genel amaç, okumalar sırasında mevcut parça sayısını azaltarak yüksek performans elde etmektir. Bu, NoSQL'in sorgularınızı modellemenizi, SQL'in ise verilerinizi modellemenizi gerektirdiği anlamına gelir.
NoSQL, dağıtılmış bir kümede yüksek performans elde etmeye odaklanır ve bu, ACID işlem kaybı, JOIN'ler ve tutarlı küresel ikincil dizinler dahil olmak üzere birçok veritabanı tasarımı ödünleşiminin temel mantığıdır.
NoSQL veritabanları doğrusal yazma ölçeklenebilirliği ve yüksek hata toleransı sağlarken, işlem garantilerinin kaybının onları kritik görev verileri için uygunsuz hale getirdiğine dair bir tartışma var.
Aşağıdaki tabloda NoSQL'deki veri modellemenin SQL'den ne kadar farklı olduğu gösterilmektedir.
SQL ve NoSQL: Neden her ikisine de ihtiyaç var?
Amazon.com, Netflix, Uber ve Airbnb gibi çok sayıda kullanıcıya sahip gerçek dünya uygulamaları, karmaşık, çok yönlü görevleri yerine getirmekle görevlidir. Örneğin, Amazon.com gibi bir e-ticaret uygulamasının, kullanıcı bilgileri, ürünler, siparişler, faturalar gibi hafif, yüksek kritik verilerin yanı sıra ürün incelemeleri, destek mesajları, kullanıcı etkinliği, kullanıcı yorumları ve önerileri. Doğal olarak bu uygulamalar en az bir NoSQL veritabanının yanı sıra en az bir SQL veritabanına da güveniyor. Bölgeler arası ve küresel sistemlerde, bir NoSQL veritabanı, belirli bir bölgede çalışan güvenilir bir kaynak SQL veritabanında depolanan veriler için coğrafi olarak dağıtılmış bir önbellek olarak çalışır.
YugaByte DB, SQL ve NoSQL'i nasıl birleştirir?
Günlük odaklı karma depolama motoru, otomatik parçalama, parçalanmış dağıtılmış fikir birliği çoğaltması ve ACID dağıtılmış işlemler (Google Spanner'dan ilham alınarak) üzerine inşa edilen YugaByte DB, NoSQL (Cassandra & Redis) ile eşzamanlı olarak uyumlu dünyanın ilk açık kaynak veritabanıdır ve SQL (PostgreSQL). Aşağıdaki tabloda gösterildiği gibi, Cassandra ile uyumlu YugaByte DB API'si YCQL, tek ve çok anahtarlı ACID işlemleri ve küresel ikincil dizin kavramlarını NoSQL API'ye ekleyerek işlemsel NoSQL veritabanları çağını başlatıyor. Ayrıca PostgreSQL ile uyumlu YugaByte DB API'si YCQL, SQL API'ye doğrusal yazma ölçeklendirme ve otomatik hata toleransı kavramlarını ekleyerek dağıtılmış SQL veritabanlarını dünyaya getirir. YugaByte DB doğası gereği işlemsel olduğundan, NoSQL API artık görev açısından kritik veriler bağlamında kullanılabilir.
Daha önce makalede belirtildiği gibi
- Birincil iş yükünüz çok anahtarlı JOIN işlemleriyse YSQL'i seçerken anahtarlarınızın birden fazla düğüme dağıtılabileceğini ve bunun NoSQL'e göre daha yüksek gecikme ve/veya daha düşük aktarım hızıyla sonuçlanabileceğini anlayın.
- Aksi takdirde, tek seferde tek bir düğümden sunulan sorgular sonucunda daha iyi performans elde edeceğinizi aklınızda bulundurarak iki NoSQL API'sinden birini seçin. YugaByte DB, aynı anda birden fazla iş yükünü yönetmesi gereken gerçek dünyadaki karmaşık uygulamalar için tek bir operasyonel veritabanı olarak hizmet verebilir.
Bir sonraki bölümde yer alan Veri modelleme laboratuvarı, yerel veritabanlarının aksine PostgreSQL ve Cassandra API uyumlu YugaByte DB veritabanlarını temel almaktadır. Bu yaklaşım, iki farklı veritabanının tamamen bağımsız kümelerini kullanmak yerine, aynı veritabanı kümesinin iki farklı API'si (iki farklı bağlantı noktasında) ile etkileşim kurmanın kolaylığını vurgular.
Aşağıdaki bölümlerde, kapsanan veritabanlarının farklılıklarını ve bazı ortak noktalarını göstermek için veri modelleme laboratuvarına göz atacağız.
Veri Modelleme Laboratuvarı
Veritabanı kurulumu
Veri modeli tasarımına verilen önem (karmaşık dağıtım mimarileri yerine) göz önüne alındığında, veritabanlarını yerel makinedeki Docker kapsayıcılarına yükleyeceğiz ve ardından ilgili komut satırı kabuklarını kullanarak onlarla etkileşime gireceğiz.
PostgreSQL ve Cassandra uyumlu YugaByte DB veritabanı
mkdir ~/yugabyte && cd ~/yugabyte
wget https://downloads.yugabyte.com/yb-docker-ctl && chmod +x yb-docker-ctl
docker pull yugabytedb/yugabyte
./yb-docker-ctl create --enable_postgres
MongoDB
docker run --name my-mongo -d mongo:latest
Komut satırı erişimi
İlgili API'ler için komut satırı kabuğunu kullanarak veritabanlarına bağlanalım.
PostgreSQL
docker exec -it yb-postgres-n1 /home/yugabyte/postgres/bin/psql -p 5433 -U postgres
Kötü olayları önceden haber veren kimse
cqlsh
katalogda bin
.
CQL'in SQL'den ilham aldığını ve benzer tablo, satır, sütun ve dizin kavramlarına sahip olduğunu unutmayın. Bununla birlikte, bir NoSQL dili olarak, çoğunu diğer makalelerde de ele alacağımız belirli bir dizi sınırlama ekler.
docker exec -it yb-tserver-n1 /home/yugabyte/bin/cqlsh
MongoDB
docker exec -it my-mongo bash
cd bin
mongo
Tablo oluştur
Artık komut satırını kullanarak çeşitli işlemleri gerçekleştirmek için veritabanıyla etkileşime girebiliriz. Farklı sanatçılar tarafından yazılan şarkılarla ilgili bilgilerin depolandığı bir tablo oluşturarak başlayalım. Bu şarkılar bir albümün parçası olabilir. Ayrıca bir şarkının isteğe bağlı özellikleri arasında çıkış yılı, fiyatı, türü ve derecelendirmesi yer alır. Gelecekte ihtiyaç duyulabilecek ek özellikleri "etiketler" alanı aracılığıyla hesaba katmamız gerekiyor. Yarı yapılandırılmış verileri anahtar-değer çiftleri şeklinde saklayabilir.
PostgreSQL
CREATE TABLE Music (
Artist VARCHAR(20) NOT NULL,
SongTitle VARCHAR(30) NOT NULL,
AlbumTitle VARCHAR(25),
Year INT,
Price FLOAT,
Genre VARCHAR(10),
CriticRating FLOAT,
Tags TEXT,
PRIMARY KEY(Artist, SongTitle)
);
Kötü olayları önceden haber veren kimse
Cassandra'da tablo oluşturmak PostgreSQL'e çok benzer. Ana farklardan biri bütünlük kısıtlamalarının olmayışıdır (ör. NULL DEĞİL), ancak bu NoSQL veritabanının değil uygulamanın sorumluluğundadır.. Birincil anahtar, bir bölüm anahtarından (aşağıdaki örnekte Sanatçı sütunu) ve bir dizi kümeleme sütunundan (aşağıdaki örnekte SongTitle sütunu) oluşur. Bölüm anahtarı, satırın hangi bölüme/parçaya yerleştirilmesi gerektiğini belirler ve kümeleme sütunları, verilerin geçerli parça içinde nasıl düzenlenmesi gerektiğini gösterir.
CREATE KEYSPACE myapp;
USE myapp;
CREATE TABLE Music (
Artist TEXT,
SongTitle TEXT,
AlbumTitle TEXT,
Year INT,
Price FLOAT,
Genre TEXT,
CriticRating FLOAT,
Tags TEXT,
PRIMARY KEY(Artist, SongTitle)
);
MongoDB
MongoDB, verileri veritabanları (Veritabanı) (Cassandra'daki Keyspace'e benzer) halinde düzenler; burada Belgeler (bir tablodaki satırlara benzer) içeren Koleksiyonlar (tablolara benzer) bulunur. MongoDB'de temel olarak bir başlangıç şeması tanımlamaya gerek yoktur. Takım "veritabanını kullan"Aşağıda gösterilen, ilk çağrıda veritabanını başlatır ve yeni oluşturulan veritabanının içeriğini değiştirir. Koleksiyonların bile açıkça oluşturulmasına gerek yoktur; yalnızca ilk belgeyi yeni bir koleksiyona eklediğinizde otomatik olarak oluşturulurlar. MongoDB'nin varsayılan olarak test veritabanını kullandığını, dolayısıyla belirli bir veritabanı belirtmeden koleksiyon düzeyindeki tüm işlemlerin varsayılan olarak üzerinde çalışacağını unutmayın.
use myNewDatabase;
Bir tablo hakkında bilgi alma
PostgreSQL
d Music
Table "public.music"
Column | Type | Collation | Nullable | Default
--------------+-----------------------+-----------+----------+--------
artist | character varying(20) | | not null |
songtitle | character varying(30) | | not null |
albumtitle | character varying(25) | | |
year | integer | | |
price | double precision | | |
genre | character varying(10) | | |
criticrating | double precision | | |
tags | text | | |
Indexes:
"music_pkey" PRIMARY KEY, btree (artist, songtitle)
Kötü olayları önceden haber veren kimse
DESCRIBE TABLE MUSIC;
CREATE TABLE myapp.music (
artist text,
songtitle text,
albumtitle text,
year int,
price float,
genre text,
tags text,
PRIMARY KEY (artist, songtitle)
) WITH CLUSTERING ORDER BY (songtitle ASC)
AND default_time_to_live = 0
AND transactions = {'enabled': 'false'};
MongoDB
use myNewDatabase;
show collections;
Bir tabloya veri girme
PostgreSQL
INSERT INTO Music
(Artist, SongTitle, AlbumTitle,
Year, Price, Genre, CriticRating,
Tags)
VALUES(
'No One You Know', 'Call Me Today', 'Somewhat Famous',
2015, 2.14, 'Country', 7.8,
'{"Composers": ["Smith", "Jones", "Davis"],"LengthInSeconds": 214}'
);
INSERT INTO Music
(Artist, SongTitle, AlbumTitle,
Price, Genre, CriticRating)
VALUES(
'No One You Know', 'My Dog Spot', 'Hey Now',
1.98, 'Country', 8.4
);
INSERT INTO Music
(Artist, SongTitle, AlbumTitle,
Price, Genre)
VALUES(
'The Acme Band', 'Look Out, World', 'The Buck Starts Here',
0.99, 'Rock'
);
INSERT INTO Music
(Artist, SongTitle, AlbumTitle,
Price, Genre,
Tags)
VALUES(
'The Acme Band', 'Still In Love', 'The Buck Starts Here',
2.47, 'Rock',
'{"radioStationsPlaying": ["KHCR", "KBQX", "WTNR", "WJJH"], "tourDates": { "Seattle": "20150625", "Cleveland": "20150630"}, "rotation": Heavy}'
);
Kötü olayları önceden haber veren kimse
Genel ifade INSERT
Cassandra'dakiler PostgreSQL'dekilere çok benziyor. Ancak anlambilimde büyük bir fark var. Cassandra'da INSERT
aslında bir operasyon UPSERT
, eğer satır zaten mevcutsa, son değerlerin satıra eklendiği yer.
Veri girişi PostgreSQL'e benzer
INSERT
yukarıda
.
MongoDB
MongoDB, Cassandra gibi bir NoSQL veritabanı olmasına rağmen ekleme işleminin Cassandra'nın anlamsal davranışıyla hiçbir ortak yanı yoktur. MongoDB'de UPSERT
Bu da onu PostgreSQL'e benzer kılıyor. Varsayılan verileri eklemeden _idspecified
koleksiyona yeni bir belgenin eklenmesine neden olacaktır.
db.music.insert( {
artist: "No One You Know",
songTitle: "Call Me Today",
albumTitle: "Somewhat Famous",
year: 2015,
price: 2.14,
genre: "Country",
tags: {
Composers: ["Smith", "Jones", "Davis"],
LengthInSeconds: 214
}
}
);
db.music.insert( {
artist: "No One You Know",
songTitle: "My Dog Spot",
albumTitle: "Hey Now",
price: 1.98,
genre: "Country",
criticRating: 8.4
}
);
db.music.insert( {
artist: "The Acme Band",
songTitle: "Look Out, World",
albumTitle:"The Buck Starts Here",
price: 0.99,
genre: "Rock"
}
);
db.music.insert( {
artist: "The Acme Band",
songTitle: "Still In Love",
albumTitle:"The Buck Starts Here",
price: 2.47,
genre: "Rock",
tags: {
radioStationsPlaying:["KHCR", "KBQX", "WTNR", "WJJH"],
tourDates: {
Seattle: "20150625",
Cleveland: "20150630"
},
rotation: "Heavy"
}
}
);
Tablo Sorgulama
Sorgu oluşturma açısından SQL ve NoSQL arasındaki belki de en önemli fark, kullanılan dildir. FROM
и WHERE
. SQL ifadeden sonra izin verir FROM
birden fazla tablo seçin ve şununla ifade edin: WHERE
herhangi bir karmaşıklıkta olabilir (işlemler dahil) JOIN
tablolar arasında). Ancak NoSQL, ciddi bir sınırlama getirme eğilimindedir. FROM
ve yalnızca belirtilen bir tabloyla çalışın ve WHERE
birincil anahtarın her zaman belirtilmesi gerekir. Bu, daha önce bahsettiğimiz NoSQL performans artışıyla bağlantılıdır. Bu arzu, herhangi bir çapraz tablo ve çapraz anahtar etkileşiminde mümkün olan her türlü azalmaya yol açar. Bir isteğe yanıt verirken düğümler arası iletişimde büyük bir gecikmeye neden olabilir ve bu nedenle genel olarak bundan kaçınılması en iyisidir. Örneğin Cassandra, sorguların belirli işleçlerle sınırlı olmasını gerektirir (yalnızca =, IN, <, >, =>, <=
) bölüm anahtarlarında, ikincil bir dizin isteğinde bulunulması haricinde (burada yalnızca = operatörüne izin verilir).
PostgreSQL
Aşağıda bir SQL veritabanı tarafından kolayca yürütülebilecek üç sorgu örneği verilmiştir.
- Bir sanatçının tüm şarkılarını görüntüleyin;
- Başlığın ilk kısmıyla eşleşen sanatçının tüm şarkılarını görüntüleyin;
- Başlığında belirli bir kelime bulunan ve fiyatı 1.00'den düşük olan bir sanatçının tüm şarkılarını görüntüleyin.
SELECT * FROM Music
WHERE Artist='No One You Know';
SELECT * FROM Music
WHERE Artist='No One You Know' AND SongTitle LIKE 'Call%';
SELECT * FROM Music
WHERE Artist='No One You Know' AND SongTitle LIKE '%Today%'
AND Price > 1.00;
Kötü olayları önceden haber veren kimse
Yukarıda listelenen PostgreSQL sorgularından yalnızca ilki Cassandra'da değişmeden çalışacaktır, çünkü operatör LIKE
gibi kümeleme sütunlarına uygulanamaz SongTitle
. Bu durumda yalnızca operatörlere izin verilir =
и IN
.
SELECT * FROM Music
WHERE Artist='No One You Know';
SELECT * FROM Music
WHERE Artist='No One You Know' AND SongTitle IN ('Call Me Today', 'My Dog Spot')
AND Price > 1.00;
MongoDB
Önceki örneklerde gösterildiği gibi MongoDB'de sorgu oluşturmanın ana yöntemi: music
aşağıdaki örnekte), bu nedenle birden fazla koleksiyonun sorgulanması yasaktır.
db.music.find( {
artist: "No One You Know"
}
);
db.music.find( {
artist: "No One You Know",
songTitle: /Call/
}
);
Bir tablonun tüm satırlarını okuma
Tüm satırların okunması, daha önce incelediğimiz sorgu modelinin özel bir durumudur.
PostgreSQL
SELECT *
FROM Music;
Kötü olayları önceden haber veren kimse
Yukarıdaki PostgreSQL örneğine benzer.
MongoDB
db.music.find( {} );
Bir tablodaki verileri düzenleme
PostgreSQL
PostgreSQL talimatlar sağlar UPDATE
Verileri değiştirmek için. Hiç fırsatı yok UPSERT
, dolayısıyla satır artık veritabanında değilse bu ifade başarısız olur.
UPDATE Music
SET Genre = 'Disco'
WHERE Artist = 'The Acme Band' AND SongTitle = 'Still In Love';
Kötü olayları önceden haber veren kimse
Cassandra'nın sahip olduğu UPDATE
PostgreSQL'e benzer. UPDATE
aynı anlamlara sahip UPSERT
, benzer INSERT
.
Yukarıdaki PostgreSQL örneğine benzer.
MongoDB
Operasyon UPSERT
. Birden fazla belgeyi güncelleme ve benzer davranışlar UPSERT
işlem için ek bayraklar ayarlanarak uygulanabilir. Örneğin aşağıdaki örnekte belirli bir sanatçının türü, şarkısına göre güncellenmektedir.
db.music.update(
{"artist": "The Acme Band"},
{
$set: {
"genre": "Disco"
}
},
{"multi": true, "upsert": true}
);
Bir tablodan veriyi kaldırmak
PostgreSQL
DELETE FROM Music
WHERE Artist = 'The Acme Band' AND SongTitle = 'Look Out, World';
Kötü olayları önceden haber veren kimse
Yukarıdaki PostgreSQL örneğine benzer.
MongoDB
MongoDB'nin belgeleri silmek için iki tür işlemi vardır -
db.music.deleteMany( {
artist: "The Acme Band"
}
);
Bir tabloyu silme
PostgreSQL
DROP TABLE Music;
Kötü olayları önceden haber veren kimse
Yukarıdaki PostgreSQL örneğine benzer.
MongoDB
db.music.drop();
Sonuç
SQL ve NoSQL arasında seçim yapma konusundaki tartışma 10 yılı aşkın süredir devam ediyor. Bu tartışmanın iki ana yönü vardır: veritabanı motoru mimarisi (monolitik, işlemsel SQL'e karşı dağıtılmış, işlemsel olmayan NoSQL) ve veritabanı tasarımı yaklaşımı (verilerinizi SQL'de modellemek ve sorgularınızı NoSQL'de modellemek).
YugaByte DB gibi dağıtılmış bir işlemsel veritabanıyla, veritabanı mimarisi hakkındaki tartışmalar kolayca sona erdirilebilir. Veri hacimleri tek bir düğüme yazılabilenden daha büyük hale geldikçe, otomatik parçalama/yeniden dengeleme ile doğrusal yazma ölçeklenebilirliğini destekleyen tamamen dağıtılmış bir mimari gerekli hale gelir.
Ayrıca makalelerden birinde belirtildiği gibi
Veritabanı tasarımı tartışmasına geri dönersek, her iki tasarım yaklaşımının da (SQL ve NoSQL) herhangi bir karmaşık gerçek dünya uygulaması için gerekli olduğunu söylemek doğru olur. SQL "veri modelleme" yaklaşımı, geliştiricilerin değişen iş gereksinimlerini daha kolay karşılamasına olanak tanırken, NoSQL "sorgu modelleme" yaklaşımı, aynı geliştiricilerin büyük hacimli veriler üzerinde düşük gecikme ve yüksek verimle çalışmasına olanak tanır. Bu nedenle YugaByte DB, yaklaşımlardan birini desteklemek yerine SQL ve NoSQL API'lerini ortak bir çekirdekte sağlar. Ayrıca YugaByte DB, PostgreSQL ve Cassandra gibi popüler veritabanı dilleriyle uyumluluk sağlayarak geliştiricilerin dağıtılmış, yüksek tutarlılığa sahip bir veritabanı motoruyla çalışmak için başka bir dil öğrenmelerine gerek kalmamasını sağlar.
Bu makalede veritabanı tasarımının temellerinin PostgreSQL, Cassandra ve MongoDB arasında nasıl farklılaştığına baktık. Gelecek makalelerde dizinler, işlemler, JOIN'ler, TTL yönergeleri ve JSON belgeleri gibi gelişmiş tasarım kavramlarına derinlemesine bakacağız.
Hafta sonunun geri kalanının harika geçmesini diliyor ve sizi davet ediyoruz
Kaynak: habr.com