Основи за дизајн на бази на податоци - Споредување на PostgreSQL, Cassandra и MongoDB

Здраво пријатели. Пред да тргнеме во вториот дел од мајските празници, го споделуваме со вас материјалот што го преведовме во пресрет на лансирањето на нов стрим на курсот „Релациски DBMS“.

Основи за дизајн на бази на податоци - Споредување на PostgreSQL, Cassandra и MongoDB

Програмерите на апликации трошат многу време споредувајќи повеќе оперативни бази на податоци за да ја изберат онаа што најдобро одговара на предвидениот обем на работа. Потребите може да вклучуваат поедноставено моделирање на податоци, трансакциски гаранции, перформанси за читање/запишување, хоризонтално скалирање и толеранција на грешки. Традиционално, изборот започнува со категоријата на базата на податоци, SQL или NoSQL, бидејќи секоја категорија претставува јасен сет на компромиси. Високите перформанси во смисла на ниска латентност и висока пропусност генерално се гледаат како услов што не се разменува и затоа е од суштинско значење за секоја база на податоци за примероци.

Целта на овој напис е да им помогне на развивачите на апликации да го направат вистинскиот избор помеѓу SQL и NoSQL во контекст на моделирање на податоци за апликации. Ќе погледнеме една SQL база на податоци, имено PostgreSQL, и две NoSQL бази на податоци, Cassandra и MongoDB, за да ги покриеме основите на дизајнот на базата на податоци, како што се создавање табели, нивно пополнување, читање податоци од табела и нивно бришење. Во следната статија, сигурно ќе ги разгледаме индексите, трансакциите, JOIN-овите, TTL директивите и дизајнот на базата на податоци базиран на JSON.

Која е разликата помеѓу SQL и NoSQL?

Базите на податоци на SQL ја зголемуваат флексибилноста на апликацијата преку ACID трансакциски гаранции, како и нивната способност да бараат податоци користејќи JOIN на неочекувани начини, покрај постоечките нормализирани модели на релациона база на податоци.

Со оглед на нивната монолитна/еден-јазол архитектура и употребата на модел за репликација на master-slave за вишок, на традиционалните SQL бази на податоци им недостасуваат две важни карактеристики - линеарна приспособливост за пишување (т.е. автоматско партиционирање низ повеќе јазли) и автоматско/нула загуба на податоци. Ова значи дека количината на добиени податоци не може да го надмине максималниот проток на запишување на еден јазол. Дополнително, некои привремени загуби на податоци мора да се земат предвид при толеранцијата на грешки (во архитектурата што нема ништо). Овде треба да имате на ум дека неодамнешните обврски сè уште не се рефлектирани во робната копија. Ажурирањата без прекини, исто така, тешко се постигнуваат во базите на податоци на SQL.

NoSQL базите на податоци обично се дистрибуираат по природа, т.е. во нив податоците се поделени на делови и дистрибуирани низ неколку јазли. Тие бараат денормализација. Ова значи дека внесените податоци исто така мора да се копираат неколку пати за да се одговори на конкретните барања што ги испраќате. Општата цел е да се добијат високи перформанси со намалување на бројот на достапни парчиња за време на читањето. Ова имплицира дека NoSQL бара од вас да ги моделирате вашите барања, додека SQL бара од вас да ги моделирате вашите податоци.

NoSQL се фокусира на постигнување високи перформанси во дистрибуиран кластер и ова е основната причина за многу компромиси во дизајнот на базата на податоци кои вклучуваат загуба на трансакции со ACID, JOIN и конзистентни глобални секундарни индекси.

Постои аргумент дека додека NoSQL базите на податоци обезбедуваат линеарна приспособливост за пишување и висока толеранција на грешки, губењето на трансакциските гаранции ги прави несоодветни за критичните податоци за мисијата.

Следната табела покажува како моделирањето на податоци во NoSQL се разликува од SQL.

Основи за дизајн на бази на податоци - Споредување на PostgreSQL, Cassandra и MongoDB

SQL и NoSQL: Зошто се потребни и двете?

Апликациите од реалниот свет со голем број корисници, како што се Amazon.com, Netflix, Uber и Airbnb, имаат задача да извршуваат сложени, повеќеслојни задачи. На пример, апликација за е-трговија како Amazon.com треба да складира лесни, висококритични податоци како што се кориснички информации, производи, нарачки, фактури, заедно со тешки, помалку чувствителни податоци како што се прегледи на производи, пораки за поддршка, корисничка активност, прегледи и препораки од корисниците. Секако, овие апликации се потпираат на барем една база на податоци SQL заедно со најмалку една база на податоци NoSQL. Во меѓурегионалните и глобалните системи, базата на податоци NoSQL работи како гео-дистрибуирана кеш за податоци складирани во доверлив извор SQL база на податоци што работи во одреден регион.

Како YugaByte DB комбинира SQL и NoSQL?

Изграден на мешан мотор за складирање ориентиран кон дневник, автоматско споделување, разделена дистрибуирана репликација на консензус и ACID дистрибуирани трансакции (инспирирани од Google Spanner), YugaByte DB е првата база на податоци со отворен код во светот која е истовремено компатибилна со NoSQL (Cassandra & Redis ) и SQL (PostgreSQL). Како што е прикажано во табелата подолу, YCQL, YugaByte DB API компатибилен со Cassandra, ги додава концептите на ACID трансакции со еден и повеќекратен клуч и глобални секундарни индекси на NoSQL API, со што ја воведува ерата на трансакциските NoSQL бази на податоци. Дополнително, YCQL, YugaByte DB API компатибилен со PostgreSQL, ги додава концептите за линеарно скалирање на запишување и автоматска толеранција на грешки во SQL API, со што ќе се донесат дистрибуирани SQL бази на податоци во светот. Бидејќи YugaByte DB е трансакциска по природа, NoSQL API сега може да се користи во контекст на критични податоци за мисијата.

Основи за дизајн на бази на податоци - Споредување на PostgreSQL, Cassandra и MongoDB

Како што беше претходно наведено во статијата „Воведување на YSQL: Дистрибуиран SQL API компатибилен со PostgreSQL за YugaByte DB“, изборот помеѓу SQL или NoSQL во YugaByte DB целосно зависи од карактеристиките на основниот обем на работа:

  • Ако вашиот примарен обем на работа се операциите JOIN со повеќе клучеви, тогаш кога избирате YSQL, разберете дека вашите клучеви може да се дистрибуираат низ повеќе јазли, што резултира со поголема латентност и/или помала пропусност од NoSQL.
  • Во спротивно, изберете кое било од двете NoSQL API, имајќи на ум дека ќе добиете подобри перформанси како резултат на прашања сервирани од еден јазол во исто време. YugaByte DB може да служи како единствена оперативна база на податоци за реални, сложени апликации кои треба да управуваат со повеќе оптоварувања истовремено.

Лабораторијата за моделирање податоци во следниот дел се заснова на базите на податоци на YugaByte DB компатибилни со PostgreSQL и Cassandra API, наспроти матичните бази на податоци. Овој пристап ја нагласува леснотијата на интеракција со две различни API (на две различни порти) од истиот кластер на бази на податоци, наспроти користењето на целосно независни кластери од две различни бази на податоци.
Во следните делови, ќе ја разгледаме лабораторијата за моделирање податоци за да ги илустрираме разликите и некои од заедничките карактеристики на опфатените бази на податоци.

Лабораторија за моделирање податоци

Инсталација на база на податоци

Со оглед на акцентот на дизајнот на моделот на податоци (наместо сложените архитектури за распоредување), ќе инсталираме бази на податоци во контејнерите на Docker на локалната машина и потоа ќе комуницираме со нив користејќи ги нивните соодветни школки на командната линија.

PostgreSQL и Cassandra компатибилна со YugaByte DB база на податоци

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

Пристап до командната линија

Ајде да се поврземе со базите на податоци користејќи ја обвивката на командната линија за соодветните API.

PostgreSQL

psql е школка од командната линија за интеракција со PostgreSQL. За полесно користење, YugaByte DB доаѓа со psql директно во папката за ѓубре.

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

Касандра

cqlsh е школка од командната линија за интеракција со Касандра и нејзините компатибилни бази на податоци преку CQL (Cassandra Query Language). За полесно користење, YugaByte DB доаѓа со cqlsh во каталогот bin.
Забележете дека CQL е инспириран од SQL и има слични концепти на табели, редови, колони и индекси. Сепак, како јазик NoSQL, додава одреден сет на ограничувања, од кои повеќето ќе ги опфатиме и во други статии.

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

MongoDB

mongo е школка од командната линија за интеракција со MongoDB. Може да се најде во директориумот за ѓубре на инсталацијата MongoDB.

docker exec -it my-mongo bash 
cd bin
mongo

Направете табела

Сега можеме да комуницираме со базата на податоци за да извршиме различни операции користејќи ја командната линија. Да почнеме со креирање табела која чува информации за песни напишани од различни изведувачи. Овие песни може да бидат дел од албум. Исто така, изборните атрибути за песна се година на издавање, цена, жанр и оцена. Треба да земеме сметка за дополнителни атрибути кои можеби ќе бидат потребни во иднина преку полето „ознаки“. Може да складира полуструктурирани податоци во форма на парови клуч-вредност.

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

Касандра

Креирањето табела во Касандра е многу слично на PostgreSQL. Една од главните разлики е недостатокот на ограничувања за интегритет (на пример, NOT NULL), но ова е одговорност на апликацијата, а не на базата на податоци NoSQL. Примарниот клуч се состои од клуч за партиција (колоната Artist во примерот подолу) и збир на колони за групирање (колоната SongTitle во примерот подолу). Копчето за партиција одредува во која партиција/парче треба да се смести редот, а колоните за групирање покажуваат како податоците треба да се организираат во тековниот фрагмент.

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 организира податоци во бази на податоци (База на податоци) (слично на Keyspace во Касандра), каде што има Колекции (слично на табелите) кои содржат Документи (слично на редовите во табелата). Во MongoDB, во основа нема потреба да се дефинира почетна шема. Тим "користи база на податоци", прикажано подолу, ја инстанцира базата на податоци при првиот повик и го менува контекстот за новосоздадената база на податоци. Дури и збирките не треба да се креираат експлицитно; тие се создаваат автоматски, едноставно кога ќе го додадете првиот документ во нова колекција. Забележете дека MongoDB стандардно ја користи тест базата, така што секоја операција на ниво на колекција без да наведе одредена база на податоци ќе се извршува на неа стандардно.

use myNewDatabase;

Добивање информации за табела
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)

Касандра

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;

Внесување податоци во табела
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}'
);

Касандра

Севкупен израз INSERT во Касандра изгледа многу слично на она во PostgreSQL. Сепак, постои една голема разлика во семантиката. Во Касандра INSERT всушност е операција UPSERT, каде што последните вредности се додаваат на редот ако редот веќе постои.

Внесувањето податоци е слично на PostgreSQL INSERT над

.

MongoDB

Иако MongoDB е NoSQL база на податоци како Касандра, нејзината операција за вметнување нема ништо заедничко со семантичкото однесување на Касандра. Во MongoDB вметнете () нема можности UPSERT, што го прави сличен на PostgreSQL. Додавање стандардни податоци без _idspecified ќе предизвика да се додаде нов документ во колекцијата.

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

Барање за табела

Можеби најзначајната разлика помеѓу SQL и NoSQL во однос на конструкцијата на барањето е јазикот што се користи FROM и WHERE. SQL дозволува по изразување FROM изберете повеќе табели и изразување со WHERE може да биде од секаква сложеност (вклучувајќи операции JOIN помеѓу табелите). Сепак, NoSQL има тенденција да наметне сериозно ограничување FROM, и работи само со една одредена табела, и во WHERE, примарниот клуч мора секогаш да биде наведен. Ова се поврзува со притисокот за изведба на NoSQL за кој зборувавме претходно. Оваа желба води до секое можно намалување на секоја вкрстена табеларна и вкрстена интеракција. Може да внесе големо доцнење во комуникацијата меѓу јазлите кога одговара на барање и затоа најдобро е да се избегнува воопшто. На пример, Касандра бара барањата да бидат ограничени на одредени оператори (само =, IN, <, >, =>, <=) на копчињата за партиција, освен кога се бара секундарен индекс (тука е дозволен само операторот =).

PostgreSQL

Подолу се дадени три примери на прашања кои лесно може да се извршат од базата на податоци SQL.

  • Прикажи ги сите песни од изведувач;
  • Прикажи ги сите песни од изведувачот што одговараат на првиот дел од насловот;
  • Прикажи ги сите песни од изведувач кои имаат одреден збор во насловот и имаат цена помала од 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;

Касандра

Од прашањата PostgreSQL наведени погоре, само првото ќе работи непроменето во Касандра, бидејќи операторот LIKE не може да се примени на колони за групирање како на пр SongTitle. Во овој случај, дозволени се само оператори = и 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

Како што е прикажано во претходните примери, главниот метод за креирање прашања во MongoDB е db.collection.find(). Овој метод експлицитно го содржи името на колекцијата (music во примерот подолу), така што е забрането барање повеќе збирки.

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

Читање на сите редови од табелата

Читањето на сите редови е едноставно посебен случај на шемата за барање што ја разгледавме претходно.

PostgreSQL

SELECT * 
FROM Music;

Касандра

Слично на примерот PostgreSQL погоре.

MongoDB

db.music.find( {} );

Уредување податоци во табела

PostgreSQL

PostgreSQL дава инструкции UPDATE за промена на податоци. Таа нема можности UPSERT, па оваа изјава нема да успее ако редот повеќе не е во базата на податоци.

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

Касандра

Касандра има UPDATE слично на PostgreSQL. UPDATE ја има истата семантика UPSERT, слично INSERT.

Слично на примерот PostgreSQL погоре.

MongoDB
Операција ажурирање () во MongoDB може целосно да ажурира постоечки документ или да ажурира само одредени полиња. Стандардно, ажурира само еден документ со оневозможена семантика UPSERT. Ажурирање на повеќе документи и слично однесување UPSERT може да се примени со поставување дополнителни знаменца за операцијата. На пример, во примерот подолу, жанрот на одреден изведувач се ажурира врз основа на неговата песна.

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

Отстранување податоци од табела

PostgreSQL

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

Касандра

Слично на примерот PostgreSQL погоре.

MongoDB

MongoDB има два типа на операции за бришење документи - DeleteOne() /deleteMany() и отстрани (). И двата типа бришат документи, но враќаат различни резултати.

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

Избришете табела

PostgreSQL

DROP TABLE Music;

Касандра

Слично на примерот PostgreSQL погоре.

MongoDB

db.music.drop();

Заклучок

Дебатата за избор помеѓу SQL и NoSQL беснее повеќе од 10 години. Постојат два главни аспекти на оваа дебата: архитектура на мотори за бази на податоци (монолитна, трансакциска SQL наспроти дистрибуирана, нетрансакциска NoSQL) и пристап на дизајнирање на базата на податоци (моделирање на вашите податоци во SQL наспроти моделирање на вашите барања во NoSQL).

Со дистрибуирана трансакциска база на податоци како YugaByte DB, дебатата за архитектурата на базата на податоци може лесно да се стави крај. Како што обемот на податоци станува поголем од она што може да се запише на еден јазол, станува неопходна целосно дистрибуирана архитектура која поддржува линеарна приспособливост за запишување со автоматско сечење/ребалансирање.

Освен тоа, како што е наведено во еден од написите Google CloudТрансакциските, силно конзистентни архитектури сега се повеќе се користат за да обезбедат подобра развојна агилност од нетрансакциските, евентуално конзистентни архитектури.

Навраќајќи се на дискусијата за дизајн на базата на податоци, фер е да се каже дека и двата пристапи за дизајн (SQL и NoSQL) се неопходни за секоја сложена апликација од реалниот свет. Пристапот за „моделирање на податоци“ на SQL им овозможува на програмерите полесно да ги исполнат променливите деловни барања, додека пристапот на NoSQL „моделирање на податоци“ им овозможува на истите програмери да работат на големи количини на податоци со мала латентност и висока пропусност. Токму поради оваа причина YugaByte DB обезбедува SQL и NoSQL API во заедничко јадро, наместо да промовира еден од пристапите. Дополнително, со обезбедување на компатибилност со популарните јазици на бази на податоци, вклучувајќи ги PostgreSQL и Cassandra, YugaByte DB гарантира дека програмерите не мора да учат друг јазик за да работат со дистрибуиран, високо конзистентен мотор на бази на податоци.

Во оваа статија, разгледавме како основите на дизајнот на базата на податоци се разликуваат помеѓу PostgreSQL, Cassandra и MongoDB. Во идните статии, ќе се нурнеме во напредни концепти за дизајн како што се индекси, трансакции, ПРИКЛУЧУВАЊА, TTL директиви и документи JSON.

Ви посакуваме убав одмор од викендот и ве покануваме бесплатен вебинар, кој ќе се одржи на 14 мај.

Извор: www.habr.com

Додадете коментар