RE:NODE

ბაზები14 წუთის საკითხავი

PostgreSQL თუ MongoDB: არჩევანი მონაცემების ფორმის მიხედვით

როგორ აირჩიო მონაცემების ფორმით და არა მოდით: მონაცემთა მოდელი, ტრანზაქციები, ინდექსები, JSONB, აგრეგაცია და რა ღირს თითოეული პატარა სერვერზე.

განახლებულია

0 მკითხველი

ორივე შესანიშნავია, ორივე მომწიფებულია და ორივე გაუძლებს ყველაფერს, რასაც აშენებ. ვინც ამბობს, რომ ერთ-ერთი უბრალოდ უკეთესია, მას გაგრძელების კითხვა არ დაუსვამთ. არჩევანს მნიშვნელობა კიდეებზე აქვს, კიდეები კი მოლოდინზე გვიან მოდის - ჩვეულებრივ, პირველად, როცა კითხვის დასმა გჭირდება, რომლისთვისაც სქემა არ შეიქმნა, ან პირველად, როცა ნახევრად ჩაწერილი ჩანაწერი ფული გიჯდება.

მოკლე ვერსია: თუ შენი მონაცემები ერთმანეთზე მითითებული ერთეულებია და გაუთვალისწინებელ კითხვებს დასვამ, გამოიყენე PostgreSQL. თუ შენი მონაცემები დამოუკიდებელი დოკუმენტებია, რომლებიც ფორმით განსხვავდება, მთლიანად იკითხება და მთლიანად იწერება, MongoDB სასიამოვნო იქნება. თუ ნამდვილად ვერ გადაწყვეტ, გამოიყენე PostgreSQL, რადგან ის დოკუმენტების შენახვასაც შეძლებს, ხოლო პირიქით ბევრად ნაკლებად მართალია. პოსტის დანარჩენი ნაწილი მსჯელობაა იმ დეტალებით, რომლებიც საშუალებას გაძლევს შენს აპლიკაციასთან შეამოწმო.

ერთი განსხვავება, საიდანაც ყველაფერი გამომდინარეობს#

PostgreSQL ინახავს სტრიქონებს ცხრილებში ტიპიზებული სვეტების ფიქსირებული ნაკრებით, ხოლო ცხრილებს შორის ურთიერთობები გასაღებებით გამოიხატება და მოთხოვნის დროს join-ებით წყდება. MongoDB ინახავს BSON დოკუმენტებს კოლექციებში, თითოეული დოკუმენტი დამოუკიდებელია, მის შიგნით ჩადგმული ობიექტებითა და მასივებით, ხოლო ურთიერთობები ან ჩაშენებულია, ან მეორე მოთხოვნით წყდება.

ყველაფერი დანარჩენი - ტრანზაქციები, სქემა, ინდექსირება, რამდენ მეხსიერებას მოითხოვს თითოეული, როგორ განაახლებ - აქედან გამოდის. კონკრეტული მაგალითი ამას თვალსაჩინოს ხდის. შეკვეთა სამი პოზიციით და მომხმარებლით:

sql
-- PostgreSQL: three tables, one querySELECT o.id, o.placed_at, u.email,       i.sku, i.quantity, i.price_centsFROM orders oJOIN users u ON u.id = o.user_idJOIN order_items i ON i.order_id = o.idWHERE o.id = 4821;
javascript
// MongoDB: one document, one readdb.orders.findOne({ _id: 4821 })// {//   _id: 4821, placedAt: ISODate("2026-04-02T10:11:00Z"),//   user: { id: 77, email: "a@example.com" },//   items: [//     { sku: "AB-1", quantity: 2, priceCents: 1200 },//     { sku: "CD-9", quantity: 1, priceCents: 4500 }//   ]// }

დოკუმენტის ვერსია ერთი დისკური წაკითხვაა და ისეთი ფორმით მოდის, რომელსაც შენი კოდი უკვე იყენებს. რელაციური ვერსია join-ს ჯდება, მაგრამ მომხმარებლის ელფოსტას ერთხელ ინახავს, ამიტომ მისი შეცვლა ყველგან ცვლის. ეს მთელი გარიგებაა ერთ ეკრანზე: დოკუმენტები ოპტიმიზებულია რაღაცის წასაკითხად, ცხრილები კი იმისთვის, რომ ფაქტი ერთხელ იცოდე.

SQL join-ებითfindOne by _idაპლიკაციაერთი შეკვეთაPostgreSQLorders, items, usersMongoDBorders collectionწაკითხვისას joinთითო სტრიქონიჩაშენებულიერთი დოკუმენტი
ერთი და იგივე შეკვეთა, ორჯერ მოდელირებული

სქემა: აღსრულებს ბაზა ან აღასრულებ შენ#

PostgreSQL არ გაძლევს სტრიქონის ჩასმის საშუალებას, რომელიც ცხრილს არ ემთხვევა. სვეტებს ტიპები აქვს, NOT NULL ნიშნავს, რომ null არ შეიძლება, foreign key უარს ამბობს არარსებულ სტრიქონზე მითითებაზე, CHECK შეზღუდვა კი უაზრობას უარყოფს. ფასი ისაა, რომ ფორმის შეცვლა ოპერაციაა, რომელიც უნდა დაგეგმო - იხილე სქემის მიგრაციები გამორთვის გარეშე, როგორ მიდის ეს.

MongoDB შეინახავს ყველაფერს, რასაც გაუგზავნი. ეს ნამდვილად სასარგებლოა, როცა ფორმა კვირაში ერთხელ იცვლება, და ნელი გაჟონვაა, როცა აღარ იცვლება: ორი წლის შემდეგ ერთ კოლექციაში დოკუმენტის ოთხი თაობა გაქვს და წაკითხვის ყოველ გზას ოთხივეს გატანა უწევს. წამალი სქემის ვალიდაციაა, რომელიც MongoDB-ს 3.6-დან აქვს და რომელსაც თითქმის არავინ რთავს:

javascript
db.createCollection("orders", {  validator: { $jsonSchema: {    bsonType: "object",    required: ["userId", "placedAt", "items"],    properties: {      userId:   { bsonType: "int" },      placedAt: { bsonType: "date" },      items:    { bsonType: "array", minItems: 1 }    }  }},  validationLevel: "moderate",   // only documents you update must pass  validationAction: "error"      // reject rather than warn})

validationLevel: "moderate" წესს ავრცელებს ჩასმებსა და იმ დოკუმენტების განახლებებზე, რომლებიც უკვე აკმაყოფილებენ მას, და სწორედ ეს გინდა, როცა ცოცხალ კოლექციაზე წესებს ამკაცრებ. ვალიდაცია ჩართე პროექტის დასაწყისში და არა არეულობის შემდეგ.

გულწრფელი შეჯამება ისაა, რომ ორივე ბაზას სქემა აქვს. ერთში ის ბაზაში წერია და ყოველ ჩაწერაზე მოწმდება. მეორეში ის შენი აპლიკაციის კოდში წერია, გაშლილია ყველა ფუნქციაში, რომელიც კოლექციას კითხულობს, და მოწმდება იმედით.

მოთხოვნები: SQL, join-ები და აგრეგაციის pipeline#

SQL-ის ძალა არ არის ის, რომ წერა სასიამოვნოა. ის დეკლარაციულია და ძველი, რაც ნიშნავს, რომ planner-ს შეუძლია შენი მოთხოვნა გადაწეროს, და ორმოცი წლის განმავლობაში უხერხული კითხვების დამსმელი ადამიანების შედეგები ენაშია შეთვისებული. ფანჯრის ფუნქციები, common table expression-ები, GROUP BY ROLLUP, lateral join-ები, რეკურსიული მოთხოვნები ხისთვის - ყველაფერი სტანდარტულია, ყველაფერი ხელმისაწვდომია და არცერთზე არ გჭირდება ფიქრი იმ დღემდე, როცა დაგჭირდება.

MongoDB-ის ეკვივალენტია აგრეგაციის pipeline: სტადიების მასივი, რომელთაგან თითოეული დოკუმენტების ნაკადს გარდაქმნის.

javascript
db.orders.aggregate([  { $match: { placedAt: { $gte: ISODate("2026-04-01") } } },  { $unwind: "$items" },  { $group: { _id: "$items.sku",              units: { $sum: "$items.quantity" },              revenue: { $sum: { $multiply: ["$items.quantity", "$items.priceCents"] } } } },  { $sort: { revenue: -1 } },  { $limit: 20 }])

ეს სრულიად კარგი მოთხოვნაა და წასაკითხად რთული არ არის. მასშტაბზე ორი პრაქტიკული განსხვავება ჩნდება. პირველი, $match სტადია პირველი უნდა იყოს, თუ გინდა, რომ ინდექსი გამოიყენოს, ხოლო აპლიკაციის კოდით აწყობილ pipeline-ებს ჩვევა აქვთ, ის სადმე სხვაგან ჩააყენონ. მეორე, join-ები არსებობს - $lookup left outer join-ს ასრულებს და შეუძლია დაკავშირებულ ველზე ინდექსი გამოიყენოს - მაგრამ არ არსებობს planner, რომელიც სტატისტიკის მიხედვით hash join-სა და merge join-ს შორის ირჩევს. დიდ კოლექციებზე სამმხრივი join სწორედ ის ადგილია, სადაც დოკუმენტური ბაზები სახალისო აღარ არის.

მონათესავე წერტილი, რომელიც ხალხს იჭერს: MongoDB-ში countDocuments() ნამდვილად ითვლის და დიდ კოლექციაზე ნელია. estimatedDocumentCount() მყისიერია, მაგრამ კოლექციის მეტამონაცემებს კითხულობს, ამიტომ შენს ფილტრს უგულებელყოფს. PostgreSQL-ს იგივე პრობლემა მეორე მხრიდან აქვს - COUNT(*) WHERE-ით სკანია, თუ ინდექსი მას არ ფარავს. არცერთ ბაზას უფასო count არ აქვს, და ნებისმიერი გვერდი, რომელიც სტრიქონების საერთო რაოდენობას აჩვენებს, საბოლოოდ შენი ყველაზე ნელი გვერდი იქნება. EXPLAIN ANALYZE-ის კითხვა გვიჩვენებს, რომელი მოთხოვნაა ეს.

ტრანზაქციები და რა ღირს ნახევრად დასრულებული ჩაწერა#

PostgreSQL-ს სამუდამოდ აქვს სრულფასოვანი მრავალ-ინსტრუქციიანი, მრავალცხრილიანი ACID ტრანზაქციები. BEGIN, გააკეთე ხუთი რამ, COMMIT, და ან ხუთივე მოხდა, ან არცერთი. ნაგულისხმევი იზოლაციის დონე read committed-ია; REPEATABLE READ და SERIALIZABLE ხელმისაწვდომია, როცა გჭირდება.

MongoDB გარანტიას იძლევა, რომ ერთი დოკუმენტის განახლება ატომურია, ჩადგმული ველებისა და მასივების ცვლილებების ჩათვლით. კარგად ჩაშენებული დოკუმენტისთვის ეს უფრო მეტ შემთხვევას ფარავს, ვიდრე ხალხი ელოდება: შეკვეთაში პოზიციის დამატება და შეკვეთის ჯამის განახლება ერთი დოკუმენტის ერთი განახლებაა და ან ხდება, ან არა.

მრავალ-დოკუმენტიანი ტრანზაქციებიც არსებობს, 4.0-დან, ერთი პირობით, რომელიც პატარა სერვერზე უზარმაზარ მნიშვნელობას იძენს: მათ replica set სჭირდება. ცალკე მდგომ mongod-ს მათი გაშვება არ შეუძლია. თუ ერთ ეგზემპლარს უშვებ და ტრანზაქციები გინდა, ამ ერთ ეგზემპლარს უშვებ როგორც ერთკვანძიან replica set-ს:

mongod.conf
replication:  replSetName: rs0
javascript
// then, once, from mongoshrs.initiate()

ეს გაძლევს oplog-ს, ტრანზაქციებსა და change stream-ებს ერთ მანქანაზე. ასევე ნიშნავს, რომ connection string-ს ?replicaSet=rs0 სჭირდება, ხოლო replica set-ის კონფიგურაციაში მითითებული hostname ისეთი უნდა იყოს, რომელსაც შენი აპლიკაცია მართლა გადაწყვეტს - ჩვეულებრივი პირველი ჩავარდნა. MongoDB connection string-ები URI-ს დეტალურად განიხილავს.

დაუსვი საკუთარ თავს ერთი კითხვა: თუ პროცესი ორ ჩაწერას შორის მოკვდებოდა, დაკარგავდა ვინმე ფულს ან ნდობას? გადახდები, კრედიტები, მარაგის დონეები, ყველაფერი, რაშიც ორი ჩანაწერი უნდა თანხმდებოდეს - ეს ტრანზაქციული შემთხვევაა და PostgreSQL მას ყოველგვარი კონფიგურაციის გარეშე გაძლევს.

ინდექსები და მოთხოვნები, რომლებიც მათ გარეშე ფუჭდება#

ორივე ბაზა სწრაფია ინდექსით და შესარცხვენი მის გარეშე, და ჩავარდნა ერთნაირად გამოიყურება: მოთხოვნა, რომელიც ათი ათასი სტრიქონით მყისიერი იყო, ორი მილიონით ცხრა წამს გრძელდება.

საჭიროებაPostgreSQLMongoDB
ნაგულისხმევი ინდექსის ტიპიB-treeB-tree
მრავალსვეტიანიComposite ინდექსი, ყველაზე მარცხენა პრეფიქსის წესიCompound ინდექსი, იგივე პრეფიქსის წესი
ცხრილის მხოლოდ ნაწილიPartial ინდექსი WHERE-ითPartial ინდექსი partialFilterExpression-ით
გამოთვლილი მნიშვნელობაExpression ინდექსი ან generated columnინდექსი ველზე, რომელსაც თავად ინახავ
JSON დოკუმენტის შიგნითGIN ინდექსი jsonb-ზეინდექსი წერტილებიან გზაზე
სრული ტექსტიtsvector plus GINText ინდექსი, ერთი კოლექციაზე
უნიკალურობაUNIQUE შეზღუდვაUnique ინდექსი
გეგმის კითხვაEXPLAIN (ANALYZE, BUFFERS).explain("executionStats")

ორი წესი დატვირთვის უმეტეს ნაწილს ატარებს. ყველაზე მარცხენა პრეფიქსის წესი ორივეზე მოქმედებს: ინდექსი (status, created_at)-ზე ეხმარება მოთხოვნას, რომელიც status-ით ფილტრავს, ან ორივეთი, მაგრამ არა მას, რომელიც მხოლოდ created_at-ით ფილტრავს. და MongoDB-ის ESR წესი - ჯერ თანასწორობის ველები, შემდეგ დალაგების ველები, შემდეგ დიაპაზონის ველები - ამ ეკოსისტემის ინდექსის ყველაზე სასარგებლო რჩევაა, სათანადოდ განხილული MongoDB ინდექსები და სქემის დიზაინში.

სადაც ისინი ნამდვილად განსხვავდებიან: PostgreSQL სიამოვნებით ატარებს ათეულ ინდექსის ტიპს და ერთი მოთხოვნისთვის რამდენიმე ინდექსს ერთმანეთს bitmap scan-ით უერთებს, ამის საფასურს კი ჩაწერის სიჩქარითა და VACUUM-ის მუშაობით იხდი - იხილე Postgres vacuum და bloat. MongoDB გზღუდავს 64 ინდექსით კოლექციაზე და ერთ text ინდექსს, და ყოველი ინდექსი მეხსიერებაში უნდა ეტეოდეს სამუშაო ნაკრებთან ერთად, თორემ წაკითხვის სიჩქარე უფსკრულში ვარდება. 1 GB ეგზემპლარზე ყურადსაღები რიცხვი ინდექსის ზომაა და არა დოკუმენტების რაოდენობა. Postgres ინდექსები ახსნილი იგივე საქმეს რელაციურ მხარეზე აკეთებს.

დოკუმენტები Postgres-ში: JSON, JSONB და როდის ჯობს#

ეს ის ფაქტია, რომელიც უმეტეს კამათს წყვეტს. PostgreSQL-ს აქვს jsonb ტიპი: ბინარული დოკუმენტი, ინდექსირებადი, მოთხოვნადი, containment ოპერატორებითა და path გამოსახულებებით. დოკუმენტურ მოდელს რელაციურის შიგნით ააგებ.

sql
CREATE TABLE events (  id          bigserial PRIMARY KEY,  received_at timestamptz NOT NULL DEFAULT now(),  kind        text NOT NULL,  payload     jsonb NOT NULL);-- index the whole document for containment queriesCREATE INDEX events_payload_gin ON events USING gin (payload jsonb_path_ops);-- "every event whose payload mentions this account"SELECT id, received_at FROM eventsWHERE payload @> '{"account": {"id": 77}}';-- pull one field out as textSELECT payload ->> 'source' AS source FROM events WHERE kind = 'webhook';

-> აბრუნებს JSON-ს, ->> აბრუნებს ტექსტს; ამის აღრევა დაბნეული WHERE პირობების კარგ წილს ხსნის. jsonb_path_ops უფრო პატარა და სწრაფ GIN ინდექსს ქმნის, რომელიც მხოლოდ containment-ს უჭერს მხარს, რაც ჩვეულებრივ ერთადერთია, რასაც კითხულობ. და როცა დოკუმენტის შიგნით ერთი ველი მნიშვნელოვანი გახდება, generated column მას ნამდვილ, ტიპიზებულ, ინდექსირებად სვეტად წარმოაჩენს ისე, რომ JSON-ის მკითხველ არაფერს გადაწერ.

საპირისპირო სვლა ბევრად უარესია. დოკუმენტური საცავი, რომელსაც რელაციურად მოქცევა სთხოვეს, ხელით დაწერილი join-ები ხდება აპლიკაციის კოდში: აიღე შეკვეთები, შეაგროვე მომხმარებლის ID-ები, აიღე მომხმარებლები, ციკლში ერთმანეთს მიაკერე. მუშაობს, უფრო ნელია, და ყოველი ასეთი ნაკერი ადგილია, სადაც მონაცემები საკუთარ თავს შეიძლება დაუპირისპირდეს.

ასე რომ: jsonb გამოიყენე იმ ნაწილებისთვის, რომლებიც ნამდვილად ცვალებადია - webhook payload-ები, event-ების სხეულები, თითო tenant-ის საკუთარი ველები, API პასუხები, რომლებსაც აქეშებ - სვეტები კი იმისთვის, რაც არ არის. ცხრილი, რომელიც ერთი id სვეტი და ერთი jsonb ბლობია, ნიშანია, რომ დოკუმენტური ბაზა უნდა გეხმარა. დოკუმენტური ბაზა, რომელსაც სამ კოლექციაზე ანგარიშს სთხოვენ, საპირისპირო ნიშანია.

რა ღირს თითოეული პატარა სერვერზე#

ორივე კომფორტულია მოკრძალებულ აპარატურაზე, თუ მას მოარგებ. ორივე საშინელია მოკრძალებულ აპარატურაზე ნაგულისხმევებზე.

PostgreSQLMongoDB
ნაგულისხმევი პორტი543227017
კავშირის მოდელიერთი OS პროცესი კავშირზეერთი thread კავშირზე
მთავარი მეხსიერების პარამეტრიshared_buffers, ნაგულისხმევი 128 MBWiredTiger cache, ნაგულისხმევი RAM-ის 50% მინუს 1 GB, ქვედა ზღვარი 256 MB
მეხსიერება მოთხოვნაზეwork_mem, ნაგულისხმევი 4 MB, თითო sort ან hash კვანძზეSort სტადია შეზღუდულია, დისკზე გადადის
დისკზე შეკუმშვაTOAST დიდი მნიშვნელობებისთვისნაგულისხმევად Snappy, კოლექციაზე
კავშირების ზღვარიmax_connections, ნაგულისხმევი 100Driver-ის pool, ნაგულისხმევი 100 pool-ზე

Postgres-ის რიცხვი, რომელიც პირველად უნდა შეცვალო, shared_buffers-ია - სერვერისთვის ხელმისაწვდომი მეხსიერების დაახლოებით მეოთხედი ჩვეულებრივი საწყისი წერტილია - ხოლო რიცხვი, რომელთან სიფრთხილეა საჭირო, work_mem-ია, რადგან ის თითო sort ან hash კვანძზე თითო მოთხოვნაში გამოიყოფა და არა ერთხელ. ორმოცდაათი კავშირი, რომელიც მოთხოვნას სამი sort-ით 64 MB-ზე უშვებს, 64 MB არ არის. Postgres-ის მორგება პატარა სერვერებისთვის სრულ ნაკრებს შეიცავს.

MongoDB-ის რიცხვი cache-ია, და გასაშუქებელი ისაა, რომ მან container-ის ლიმიტი დაინახა და არა host-ის მეხსიერება. პირდაპირ ჰკითხე:

javascript
db.serverStatus().wiredTiger.cache["maximum bytes configured"]

1 GB ეგზემპლარზე ეს უნდა იყოს 256 MB ქვედა ზღვარი და არა რამდენიმე გიგაბაიტი. თუ შეუძლებელ რიცხვს აბრუნებს, პირდაპირ დააყენე storage.wiredTiger.engineConfig.cacheSizeGB და გადატვირთე.

კავშირები მეორე გაზიარებული ხარჯია და მიზეზი თითოეულში განსხვავებულია. PostgreSQL-ის კავშირი პროცესია საკუთარი მეხსიერებით, ამიტომ ას უქმ კავშირზე ნამდვილი მეხსიერება იკარგება; MongoDB-ისა thread-ებია და უფრო იაფი, მაგრამ 100-იანი pool აპლიკაციის თითო პროცესზე მაინც გროვდება. ორივეგან გამოსავალი ერთია და უფრო დიდი გეგმა არ არის - იხილე connection pool-ები და შეცდომა, რომელიც ყველაზე უარეს დროს მოდის.

RE:NODE-ზე ორივე იყიდება როგორც შენი საკუთარი სერვერი და არა გაზიარებული კლასტერი: PostgreSQL თვეში $6-დან და MongoDB $7-დან, გეგმებით 1 GB მეხსიერებისა და 20 GB NVMe-დან 14 GB-სა და 100 GB-მდე, superuser პაროლით, რომელიც თითო სერვერზე გენერირდება იმ გამოქვეყნებული ნაგულისხმევის ნაცვლად, რომელსაც მზა image-ები ატარებს. გაქვს ფაილები და კონსოლი, ამიტომ postgresql.conf და mongod.conf შენი სარედაქტოა, რაც ზემოთ მოცემული ცხრილის მთელი აზრია.

გადაწყვეტილების ცხრილი და პატიოსანი ნაგულისხმევი#

თუ ეს შენს პროექტზე მართალიაგადაიხარე
ფული, მარაგი, კრედიტები, ყველაფერი, რაზეც ორი ჩანაწერი უნდა თანხმდებოდესPostgreSQL
ანგარიშგება, აგრეგაცია და join-ები რამდენიმე ერთეულზეPostgreSQL
კითხვები, რომლებზეც ჯერ არ გიფიქრიაPostgreSQL
გუნდში SQL-ის ძლიერი გამოცდილებაPostgreSQL
ჩანაწერები, რომლებიც ერთმანეთისგან ფორმით ნამდვილად განსხვავდებაMongoDB
მთლიანად იკითხება და მთლიანად იწერება, აპლიკაციის საკუთარი ფორმითMongoDB
სქემა კვირაში ერთხელ იცვლება, პროდუქტი დამკვიდრებული არ არისMongoDB
დიდი მოცულობის event ან ლოგ მონაცემები, სადაც join-ები არარელევანტურიაMongoDB
ჰორიზონტალური sharding უახლოესი მოთხოვნააMongoDB
ერთი პატარა სერვერი, ერთი აპლიკაცია, ops გუნდის გარეშეPostgreSQL

თუ ვერ წყვეტ, გამოიყენე PostgreSQL. ის დოკუმენტებს jsonb-ით საკმაოდ კარგად უმკლავდება, როცა გჭირდება, და არაფერი დაგიჯდება იმ დღეს, როცა join, ტრანზაქცია ან ანგარიში დაგჭირდება. PostgreSQL-ის არჩევის და მისი სიმკაცრის არასოდეს საჭიროების ფასი რამდენიმე დამატებითი CREATE TABLE-ია. მეორე შეცდომის ფასი გადაწერაა.

ორი რამ, რაც გადაწყვეტილების ნაწილი არ უნდა იყოს. სიჩქარე: ერთი პატარა სერვერის მასშტაბზე ორივეს ზღვარი შენი ინდექსები და მოთხოვნებია და არა ძრავა, და გამოტოვებული ინდექსი ნებისმიერ ძრავის არჩევანზე მეტს ღირს. და "რომელი მასშტაბირდება": MongoDB-ის sharding ნამდვილად ჩაშენებულია, მაგრამ shard-ირებული კლასტერი config სერვერებია, პლუს router-ები, პლუს replica set-ები, რაც ჰობი პროექტის გვერდით გასაშვები რამ არ არის. Read replica-ები და უფრო დიდი მანქანა თითქმის ყველას უფრო შორს წაიყვანს, ვიდრე რომელიმე მათგანი.

რომელსაც არ უნდა აირჩიო, ოპერაციული სამუშაო ერთი ფორმისაა: ნამდვილი backup გამოცდილი აღდგენით (მონაცემთა ბაზის backup-ები და აღდგენა), დაკეტილი ქსელური პოზიცია (მონაცემთა ბაზის უსაფრთხოების ჩამონათვალი) და dump, რომლის ხელით გაკეთებაც იცი, pg_dump და pg_restore-ით ან mongodump და mongorestore-ით.

FAQ#

MongoDB უფრო სწრაფია, ვიდრე PostgreSQL?

ერთი დამოუკიდებელი დოკუმენტის მისი გასაღებით წასაკითხად, ჩვეულებრივ, დიახ, რადგან ეს ერთი წაკითხვაა join-ის ნაცვლად. თითქმის ყველაფერზე დანარჩენზე განსხვავებას განსაზღვრავს, გაქვს თუ არა სწორი ინდექსი. Benchmark-ები, რომლებიც დიდ სხვაობას აჩვენებს, ჩვეულებრივ ერთის მორგებულ ეგზემპლარს მეორის ნაგულისხმევ ინსტალაციას ადარებს.

შეუძლია PostgreSQL-ს MongoDB-ის ჩანაცვლება JSONB-ით?

უმეტესი პატარა და საშუალო აპლიკაციისთვის, დიახ. jsonb GIN ინდექსით გაძლევს უსქემო შენახვას, containment მოთხოვნებსა და path გამოსახულებებს ისეთ ბაზაში, რომელსაც ტრანზაქციებისა და join-ების გაკეთებაც შეუძლია. რასაც არ გაძლევს, MongoDB-ის ჩაშენებული sharding-ი და მისი აგრეგაციის pipeline სინტაქსია.

მჭირდება replica set MongoDB-ის გამოსაყენებლად?

მონაცემების შესანახად არა, მაგრამ მრავალ-დოკუმენტიანი ტრანზაქციებისა და change stream-ებისთვის - დიახ, ცალკე მდგომ mongod-ს არცერთი არ უჭერს მხარს. ერთი კვანძის ერთწევრიან replica set-ად გაშვება replSetName-ითა და rs.initiate()-ით ერთ წუთს გრძელდება და ორივეს ხსნის.

რომელია უფრო იაფი პატარა სერვერზე გასაშვებად?

ახლოსაა. PostgreSQL უქმ კავშირებზე უფრო ეკონომიურია აბსოლუტურ გამოხატულებაში მხოლოდ იმ შემთხვევაში, თუ pool-ს სწორად იყენებ, რადგან თითოეული პროცესია; MongoDB-ს თავისი WiredTiger cache უნდა და ადგილი ინდექსებისთვის. 1 GB გეგმაზე ორივე კარგად მუშაობს ნამდვილი აპლიკაციისთვის, და ორივე შემთხვევაში შემზღუდავი ფაქტორია, ეტევა თუ არა შენი სამუშაო ნაკრები და ინდექსები მეხსიერებაში.

შემიძლია ორივე გამოვიყენო ერთ აპლიკაციაში?

დიახ, და ბევრი ხალხი იყენებს - Postgres ჩანაწერებისთვის, რომლებიც სწორი უნდა იყოს, MongoDB event ან დოკუმენტური მონაცემებისთვის. ხარჯის შესახებ პატიოსანი იყავი: ორი ძრავა backup-ისთვის, განახლებისთვის, მონიტორინგისთვის და დასაკავშირებლად, და ტრანზაქცია, რომელიც წყვილს გადაფარავს, არ არსებობს. გააკეთე ეს იმიტომ, რომ დატვირთვა ამას მოითხოვს და არა არჩევანის თავიდან ასაცილებლად.

რამდენად რთულია მოგვიანებით გადართვა?

უფრო რთული, ვიდრე ჰოსტის გადატანა, უფრო ადვილი, ვიდრე გადაწერა. მონაცემები გადაკონვერტირდება; მოთხოვნების კოდი - არა. ყოველი ადგილი, სადაც შენი აპლიკაცია ბაზას ეხება, უნდა შეიცვალოს, და სწორედ ამიტომ ღირს არჩევანი ახლა ოც წუთად და არა წელიწადში ორ კვირად.


კომენტარები

სრულიად ანონიმურად: ანგარიშის, ელფოსტის და cookie-ის გარეშე. ინახება მხოლოდ სახელი, ტექსტი და დრო - სხვა არაფერი. ბმულების რაოდენობა ლიმიტირებულია.

0/2000