سلام دوستان. قبل از عزیمت به قسمت دوم تعطیلات اردیبهشت، مطالبی را که در انتظار راه اندازی یک جریان جدید با نرخ ترجمه کرده ایم با شما به اشتراک می گذاریم.
توسعه دهندگان برنامه زمان زیادی را صرف مقایسه چندین پایگاه داده عملیاتی می کنند تا پایگاه داده ای را انتخاب کنند که برای حجم کاری مورد نظر آنها بهترین کارایی را دارد. نیازها ممکن است شامل مدلسازی دادههای ساده، تضمینهای تراکنش، عملکرد خواندن/نوشتن، مقیاسبندی افقی و تحمل خطا باشد. به طور سنتی، انتخاب با دسته پایگاه داده، SQL یا NoSQL آغاز می شود، زیرا هر دسته مجموعه ای واضح از مبادلات را ارائه می دهد. عملکرد بالا از نظر تأخیر کم و توان عملیاتی بالا به طور کلی به عنوان یک الزام در نظر گرفته می شود که نمی تواند به خطر بیفتد و بنابراین برای هر پایگاه داده در نمونه ضروری است.
هدف این مقاله کمک به توسعه دهندگان برنامه در انتخاب صحیح بین SQL و NoSQL در زمینه مدل سازی داده های برنامه است. ما به یک پایگاه داده SQL، یعنی PostgreSQL، و دو پایگاه داده NoSQL، Cassandra و MongoDB نگاه می کنیم تا اصول طراحی پایگاه داده را پوشش دهیم، مانند ایجاد جداول، پر کردن آنها، خواندن داده ها از یک جدول و حذف آنها. در مقاله بعدی قطعا به ایندکس ها، تراکنش ها، JOIN ها، دستورالعمل های TTL و طراحی پایگاه داده بر اساس JSON خواهیم پرداخت.
تفاوت بین SQL و NoSQL چیست؟
پایگاههای داده SQL انعطافپذیری برنامهها را از طریق تضمینهای تراکنشهای ACID و همچنین توانایی آنها برای پرسوجو از دادهها با استفاده از JOIN به روشهای غیرمنتظره در بالای مدلهای پایگاهداده رابطهای عادی شده افزایش میدهند.
با توجه به معماری یکپارچه/تک گره آنها و استفاده از یک مدل تکرار master-slave برای افزونگی، پایگاه های داده SQL سنتی فاقد دو ویژگی مهم هستند - مقیاس پذیری نوشتن خطی (یعنی تقسیم خودکار در چندین گره) و از دست دادن خودکار/صفر داده. این بدان معناست که مقدار داده های دریافتی نمی تواند از حداکثر توان نوشتن یک گره تجاوز کند. علاوه بر این، برخی از دست دادن موقت داده ها باید برای تحمل خطا (در یک معماری غیر اشتراکی) در نظر گرفته شود. در اینجا باید به خاطر داشته باشید که commit های اخیر هنوز در نسخه Slave منعکس نشده اند. در پایگاه داده های SQL نیز دستیابی به به روز رسانی خرابی دشوار است.
پایگاههای داده NoSQL معمولاً در طبیعت توزیع میشوند، یعنی. در آنها، داده ها به بخش ها تقسیم می شوند و در چندین گره توزیع می شوند. آنها نیاز به غیرعادی سازی دارند. به این معنی که داده های وارد شده نیز باید چندین بار کپی شوند تا به درخواست های خاصی که ارسال می کنید پاسخ داده شود. هدف کلی دستیابی به عملکرد بالا با کاهش تعداد خرده های موجود در زمان خواندن است. این بدان معناست که NoSQL از شما میخواهد که پرس و جوهای خود را مدل کنید، در حالی که SQL از شما میخواهد دادههای خود را مدل کنید.
NoSQL بر دستیابی به عملکرد بالا در یک خوشه توزیع شده تاکید دارد و این دلیل اصلی بسیاری از مبادلات طراحی پایگاه داده است که شامل از دست دادن تراکنش های ACID، JOIN ها و شاخص های ثانویه جهانی ثابت است.
این عقیده وجود دارد که اگرچه پایگاههای داده NoSQL مقیاسپذیری نوشتن خطی و تحمل خطا بالا را ارائه میکنند، از دست دادن ضمانتهای تراکنش باعث میشود آنها برای دادههای حیاتی نامناسب باشند.
جدول زیر نشان می دهد که چگونه مدل سازی داده ها در NoSQL با SQL متفاوت است.
SQL و NoSQL: چرا هر دو مورد نیاز هستند؟
برنامه های کاربردی واقعی با تعداد زیادی کاربر، مانند Amazon.com، Netflix، Uber و Airbnb، وظیفه انجام وظایف پیچیده از انواع مختلف را بر عهده دارند. به عنوان مثال، یک برنامه تجارت الکترونیک مانند Amazon.com باید داده های سبک وزن و بسیار حساس مانند اطلاعات کاربران، محصولات، سفارشات، فاکتورها، همراه با داده های سنگین اما کمتر حساس مانند بررسی محصول، پیام های پشتیبانی، فعالیت کاربر را ذخیره کند. ، نظرات و توصیه های کاربران. به طور طبیعی، این برنامه ها حداقل به یک پایگاه داده SQL به همراه حداقل یک پایگاه داده NoSQL متکی هستند. در سیستم های بین منطقه ای و جهانی، پایگاه داده NoSQL به عنوان یک حافظه پنهان جغرافیایی توزیع شده برای داده های ذخیره شده در یک منبع قابل اعتماد، پایگاه داده SQL، کار می کند که در هر منطقه ای کار می کند.
YugaByte DB چگونه SQL و NoSQL را ترکیب می کند؟
YugaByte DB که بر روی یک موتور ذخیره سازی ترکیبی لاگ گرا، اشتراک گذاری خودکار، تکثیر توافقی توزیع شده خرد شده و تراکنش های توزیع شده ACID (الهام گرفته از Google Spanner) ساخته شده است، اولین پایگاه داده منبع باز جهان است که به طور همزمان با NoSQL (Cassandra & Redis) سازگار است. ) و SQL (PostgreSQL). همانطور که در جدول زیر نشان داده شده است، YCQL، یک API YugaByte DB سازگار با Cassandra، مفاهیم تراکنشهای ACID تک کلیدی و چند کلیدی و شاخصهای ثانویه جهانی را به NoSQL API اضافه میکند، بنابراین عصر پایگاههای داده NoSQL تراکنشی را آغاز میکند. علاوه بر این، YCQL، یک YugaByte DB API سازگار با PostgreSQL، مفاهیم مقیاس نوشتن خطی و خطای خودکار را به API SQL اضافه میکند و پایگاههای داده SQL توزیع شده را به دنیا میآورد. از آنجایی که پایگاه داده YugaByte DB ذاتا تراکنشی است، NoSQL API اکنون می تواند در زمینه داده های حیاتی استفاده شود.
همانطور که قبلا در مقاله گفته شد
- اگر حجم کار اصلی شما عملیات JOIN چند کلیدی است، پس هنگام انتخاب YSQL، توجه داشته باشید که کلیدهای شما ممکن است در چندین گره پخش شوند که منجر به تاخیر بیشتر و/یا توان عملیاتی کمتر از NoSQL می شود.
- در غیر این صورت، یکی از دو API NoSQL را انتخاب کنید، در نظر داشته باشید که در نتیجه پرس و جوهای ارائه شده از یک گره در یک زمان، عملکرد بهتری خواهید داشت. YugaByte DB می تواند به عنوان یک پایگاه داده عملیاتی واحد برای برنامه های کاربردی پیچیده واقعی که نیاز به مدیریت بارهای کاری متعدد به طور همزمان دارند، خدمت کند.
آزمایشگاه مدلسازی داده در بخش بعدی بر خلاف پایگاههای داده اصلی، مبتنی بر APIهای پایگاه داده YugaByte DB سازگار PostgreSQL و Cassandra است. این رویکرد بر سهولت تعامل با دو 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 و
docker exec -it yb-postgres-n1 /home/yugabyte/postgres/bin/psql -p 5433 -U postgres
کاساندرا
cqlsh
در کاتالوگ bin
.
توجه داشته باشید که CQL از SQL الهام گرفته شده است و مفاهیم مشابهی از جداول، ردیف ها، ستون ها و شاخص ها دارد. با این حال، به عنوان یک زبان NoSQL، مجموعه ای از محدودیت ها را اضافه می کند که بیشتر آنها را در مقالات دیگر نیز پوشش خواهیم داد.
docker exec -it yb-tserver-n1 /home/yugabyte/bin/cqlsh
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)
);
کاساندرا
ایجاد جدول در Cassandra بسیار شبیه PostgreSQL است. یکی از تفاوتهای اصلی عدم وجود محدودیتهای یکپارچگی (مانند NOT NULL) است، اما این مسئولیت بر عهده برنامه است، نه پایگاه داده NoSQL.. کلید اصلی از یک کلید پارتیشن (ستون هنرمند در مثال زیر) و مجموعه ای از ستون های خوشه بندی (ستون 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 در Cassandra)، جایی که مجموعه هایی (مجموعه ها) (مشابه جداول) که حاوی اسناد (اسناد) هستند (مشابه ردیف های یک جدول) وجود دارد. در 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
در Cassandra بسیار شبیه به مورد در PostgreSQL است. با این حال، یک تفاوت بزرگ در معناشناسی وجود دارد. در کاساندرا INSERT
در واقع یک عملیات است UPSERT
، جایی که آخرین مقادیر به رشته اضافه می شود، در صورتی که رشته از قبل وجود داشته باشد.
ورود داده ها مشابه PostgreSQL است
INSERT
بالاتر
.
MongoDB
اگرچه MongoDB یک پایگاه داده NoSQL مانند Cassandra است، عملیات ورود داده آن هیچ ارتباطی با رفتار معنایی کاساندرا ندارد. در 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 ذکر شده در بالا، فقط اولین مورد بدون تغییر در Cassandra کار می کند، زیرا عبارت 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 است 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
عمل 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 دو نوع عملیات برای حذف اسناد دارد -
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، بحث معماری پایگاه داده را می توان به راحتی از بین برد. با بزرگتر شدن حجم داده ها از آنچه می توان در یک گره نوشت، یک معماری کاملاً توزیع شده که از مقیاس پذیری نوشتن خطی با تقسیم خودکار/تعادل مجدد خودکار پشتیبانی می کند، ضروری می شود.
علاوه بر آنچه در یکی از مقالات گفته شد
در بازگشت به بحث طراحی پایگاه داده، منصفانه است که بگوییم هر دو رویکرد طراحی (SQL و NoSQL) برای هر برنامه پیچیده دنیای واقعی ضروری هستند. رویکرد "مدل سازی داده" SQL به توسعه دهندگان این امکان را می دهد تا به راحتی نیازهای در حال تغییر کسب و کار را برآورده کنند، در حالی که رویکرد "مدل سازی پرس و جو" NoSQL به همان توسعه دهندگان اجازه می دهد تا حجم زیادی از داده ها را با تاخیر کم و توان عملیاتی بالا مدیریت کنند. به همین دلیل است که YugaByte DB APIهای SQL و NoSQL را در یک هسته مشترک ارائه می دهد و از هیچ یک از رویکردها حمایت نمی کند. علاوه بر این، با ارائه سازگاری با زبان های پایگاه داده محبوب از جمله PostgreSQL و Cassandra، YugaByte DB تضمین می کند که توسعه دهندگان برای کار با یک موتور پایگاه داده کاملاً سازگار توزیع شده نیازی به یادگیری زبان دیگری ندارند.
در این مقاله، به چگونگی تفاوت اصول طراحی پایگاه داده بین PostgreSQL، Cassandra و MongoDB پرداختیم. در مقالات بعدی، به مفاهیم طراحی پیشرفته مانند شاخص ها، تراکنش ها، JOIN ها، دستورالعمل های TTL و اسناد JSON خواهیم پرداخت.
آخر هفته خوبی را برای شما آرزو می کنیم و شما را دعوت می کنیم
منبع: www.habr.com