Dasar-dasar Desain Basis Data - Membandingkan PostgreSQL, Cassandra, dan MongoDB

Halo teman teman. Sebelum berangkat liburan bulan Mei bagian kedua, kami berbagi dengan Anda materi yang kami terjemahkan untuk mengantisipasi peluncuran aliran baru di kursus "DBMS Relasional".

Dasar-dasar Desain Basis Data - Membandingkan PostgreSQL, Cassandra, dan MongoDB

Pengembang aplikasi menghabiskan banyak waktu membandingkan beberapa database operasional untuk memilih salah satu yang paling sesuai dengan beban kerja yang diinginkan. Kebutuhannya mungkin mencakup pemodelan data yang disederhanakan, jaminan transaksional, kinerja baca/tulis, penskalaan horizontal, dan toleransi kesalahan. Secara tradisional, pilihan dimulai dengan kategori database, SQL atau NoSQL, karena setiap kategori menyajikan serangkaian trade-off yang jelas. Performa tinggi dalam hal latensi rendah dan throughput tinggi umumnya dipandang sebagai persyaratan non-trade-off dan oleh karena itu penting untuk database sampel mana pun.

Tujuan artikel ini adalah untuk membantu pengembang aplikasi membuat pilihan yang tepat antara SQL dan NoSQL dalam konteks pemodelan data aplikasi. Kita akan melihat satu database SQL, yaitu PostgreSQL, dan dua database NoSQL, Cassandra dan MongoDB, untuk membahas dasar-dasar desain database, seperti membuat tabel, mengisinya, membaca data dari tabel, dan menghapusnya. Pada artikel berikutnya, kita pasti akan melihat indeks, transaksi, GABUNG, arahan TTL, dan desain database berbasis JSON.

Apa perbedaan antara SQL dan NoSQL?

Basis data SQL meningkatkan fleksibilitas aplikasi melalui jaminan transaksional ACID, serta kemampuannya untuk mengkueri data menggunakan GABUNG dengan cara yang tidak terduga di atas model basis data relasional yang dinormalisasi.

Mengingat arsitektur monolitik/node tunggal dan penggunaan model replikasi master-slave untuk redundansi, database SQL tradisional tidak memiliki dua fitur penting - skalabilitas penulisan linier (yaitu partisi otomatis di beberapa node) dan kehilangan data otomatis/nol. Artinya, jumlah data yang diterima tidak boleh melebihi throughput tulis maksimum dari satu node. Selain itu, beberapa kehilangan data sementara harus diperhitungkan dalam toleransi kesalahan (dalam arsitektur shared-nothing). Di sini Anda perlu mengingat bahwa komitmen terbaru belum tercermin dalam salinan budak. Pembaruan non-downtime juga sulit dicapai dalam database SQL.

Basis data NoSQL biasanya didistribusikan secara alami, mis. di dalamnya, data dibagi menjadi beberapa bagian dan didistribusikan ke beberapa node. Mereka memerlukan denormalisasi. Artinya data yang dimasukkan juga harus disalin beberapa kali untuk menanggapi permintaan spesifik yang Anda kirimkan. Sasaran keseluruhannya adalah mendapatkan performa tinggi dengan mengurangi jumlah pecahan yang tersedia selama pembacaan. Ini menyiratkan bahwa NoSQL mengharuskan Anda memodelkan kueri Anda, sedangkan SQL mengharuskan Anda memodelkan data Anda.

NoSQL berfokus pada pencapaian kinerja tinggi dalam cluster terdistribusi dan ini adalah alasan yang mendasari banyak pengorbanan desain database yang mencakup kehilangan transaksi ACID, GABUNG, dan indeks sekunder global yang konsisten.

Ada argumen bahwa meskipun database NoSQL memberikan skalabilitas penulisan linier dan toleransi kesalahan yang tinggi, hilangnya jaminan transaksional membuatnya tidak cocok untuk data yang sangat penting.

Tabel berikut menunjukkan perbedaan pemodelan data di NoSQL dengan SQL.

Dasar-dasar Desain Basis Data - Membandingkan PostgreSQL, Cassandra, dan MongoDB

SQL dan NoSQL: Mengapa keduanya diperlukan?

Aplikasi dunia nyata dengan jumlah pengguna yang besar, seperti Amazon.com, Netflix, Uber, dan Airbnb, ditugaskan untuk melakukan tugas yang kompleks dan memiliki banyak aspek. Misalnya, aplikasi e-niaga seperti Amazon.com perlu menyimpan data yang ringan dan sangat penting seperti informasi pengguna, produk, pesanan, faktur, serta data yang berat dan kurang sensitif seperti ulasan produk, pesan dukungan, aktivitas pengguna, ulasan dan rekomendasi pengguna. Tentu saja, aplikasi ini mengandalkan setidaknya satu database SQL dan setidaknya satu database NoSQL. Dalam sistem lintas regional dan global, database NoSQL beroperasi sebagai cache yang terdistribusi secara geografis untuk data yang disimpan dalam database SQL sumber tepercaya yang berjalan di wilayah tertentu.

Bagaimana YugaByte DB menggabungkan SQL dan NoSQL?

Dibangun di atas mesin penyimpanan campuran berorientasi log, auto-sharding, replikasi konsensus terdistribusi sharded, dan transaksi terdistribusi ACID (terinspirasi oleh Google Spanner), YugaByte DB adalah database sumber terbuka pertama di dunia yang secara bersamaan kompatibel dengan NoSQL (Cassandra & Redis) dan SQL (PostgreSQL). Seperti yang ditunjukkan pada tabel di bawah, YCQL, YugaByte DB API yang kompatibel dengan Cassandra, menambahkan konsep transaksi ACID tunggal dan multi-kunci serta indeks sekunder global ke API NoSQL, sehingga mengantarkan era database NoSQL transaksional. Selain itu, YCQL, YugaByte DB API yang kompatibel dengan PostgreSQL, menambahkan konsep penskalaan tulis linier dan toleransi kesalahan otomatis ke SQL API, menghadirkan database SQL terdistribusi ke seluruh dunia. Karena YugaByte DB bersifat transaksional, API NoSQL kini dapat digunakan dalam konteks data yang sangat penting.

Dasar-dasar Desain Basis Data - Membandingkan PostgreSQL, Cassandra, dan MongoDB

Seperti yang telah dijelaskan sebelumnya pada artikel tersebut "Memperkenalkan YSQL: API SQL Terdistribusi yang Kompatibel dengan PostgreSQL untuk YugaByte DB", pilihan antara SQL atau NoSQL di YugaByte DB bergantung sepenuhnya pada karakteristik beban kerja yang mendasarinya:

  • Jika beban kerja utama Anda adalah operasi GABUNG multi-kunci, maka saat memilih YSQL, pahami bahwa kunci Anda mungkin didistribusikan ke beberapa node, sehingga menghasilkan latensi lebih tinggi dan/atau throughput lebih rendah dibandingkan NoSQL.
  • Jika tidak, pilih salah satu dari dua API NoSQL, ingatlah bahwa Anda akan mendapatkan performa yang lebih baik sebagai hasil kueri yang disajikan dari satu node pada satu waktu. YugaByte DB dapat berfungsi sebagai database operasional tunggal untuk aplikasi kompleks di dunia nyata yang perlu mengelola beberapa beban kerja secara bersamaan.

Lab pemodelan data di bagian selanjutnya didasarkan pada database YugaByte DB yang kompatibel dengan PostgreSQL dan Cassandra API, bukan database asli. Pendekatan ini menekankan kemudahan berinteraksi dengan dua API berbeda (pada dua port berbeda) dari cluster database yang sama, dibandingkan menggunakan cluster yang sepenuhnya independen dari dua database berbeda.
Pada bagian berikut, kita akan melihat lab pemodelan data untuk mengilustrasikan perbedaan dan beberapa kesamaan dari database yang dibahas.

Laboratorium Pemodelan Data

Instalasi basis data

Mengingat penekanan pada desain model data (daripada arsitektur penerapan yang kompleks), kami akan menginstal database di container Docker pada mesin lokal dan kemudian berinteraksi dengannya menggunakan shell baris perintah masing-masing.

Basis data YugaByte DB yang kompatibel dengan PostgreSQL & Cassandra

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

Akses baris perintah

Mari terhubung ke database menggunakan shell baris perintah untuk API yang sesuai.

PostgreSQL

psql adalah shell baris perintah untuk berinteraksi dengan PostgreSQL. Untuk kemudahan penggunaan, YugaByte DB hadir dengan psql tepat di folder bin.

docker exec -it yb-postgres-n1 /home/yugabyte/postgres/bin/psql -p 5433 -U postgres

Cassandra

cqlsh adalah shell baris perintah untuk berinteraksi dengan Cassandra dan database yang kompatibel melalui CQL (Cassandra Query Language). Untuk kemudahan penggunaan, YugaByte DB hadir dengan cqlsh di katalog bin.
Perhatikan bahwa CQL terinspirasi oleh SQL dan memiliki konsep tabel, baris, kolom, dan indeks yang serupa. Namun, sebagai bahasa NoSQL, ia menambahkan serangkaian batasan tertentu, yang sebagian besar juga akan kami bahas di artikel lain.

docker exec -it yb-tserver-n1 /home/yugabyte/bin/cqlsh

MongoDB

mongo adalah shell baris perintah untuk berinteraksi dengan MongoDB. Itu dapat ditemukan di direktori bin instalasi MongoDB.

docker exec -it my-mongo bash 
cd bin
mongo

Buat tabel

Sekarang kita dapat berinteraksi dengan database untuk melakukan berbagai operasi menggunakan baris perintah. Mari kita mulai dengan membuat tabel yang menyimpan informasi tentang lagu-lagu yang ditulis oleh berbagai artis. Lagu-lagu ini mungkin merupakan bagian dari album. Atribut opsional untuk sebuah lagu juga adalah tahun rilis, harga, genre, dan rating. Kita perlu memperhitungkan atribut tambahan yang mungkin diperlukan di masa mendatang melalui kolom "tag". Itu dapat menyimpan data semi-terstruktur dalam bentuk pasangan nilai kunci.

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)
);	

Cassandra

Membuat tabel di Cassandra sangat mirip dengan PostgreSQL. Salah satu perbedaan utamanya adalah kurangnya batasan integritas (misalnya NOT NULL), namun ini adalah tanggung jawab aplikasi, bukan database NoSQL.. Kunci utama terdiri dari kunci partisi (kolom Artis pada contoh di bawah) dan sekumpulan kolom pengelompokan (kolom Judul Lagu pada contoh di bawah). Kunci partisi menentukan di partisi/shard mana baris harus ditempatkan, dan kolom pengelompokan menunjukkan bagaimana data harus diatur dalam shard saat ini.

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 mengatur data ke dalam basis data (Database) (mirip dengan Keyspace di Cassandra), dimana terdapat Koleksi (mirip dengan tabel) yang berisi Dokumen (mirip dengan baris dalam tabel). Di MongoDB, pada dasarnya tidak perlu mendefinisikan skema awal. Tim "gunakan basis data", yang ditunjukkan di bawah, membuat instance database pada panggilan pertama dan mengubah konteks database yang baru dibuat. Bahkan koleksi tidak perlu dibuat secara eksplisit; mereka dibuat secara otomatis, cukup ketika Anda menambahkan dokumen pertama ke koleksi baru. Perhatikan bahwa MongoDB menggunakan database pengujian secara default, sehingga operasi tingkat koleksi apa pun tanpa menentukan database tertentu akan berjalan di dalamnya secara default.

use myNewDatabase;

Mendapatkan informasi tentang tabel
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)

Cassandra

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;

Memasukkan data ke dalam tabel
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}'
);

Cassandra

Ekspresi keseluruhan INSERT di Cassandra terlihat sangat mirip dengan di PostgreSQL. Namun, ada satu perbedaan besar dalam semantik. Di Cassandra INSERT sebenarnya adalah sebuah operasi UPSERT, dimana nilai terakhir ditambahkan ke baris jika baris tersebut sudah ada.

Entri data mirip dengan PostgreSQL INSERT atas

.

MongoDB

Meskipun MongoDB adalah database NoSQL seperti Cassandra, operasi penyisipannya tidak memiliki kesamaan dengan perilaku semantik Cassandra. Di MongoDB memasukkan() tidak memiliki peluang UPSERT, yang membuatnya mirip dengan PostgreSQL. Menambahkan data default tanpa _idspecified akan menyebabkan dokumen baru ditambahkan ke koleksi.

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"
}
}
);

Kueri Tabel

Mungkin perbedaan paling signifikan antara SQL dan NoSQL dalam hal konstruksi kueri adalah bahasa yang digunakan FROM ΠΈ WHERE. SQL memungkinkan setelah ekspresi FROM pilih beberapa tabel, dan ekspresi dengan WHERE dapat berupa kompleksitas apa pun (termasuk operasi JOIN antar tabel). Namun, NoSQL cenderung menerapkan batasan yang ketat FROM, dan hanya bekerja dengan satu tabel tertentu, dan masuk WHERE, kunci utama harus selalu ditentukan. Hal ini terkait dengan peningkatan kinerja NoSQL yang telah kita bicarakan sebelumnya. Keinginan ini mengarah pada setiap kemungkinan pengurangan interaksi lintas tabel dan lintas kunci. Hal ini dapat menyebabkan penundaan yang besar dalam komunikasi antar-node saat merespons permintaan dan oleh karena itu sebaiknya dihindari secara umum. Misalnya, Cassandra mengharuskan kueri dibatasi pada operator tertentu (hanya =, IN, <, >, =>, <=) pada kunci partisi, kecuali saat meminta indeks sekunder (hanya operator = yang diperbolehkan di sini).

PostgreSQL

Di bawah ini adalah tiga contoh kueri yang dapat dengan mudah dieksekusi oleh database SQL.

  • Menampilkan semua lagu oleh artis;
  • Menampilkan semua lagu dari artis yang cocok dengan bagian pertama judulnya;
  • Menampilkan semua lagu karya artis yang memiliki kata tertentu di judulnya dan harganya kurang dari 1.00.
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;

Cassandra

Dari kueri PostgreSQL yang tercantum di atas, hanya kueri pertama yang akan berfungsi tanpa perubahan di Cassandra, karena operatornya LIKE tidak dapat diterapkan pada kolom pengelompokan seperti SongTitle. Dalam hal ini, hanya operator yang diperbolehkan = ΠΈ 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

Seperti yang ditunjukkan pada contoh sebelumnya, metode utama untuk membuat query di MongoDB adalah db.koleksi.temukan(). Metode ini secara eksplisit berisi nama koleksi (music pada contoh di bawah), jadi menanyakan beberapa koleksi dilarang.

db.music.find( {
  artist: "No One You Know"
 } 
);
db.music.find( {
  artist: "No One You Know",
  songTitle: /Call/
 } 
);

Membaca semua baris tabel

Membaca semua baris hanyalah kasus khusus dari pola kueri yang kita lihat sebelumnya.

PostgreSQL

SELECT * 
FROM Music;

Cassandra

Mirip dengan contoh PostgreSQL di atas.

MongoDB

db.music.find( {} );

Mengedit data dalam tabel

PostgreSQL

PostgreSQL memberikan instruksi UPDATE untuk mengubah data. Dia tidak punya peluang UPSERT, jadi pernyataan ini akan gagal jika baris tersebut tidak lagi ada di database.

UPDATE Music
SET Genre = 'Disco'
WHERE Artist = 'The Acme Band' AND SongTitle = 'Still In Love';

Cassandra

Cassandra punya UPDATE mirip dengan PostgreSQL. UPDATE memiliki semantik yang sama UPSERT, menyukai INSERT.

Mirip dengan contoh PostgreSQL di atas.

MongoDB
Operasi memperbarui() di MongoDB dapat sepenuhnya memperbarui dokumen yang ada atau hanya memperbarui bidang tertentu. Secara default, ini hanya memperbarui satu dokumen dengan semantik dinonaktifkan UPSERT. Memperbarui banyak dokumen dan perilaku serupa UPSERT dapat diterapkan dengan menyetel tanda tambahan untuk operasi tersebut. Misalnya, pada contoh di bawah, genre artis tertentu diperbarui berdasarkan lagunya.

db.music.update(
  {"artist": "The Acme Band"},
  { 
    $set: {
      "genre": "Disco"
    }
  },
  {"multi": true, "upsert": true}
);

Menghapus data dari tabel

PostgreSQL

DELETE FROM Music
WHERE Artist = 'The Acme Band' AND SongTitle = 'Look Out, World';

Cassandra

Mirip dengan contoh PostgreSQL di atas.

MongoDB

MongoDB memiliki dua jenis operasi untuk menghapus dokumen - hapusSatu() /deleteMany() ΠΈ menghapus(). Kedua jenis ini menghapus dokumen tetapi memberikan hasil yang berbeda.

db.music.deleteMany( {
        artist: "The Acme Band"
    }
);

Menghapus tabel

PostgreSQL

DROP TABLE Music;

Cassandra

Mirip dengan contoh PostgreSQL di atas.

MongoDB

db.music.drop();

Kesimpulan

Perdebatan mengenai pilihan antara SQL dan NoSQL telah berlangsung selama lebih dari 10 tahun. Ada dua aspek utama dalam perdebatan ini: arsitektur mesin basis data (monolitik, SQL transaksional vs terdistribusi, NoSQL non-transaksional) dan pendekatan desain basis data (memodelkan data Anda dalam SQL vs memodelkan kueri Anda di NoSQL).

Dengan database transaksional terdistribusi seperti YugaByte DB, perdebatan tentang arsitektur database dapat dengan mudah dihentikan. Ketika volume data menjadi lebih besar daripada yang dapat ditulis ke satu node, arsitektur terdistribusi penuh yang mendukung skalabilitas penulisan linier dengan sharding/penyeimbangan ulang otomatis menjadi diperlukan.

Selain itu seperti yang tertuang dalam salah satu artikel Google CloudArsitektur transaksional yang sangat konsisten kini lebih banyak digunakan untuk memberikan kelincahan pengembangan yang lebih baik dibandingkan arsitektur non-transaksional yang pada akhirnya konsisten.

Kembali ke diskusi desain database, dapat dikatakan bahwa kedua pendekatan desain (SQL dan NoSQL) diperlukan untuk aplikasi dunia nyata yang kompleks. Pendekatan "pemodelan data" SQL memungkinkan pengembang untuk lebih mudah memenuhi perubahan kebutuhan bisnis, sedangkan pendekatan "pemodelan kueri" NoSQL memungkinkan pengembang yang sama untuk beroperasi pada data dalam jumlah besar dengan latensi rendah dan throughput tinggi. Karena alasan inilah YugaByte DB menyediakan API SQL dan NoSQL dalam inti yang sama, daripada mempromosikan salah satu pendekatannya. Selain itu, dengan menyediakan kompatibilitas dengan bahasa database populer termasuk PostgreSQL dan Cassandra, YugaByte DB memastikan bahwa pengembang tidak perlu mempelajari bahasa lain untuk bekerja dengan mesin database yang terdistribusi dan sangat konsisten.

Pada artikel ini, kita melihat perbedaan dasar desain database antara PostgreSQL, Cassandra, dan MongoDB. Di artikel mendatang, kita akan mendalami konsep desain tingkat lanjut seperti indeks, transaksi, GABUNG, arahan TTL, dan dokumen JSON.

Kami berharap Anda mendapatkan sisa akhir pekan yang menyenangkan dan mengundang Anda ke sana webinar gratis, yang akan berlangsung pada 14 Mei.

Sumber: www.habr.com

Tambah komentar