Dasar-Dasar Desain Basis Data - Perbandingan PostgreSQL, Cassandra, dan MongoDB

Halo teman-teman. Sebelum berangkat untuk bagian kedua dari liburan Mei, kami berbagi dengan Anda materi yang kami terjemahkan pada malam peluncuran aliran baru dengan laju "DBMS Relasional" .



Pengembang aplikasi menghabiskan banyak waktu membandingkan banyak database operasi untuk memilih salah satu yang paling sesuai dengan beban kerja yang dituju. Kebutuhan dapat mencakup pemodelan data yang disederhanakan, jaminan transaksional, kinerja baca / tulis, penskalaan horizontal, dan toleransi kesalahan. Secara tradisional, pilihan dimulai dengan kategori basis data, SQL atau NoSQL, karena masing-masing kategori menyediakan serangkaian pertukaran yang jelas. Kinerja tinggi dalam hal latensi rendah dan throughput tinggi biasanya dipandang sebagai persyaratan trade-off, dan oleh karena itu diperlukan untuk setiap basis data dalam sampel.

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 berbicara tentang dasar-dasar desain database, seperti membuat tabel, mengisi mereka, membaca data dari tabel dan menghapusnya. Pada artikel selanjutnya, kita pasti akan melihat indeks, transaksi, GABUNG, arahan TTL, dan desain basis data berbasis JSON.

Apa perbedaan antara SQL dan NoSQL?

Database SQL meningkatkan fleksibilitas aplikasi dengan jaminan transaksional ACID, serta kemampuannya untuk meminta data menggunakan GABUNGAN secara tak terduga di atas model database relasional yang dinormalisasi yang ada.

Mengingat arsitektur monolitik / single-node dan penggunaan model replikasi master-slave untuk redundansi, database SQL tradisional tidak memiliki dua fitur penting - skalabilitas linear catatan (mis., Pemisahan otomatis menjadi beberapa node) dan kehilangan data otomatis / nol. Ini berarti bahwa jumlah data yang diterima tidak dapat melebihi throughput tulis maksimum dari satu node. Selain itu, beberapa kehilangan data sementara harus diperhitungkan selama toleransi kesalahan (dalam arsitektur tanpa berbagi sumber daya). Di sini Anda perlu diingat bahwa komit baru-baru ini belum tercermin dalam salinan budak. Pembaruan tanpa downtime juga sulit dicapai dalam database SQL.

Basis data NoSQL biasanya didistribusikan secara alami, mis. di dalamnya, data dibagi menjadi beberapa bagian dan didistribusikan di beberapa node. Mereka membutuhkan denasionalisasi. Ini berarti bahwa data yang dimasukkan juga harus disalin beberapa kali untuk menanggapi permintaan spesifik yang Anda kirim. Tujuan keseluruhan adalah untuk mendapatkan kinerja tinggi dengan mengurangi jumlah pecahan yang tersedia saat membaca. Ini mengikuti pernyataan bahwa NoSQL mengharuskan Anda untuk memodelkan kueri Anda, sementara SQL mengharuskan Anda untuk memodelkan data Anda.

NoSQL berfokus pada pencapaian kinerja tinggi dalam cluster terdistribusi, dan ini adalah alasan utama untuk banyak trade-off desain database yang meliputi ACID kerugian transaksi, GABUNG, dan indeks sekunder global yang konsisten.

Dipercaya bahwa meskipun database NoSQL memberikan skalabilitas penulisan linier dan toleransi kesalahan yang tinggi, hilangnya jaminan transaksional membuat mereka tidak cocok untuk data penting misi.

Tabel berikut menunjukkan bagaimana pemodelan data dalam NoSQL berbeda dari SQL.



SQL dan NoSQL: Mengapa keduanya dibutuhkan?

Aplikasi dunia nyata dengan sejumlah besar pengguna, seperti Amazon.com, Netflix, Uber, dan Airbnb, melakukan tugas yang kompleks dan beragam. Misalnya, aplikasi e-commerce seperti Amazon.com perlu menyimpan data yang ringan dan sangat kritis, seperti informasi tentang pengguna, produk, pesanan, faktur, bersama dengan data yang berat tetapi kurang sensitif, seperti ulasan produk, pesan dukungan , aktivitas pengguna, ulasan pengguna, dan rekomendasi. Secara alami, aplikasi ini mengandalkan setidaknya satu database SQL bersama dengan setidaknya satu database NoSQL. Dalam sistem antar-regional dan global, basis data NoSQL berfungsi sebagai cache yang didistribusikan secara geografis untuk data yang disimpan dalam sumber tepercaya, basis data SQL, yang bekerja di satu wilayah.

Bagaimana YugaByte DB menggabungkan SQL dan NoSQL?

Dibangun di atas mesin penyimpanan campuran berorientasi log, sharding otomatis, replikasi konsensus terdistribusi sharding, dan transaksi yang didistribusikan ACID (terinspirasi oleh Google Spanner), YugaByte DB adalah database open source pertama di dunia yang secara bersamaan kompatibel dengan NoSQL (Cassandra & Redis) ) dan SQL (PostgreSQL). Seperti yang ditunjukkan pada tabel di bawah ini, YSQL, YugaByte DB API yang kompatibel dengan Cassandra, menambahkan konsep transaksi ACID tunggal dan multi-kunci dan indeks sekunder global ke API NoSQL, sehingga membuka era database NoSQL transaksional. Selain itu, YSQL, yang merupakan YugaByte DB API yang mematuhi PostgreSQL, menambahkan gagasan tentang penskalaan penulisan linier dan toleransi kesalahan otomatis ke SQL API, yang memperkenalkan basis data SQL terdistribusi ke dunia. Karena database DB YugaByte pada dasarnya bersifat transaksional, API NoSQL sekarang dapat digunakan dalam konteks data mission-critical.



Seperti yang dinyatakan sebelumnya dalam artikel โ€œMemperkenalkan YSQL: API SQL Terdistribusi Kompatibel PostgreSQL untuk YugaByte DBโ€ , pilihan antara SQL atau NoSQL di YugaByte DB sepenuhnya bergantung pada karakteristik beban kerja utama:

  • Jika beban kerja utama adalah operasi multi-kunci dengan BERGABUNG, maka ketika memilih YSQL, pahami bahwa kunci Anda dapat didistribusikan di beberapa node, yang akan mengarah ke penundaan yang lebih tinggi dan / atau throughput yang lebih rendah daripada di NoSQL.
  • Jika tidak, pilih salah satu dari kedua API NoSQL, dengan mengingat bahwa Anda akan mendapatkan kinerja yang lebih baik sebagai hasil dari permintaan yang dilayani dari satu simpul pada satu waktu. YugaByte DB dapat berfungsi sebagai basis data operasional tunggal untuk aplikasi yang sangat kompleks di mana Anda perlu mengelola beberapa beban kerja secara bersamaan.

Lab pemodelan data di bagian selanjutnya didasarkan pada database DB YugaByte yang kompatibel dengan PostgreSQL dan Cassandra API, sebagai lawan dari database sumber. Pendekatan ini menekankan kemudahan interaksi dengan dua API yang berbeda (pada dua port yang berbeda) dari kelompok basis data yang sama, yang bertentangan dengan penggunaan kelompok yang sepenuhnya independen dari dua basis data yang berbeda.

Pada bagian berikut, kita akan bertemu dengan lab pemodelan data untuk menggambarkan perbedaan dan beberapa fitur umum dari database yang dimaksud.

Lab Pemodelan Data

Instalasi Database

Mengingat penekanan pada mendesain model data (daripada arsitektur penyebaran yang kompleks), kami akan menginstal basis data dalam wadah Docker di komputer lokal, dan kemudian kami akan berinteraksi dengan mereka menggunakan cangkang baris perintah yang sesuai.

Kompatibel dengan PostgreSQL & Cassandra, Basis data DB YugaByte

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 kita sambungkan 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 langsung di folder bin.

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

Cassandra

cqlsh adalah shell command-line untuk berinteraksi dengan Cassandra dan databasenya yang kompatibel melalui CQL (bahasa permintaan Cassandra). Untuk kemudahan penggunaan, YugaByte DB hadir dengan cqlsh di bin .

Perhatikan bahwa CQL terinspirasi oleh SQL dan memiliki konsep yang mirip dengan tabel, baris, kolom, dan indeks. Namun, sebagai bahasa NoSQL, ia menambahkan serangkaian batasan tertentu, yang sebagian besar akan kami bahas dalam 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 dari instalasi MongoDB.

 docker exec -it my-mongo bash cd bin mongo 

Pembuatan 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 yang ditulis oleh artis yang berbeda. Lagu-lagu ini dapat menjadi bagian dari album. Atribut opsional untuk tahun - lagu rilis, harga, genre, dan peringkat. Kami perlu mempertimbangkan atribut tambahan yang mungkin diperlukan di masa mendatang melalui bidang "tag". Itu dapat menyimpan data semi-terstruktur sebagai pasangan kunci-nilai.

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 utama adalah kurangnya kendala integritas (misalnya, BUKAN NULL), tetapi ini adalah tanggung jawab aplikasi, bukan database NoSQL . Kunci utama terdiri dari kunci bagian (kolom Artis pada contoh di bawah) dan satu set kolom pengelompokan (kolom SongTitle pada contoh di bawah). Kunci partisi menentukan partisi / beling mana untuk menempatkan baris, dan kolom pengelompokan menunjukkan bagaimana data harus diatur di dalam beling 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), di mana ada koleksi (Koleksi) (mirip dengan tabel) yang berisi dokumen (Dokumen) (mirip dengan baris dalam tabel). MongoDB pada dasarnya tidak memerlukan definisi dari skema asli. Perintah "gunakan database" yang ditunjukkan di bawah ini membuat instance dari database pada panggilan pertama dan mengubah konteks untuk database yang baru dibuat. Bahkan koleksi tidak perlu dibuat secara eksplisit, koleksi itu dibuat secara otomatis, hanya ketika Anda menambahkan dokumen pertama ke koleksi baru. Harap dicatat bahwa MongoDB menggunakan database uji secara default, oleh karena itu setiap operasi tingkat pengumpulan tanpa menentukan database tertentu akan dilakukan di dalamnya secara default.

 use myNewDatabase; 

Mengambil informasi 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; 

Posting data ke 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

Secara umum, ekspresi INSERT di Cassandra terlihat sangat mirip dengan yang ada di PostgreSQL. Namun, ada satu perbedaan besar dalam semantik. Dalam Cassandra, INSERT sebenarnya adalah operasi UPSERT mana nilai terakhir ditambahkan ke string jika string sudah ada.
Entri data mirip dengan PostgreSQL INSERT atas

Mongodb

Meskipun MongoDB adalah database NoSQL, seperti Cassandra, operasi penyisipannya tidak ada hubungannya dengan perilaku semantik di Cassandra. Dalam MongoDB, masukkan () tidak memiliki kemampuan UPSERT , yang membuatnya terlihat seperti PostgreSQL. Menambahkan data default tanpa _idspecified akan menambahkan dokumen baru 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 desain kueri adalah penggunaan pernyataan FROM dan WHERE . SQL memungkinkan Anda untuk memilih beberapa tabel setelah FROM , dan WHERE dapat memiliki kompleksitas apa pun (termasuk operasi JOIN antara tabel). Namun, NoSQL cenderung memaksakan pembatasan yang ketat pada FROM , dan bekerja dengan hanya satu tabel yang ditentukan, dan di WHERE , kunci utama harus selalu ditentukan. Ini karena keinginan untuk meningkatkan kinerja NoSQL, yang telah kita bicarakan sebelumnya. Keinginan ini mengarah pada setiap kemungkinan pengurangan interaksi lintas-tabular dan lintas-kunci. Ini dapat menyebabkan keterlambatan besar dalam komunikasi antar-nodal ketika menanggapi permintaan dan, oleh karena itu, sebaiknya dihindari secara prinsip. Sebagai contoh, Cassandra mensyaratkan bahwa permintaan dibatasi untuk operator tertentu (hanya =, IN, <, >, =>, <= diizinkan) pada kunci partisi, kecuali ketika meminta indeks sekunder (hanya = operator yang diizinkan di sini).

PostgreSQL

Tiga contoh pertanyaan yang dapat dengan mudah dieksekusi oleh database SQL akan diberikan di bawah ini.

  • Cetak semua lagu artis;
  • Cetak semua lagu artis yang cocok dengan bagian pertama nama;
  • Daftar semua lagu artis yang memiliki kata tertentu dalam judul 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 di atas, hanya yang pertama yang akan berfungsi di Cassandra tidak berubah, karena pernyataan LIKE tidak dapat diterapkan pada pengelompokan kolom seperti SongTitle . Dalam hal ini, hanya operator = dan IN yang diizinkan.

 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 ditunjukkan dalam contoh sebelumnya, metode utama untuk membuat kueri di MongoDB adalah db.collection.find () . Metode ini secara eksplisit berisi nama koleksi ( music dalam contoh di bawah), sehingga permintaan untuk beberapa koleksi dilarang.

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

Baca semua baris tabel

Membaca semua baris hanyalah kasus khusus dari templat kueri yang telah kita periksa sebelumnya.

PostgreSQL

 SELECT * FROM Music; 


Cassandra

Mirip dengan contoh di PostgreSQL di atas.


Mongodb

 db.music.find( {} ); 

Mengedit data dalam sebuah tabel

PostgreSQL

PostgreSQL menyediakan UPDATE untuk mengubah data. Itu tidak memiliki kemampuan UPSERT , sehingga pelaksanaan instruksi ini akan gagal jika baris tidak lagi ada di database.

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

Cassandra

Cassandra memiliki UPDATE mirip dengan PostgreSQL. UPDATE memiliki semantik UPSERT sama UPSERT INSERT .

Mirip dengan contoh di PostgreSQL di atas.

Mongodb
Operasi pembaruan () di MongoDB dapat sepenuhnya memperbarui dokumen yang ada atau hanya memperbarui bidang tertentu. Secara default, ini memperbarui hanya satu dokumen dengan semantik UPSERT . Memperbarui beberapa dokumen dan perilaku yang mirip dengan UPSERT dapat diterapkan dengan mengatur bendera tambahan untuk operasi. Misalnya, dalam contoh di bawah ini, genre artis tertentu diperbarui oleh 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 di PostgreSQL di atas.

Mongodb

MongoDB memiliki dua jenis operasi untuk menghapus dokumen - deleteOne () / deleteMany () dan hapus () . Kedua jenis menghapus dokumen, tetapi mengembalikan hasil yang berbeda.

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

Hapus tabel

PostgreSQL

 DROP TABLE Music; 

Cassandra

Mirip dengan contoh di PostgreSQL di atas.

Mongodb

 db.music.drop(); 

Kesimpulan

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

Dengan database transaksional terdistribusi seperti YugaByte DB, perdebatan tentang arsitektur database dapat dengan mudah dihilangkan. Ketika volume data menjadi lebih besar dari apa yang dapat ditulis ke satu node, arsitektur terdistribusi penuh yang mendukung skalabilitas linier dari rekaman dengan sharding / rebalancing otomatis menjadi perlu.

Selain dikatakan dalam artikel Google Cloud , arsitektur transaksional, sangat konsisten sekarang lebih banyak digunakan untuk memberikan fleksibilitas pengembangan yang lebih baik daripada arsitektur non-transaksional, akhirnya konsisten.

Kembali ke pembahasan desain database, wajar untuk mengatakan bahwa kedua pendekatan desain (SQL dan NoSQL) diperlukan untuk aplikasi nyata yang kompleks. Pendekatan SQL "pemodelan data" memungkinkan pengembang untuk lebih mudah memenuhi persyaratan bisnis yang berubah, sedangkan pendekatan NoSQL "pemodelan data" memungkinkan pengembang yang sama untuk menangani sejumlah besar data dengan latensi rendah dan throughput tinggi. Untuk alasan inilah YugaByte DB menyediakan SQL dan NoSQL API di kernel yang sama, daripada mempromosikan salah satu pendekatan. Selain itu, dengan memastikan kompatibilitas dengan bahasa database populer, termasuk PostgreSQL dan Cassandra, YugaByte DB memastikan bahwa pengembang tidak harus belajar bahasa lain untuk bekerja dengan mesin database terdistribusi, sangat konsisten.

Pada artikel ini, kami menemukan perbedaan dasar-dasar desain database di PostgreSQL, Cassandra, dan MongoDB. Dalam artikel berikut, kami akan menyelami konsep desain canggih seperti indeks, transaksi, GABUNG, arahan TTL, dan dokumen JSON.

Kami berharap Anda senang tinggal di sini selama akhir pekan dan mengundang Anda ke webinar gratis , yang akan diadakan pada 14 Mei.

Source: https://habr.com/ru/post/id451042/


All Articles