{"id":55011,"date":"2020-01-10T00:00:00","date_gmt":"2020-01-09T21:00:00","guid":{"rendered":"https:\/\/prohoster.info\/blog\/blog_prohoster\/bd-messendzhera-ch-1-proektiruem-karkas-bazy"},"modified":"2020-02-18T14:03:05","modified_gmt":"2020-02-18T11:03:05","slug":"bd-messendzhera-ch-1-proektiruem-karkas-bazy","status":"publish","type":"post","link":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/bd-messendzhera-ch-1-proektiruem-karkas-bazy","title":{"rendered":"Database of the Messenger (Part 1): Designing the Framework","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>How to translate business requirements into specific data structures using the example of designing a database for a messenger from scratch.<\/p>\n<ul>\n<li>Part 1: designing the database framework<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/483170\/\">Part 2: partitioning 'live'<\/a><\/noindex><\/li>\n<\/ul>\n<p>\n<img decoding=\"async\" alt=\"Database of the Messenger (Part 1): Designing the Framework\" src=\"\/wp-content\/uploads\/2020\/01\/d4e85052405da3f6580e4e931c292079.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\nOur database will not be as large and distributed as <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/vk\/blog\/342570\/\">VKontakte<\/a><\/noindex> or <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/oleg-bunin\/blog\/340976\/\">Badoo<\/a><\/noindex>, but rather \"just enough\" that performs well\u2014functionally, quickly, and <b>fits on a single server.<\/b> PostgreSQL\u2014to allow deploying a separate instance of the service somewhere on the side, for example.<\/p>\n<p>Therefore, we will not touch on issues of sharding, replication, and geo-distributed systems, but focus on schema solutions within the database.<br \/>\n<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h2>Step 1: A bit of business specificity.<\/h2>\n<p>\nWe will design our messaging exchange not abstractly but integrate it into the environment of a <noindex><a rel=\"nofollow\" href=\"https:\/\/sbis.ru\/help\/work_in\/sms\/\">corporate social network.<\/a><\/noindex>This means that people are not just \"chatting\" but communicating with each other in the context of solving specific business tasks.<\/p>\n<p>What kind of tasks does a business have? Let's look at the example of Vasily\u2014the head of the development department.<\/p>\n<ul>\n<li><i>\"Nikolai, we need a patch on this task by today!\"<\/i><br \/>\nThis means that exchanges can happen in the context of some <b>Housing: rent and mortgage<\/b>.<\/li>\n<li><i>\"Kolya, wanna play Dota tonight?\"<\/i><br \/>\nSo even between one pair of interlocutors, communication can occur simultaneously on <b>different topics.<\/b>.<\/li>\n<li><i>\"Petr, Nikolai, check the attached price list for the new server.\"<\/i><br \/>\nThus, one message can have <b>multiple recipients.<\/b>At the same time, a message can contain <b>attached files.<\/b>.<\/li>\n<li><i>\"Semyon, you take a look too.\"<\/i><br \/>\nAnd there should be an option to invite a new participant into an ongoing conversation. <b>We'll stop here for now on this list of \"obvious\" needs.<\/b>.<\/li>\n<\/ul>\n<p>\nWithout understanding the application-specific task and its constraints, designing an<\/p>\n<blockquote><p>effective <b>database schema for its solution is practically impossible.<\/b> Step 2: Minimal logical schema.<\/p><\/blockquote>\n<p><\/p>\n<h2>So far, the schema looks very much like an email exchange\u2014a traditional business communication tool. Indeed, \"algorithmically,\" many business tasks are alike, and thus the tools for their resolution will be structurally similar.<\/h2>\n<p>\nLet's fix the already obtained logical schema of entity relationships. For simplicity in understanding our model, we will use the most primitive representation of an<\/p>\n<p>ER model <noindex><a rel=\"nofollow\" href=\"https:\/\/ru.wikipedia.org\/wiki\/ER-%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C\">without the complexities of UML or IDEF notations:<\/a><\/noindex> without complicating UML or IDEF notations:<\/p>\n<p><img decoding=\"async\" alt=\"Database of the Messenger (Part 1): Designing the Framework\" src=\"\/wp-content\/uploads\/2020\/01\/75d0b3cf9e5a44ae3e243449fa406fbc.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\nIn our example, the persona, document, and binary \"body\" of the file are considered \"external\" entities that exist independently of our service. Therefore, we will refer to them as links \"somewhere\" by UUID from now on.<\/p>\n<blockquote><p>Draw <b>the diagrams as simply as possible<\/b> \u2014 most of those to whom you will show them are not experts in reading UML\/IDEF. But do draw them anyway.<\/p><\/blockquote>\n<p><\/p>\n<h2>Step 3: Drafting the table structure<\/h2>\n<p>\n<b class=\"spoiler_title\">About table and field names<\/b>You can have different opinions about 'Russian' names of fields and tables, but it's a matter of taste. Since <noindex><a rel=\"nofollow\" href=\"https:\/\/tensor.ru\/about\/career\/vacancies\">we don't have foreign developers in 'Tensor', and PostgreSQL allows us to use names even in hieroglyphs, as long as they<\/a><\/noindex> are enclosed in quotes <u>, we prefer naming objects clearly and understandably to avoid misunderstandings.<\/u>Let's look at the resulting plan:<br \/>\nSince messages are written by multiple people at once, some of them may even do so <u>in offline mode<\/u>, the simplest option is to <b>use UUIDs as identifiers<\/b> not only for external entities but also for all objects within our service. Moreover, they can even be generated on the client side \u2014 this will help us support message sending during temporary database unavailability, and the likelihood of collisions is extremely low.<\/p>\n<p>The draft structure of the tables in our database will look like this:<br \/>\n<b class=\"spoiler_title\">Tables: RU<\/b><\/p>\n<pre><code class=\"sql\">CREATE TABLE \"\u0422\u0435\u043c\u0430\"(\n  \"\u0422\u0435\u043c\u0430\"\n    uuid\n      PRIMARY KEY\n, \"\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\"\n    uuid\n, \"\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\"\n    text\n);\n\nCREATE TABLE \"\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\"(\n  \"\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\"\n    uuid\n      PRIMARY KEY\n, \"\u0422\u0435\u043c\u0430\"\n    uuid\n, \"\u0410\u0432\u0442\u043e\u0440\"\n    uuid\n, \"\u0414\u0430\u0442\u0430\u0412\u0440\u0435\u043c\u044f\"\n    timestamp\n, \"\u0422\u0435\u043a\u0441\u0442\"\n    text\n);\n\nCREATE TABLE \"\u0410\u0434\u0440\u0435\u0441\u0430\u0442\"(\n  \"\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\"\n    uuid\n, \"\u041f\u0435\u0440\u0441\u043e\u043d\u0430\"\n    uuid\n, PRIMARY KEY(\"\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\", \"\u041f\u0435\u0440\u0441\u043e\u043d\u0430\")\n);\n\nCREATE TABLE \"\u0424\u0430\u0439\u043b\"(\n  \"\u0424\u0430\u0439\u043b\"\n    uuid\n      PRIMARY KEY\n, \"\u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\"\n    uuid\n, \"BLOB\"\n    uuid\n, \"\u0418\u043c\u044f\"\n    text\n);<\/code><\/pre>\n<p>\n<b class=\"spoiler_title\">Tables: EN<\/b><\/p>\n<pre><code class=\"sql\">CREATE TABLE theme(\n  theme\n    uuid\n      PRIMARY KEY\n, document\n    uuid\n, title\n    text\n);\n\nCREATE TABLE message(\n  message\n    uuid\n      PRIMARY KEY\n, theme\n    uuid\n, author\n    uuid\n, dt\n    timestamp\n, body\n    text\n);\n\nCREATE TABLE message_addressee(\n  message\n    uuid\n, person\n    uuid\n, PRIMARY KEY(message, person)\n);\n\nCREATE TABLE message_file(\n  file\n    uuid\n      PRIMARY KEY\n, message\n    uuid\n, content\n    uuid\n, filename\n    text\n);<\/code><\/pre>\n<p><\/p>\n<blockquote><p>The simplest way to describe the format is to start \"unpacking\" the relationship graph <b>from tables that do not reference<\/b> anyone.<\/p><\/blockquote>\n<p><\/p>\n<h2>Step 4: Identifying non-obvious needs<\/h2>\n<p>\nThat's it, we have designed a database that we can write to excellently and <i><b>somehow<\/b><\/i> read.<\/p>\n<p>Let's put ourselves in the shoes of a user of our service \u2014 what would we want to do with it?<\/p>\n<ul>\n<li><i>Recent messages<\/i><br \/>\nThis <b>a chronologically sorted<\/b> by various criteria, the registry of \"my\" messages. Where I am one of the recipients, where I am the author, where someone wrote to me, but I did not respond, where I did not receive a response, ...<\/li>\n<li><i>Participants in the correspondence<\/i><br \/>\nWho is actually involved in this long, long chat?<\/li>\n<\/ul>\n<p>\nOur structure allows us to solve both of these tasks in general, but not quickly. The problem is that for sorting within the framework of the first task, <b>it is impossible to create an index<\/b>, suitable for each of the participants (and we would have to extract all records), and to solve the second one, we need to <b>extract all messages<\/b> on the topic.<\/p>\n<blockquote><p>Unforeseen user tasks can put a serious <b>strain on performance<\/b>.<\/p><\/blockquote>\n<p><\/p>\n<h2>Step 5: Reasonable Denormalization<\/h2>\n<p>\nBoth of our problems can be solved with additional tables, where we will <b>duplicate part of the data<\/b>, necessary for forming suitable indexes for our tasks.<br \/>\n<img decoding=\"async\" alt=\"Database of the Messenger (Part 1): Designing the Framework\" src=\"\/wp-content\/uploads\/2020\/01\/f136a9904518b05bca74cc2b9c2f01b2.jpg\" style=\"display:block;margin: 0 auto;\" \/><br \/>\n<br \/>\n<b class=\"spoiler_title\">Tables: RU<\/b><\/p>\n<pre><code class=\"sql\">CREATE TABLE \"MessageRegistry\"(\n  \"Owner\"\n    uuid\n, \"RegistryType\"\n    smallint\n, \"DateTime\"\n    timestamp\n, \"Message\"\n    uuid\n, PRIMARY KEY(\"Owner\", \"RegistryType\", \"Message\")\n);\nCREATE INDEX ON \"MessageRegistry\"(\"Owner\", \"RegistryType\", \"DateTime\" DESC);\n\nCREATE TABLE \"ThemeParticipant\"(\n  \"Theme\"\n    uuid\n, \"Person\"\n    uuid\n, PRIMARY KEY(\"Theme\", \"Person\")\n);<\/code><\/pre>\n<p>\n<b class=\"spoiler_title\">Tables: EN<\/b><\/p>\n<pre><code class=\"sql\">CREATE TABLE message_registry(\n  owner\n    uuid\n, registry\n    smallint\n, dt\n    timestamp\n, message\n    uuid\n, PRIMARY KEY(owner, registry, message)\n);\nCREATE INDEX ON message_registry(owner, registry, dt DESC);\n\nCREATE TABLE theme_participant(\n  theme\n    uuid\n, person\n    uuid\n, PRIMARY KEY(theme, person)\n);<\/code><\/pre>\n<p>\nHere we applied two typical approaches used when creating auxiliary tables:<\/p>\n<ul>\n<li><b>Record multiplication<\/b><br \/>\nWe create several consequential records from one original message record in different types of registries for different owners \u2014 for both the sender and the recipient. Now each of the registries fits the index \u2014 since in a typical case, we would want to see only the first page.<\/li>\n<li><b>Record uniqueness<\/b><br \/>\nWhen sending a message within a specific topic, it is sufficient to check whether such a record already exists. If not, we add it to our 'dictionary'.<\/li>\n<\/ul>\n<p>\nIn the next part of the article, we will discuss <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/483170\/\">the implementation of partitioning<\/a><\/noindex> into our database structure.<br \/>\n<br \/>Source: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/483176\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u00ab\u0441 \u043d\u0443\u043b\u044f\u00bb \u0431\u0430\u0437\u044b \u0434\u043b\u044f \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430. \u0427\u0430\u0441\u0442\u044c 1: \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u043a\u0430\u0440\u043a\u0430\u0441 \u0431\u0430\u0437\u044b \u0427\u0430\u0441\u0442\u044c 2: \u0441\u0435\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u0443\u0435\u043c \u00ab\u043d\u0430\u0436\u0438\u0432\u0443\u044e\u00bb \u041d\u0430\u0448\u0430 \u0431\u0430\u0437\u0430 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435 \u0442\u0430\u043a\u043e\u0439 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u043d\u043e\u0439 \u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439, \u043a\u0430\u043a \u0443 \u0412\u041a\u043e\u043d\u0442\u0430\u043a\u0442\u0435 \u0438\u043b\u0438 Badoo, \u0430 \u00ab\u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u043e\u00bb, \u043d\u043e \u0431\u044b\u043b\u043e \u0445\u043e\u0440\u043e\u0448\u043e \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e, \u0431\u044b\u0441\u0442\u0440\u043e \u0438 \u0443\u043c\u0435\u0449\u0430\u043b\u043e\u0441\u044c \u043d\u0430 \u043e\u0434\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0435 PostgreSQL \u2014 \u0447\u0442\u043e\u0431\u044b [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-55011","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u00ab\u0441 \u043d\u0443\u043b\u044f\u00bb \u0431\u0430\u0437\u044b \u0434\u043b\u044f \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430. \u0427\u0430\u0441\u0442\u044c 1: \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u043a\u0430\u0440\u043a\u0430\u0441 \u0431\u0430\u0437\u044b\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/bd-messendzhera-ch-1-proektiruem-karkas-bazy\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0411\u0414 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430 (\u0447.1): \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u043a\u0430\u0440\u043a\u0430\u0441 \u0431\u0430\u0437\u044b | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u00ab\u0441 \u043d\u0443\u043b\u044f\u00bb \u0431\u0430\u0437\u044b \u0434\u043b\u044f \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430. \u0427\u0430\u0441\u0442\u044c 1: \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u043a\u0430\u0440\u043a\u0430\u0441 \u0431\u0430\u0437\u044b\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/bd-messendzhera-ch-1-proektiruem-karkas-bazy\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2020-01-09T21:00:00+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-02-18T11:03:05+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Messenger DB (Part 1): Designing the Database Framework | ProHoster","description":"How to translate business requirements into specific data structures on the example of designing a database for a messenger from scratch. Part 1: designing the database framework","canonical_url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/bd-messendzhera-ch-1-proektiruem-karkas-bazy","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0411\u0414 \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430 (\u0447.1): \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u043a\u0430\u0440\u043a\u0430\u0441 \u0431\u0430\u0437\u044b | ProHoster","og:description":"\u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0432\u0435\u0441\u0442\u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u00ab\u0441 \u043d\u0443\u043b\u044f\u00bb \u0431\u0430\u0437\u044b \u0434\u043b\u044f \u043c\u0435\u0441\u0441\u0435\u043d\u0434\u0436\u0435\u0440\u0430. \u0427\u0430\u0441\u0442\u044c 1: \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u043a\u0430\u0440\u043a\u0430\u0441 \u0431\u0430\u0437\u044b","og:url":"https:\/\/prohoster.info\/en\/blog\/administrirovanie\/bd-messendzhera-ch-1-proektiruem-karkas-bazy","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2020-01-09T21:00:00+00:00","article:modified_time":"2020-02-18T11:03:05+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"55011","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-24 13:30:15","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 17:27:13","updated":"2026-01-24 13:30:15","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/55011","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/comments?post=55011"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/55011\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media?parent=55011"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/categories?post=55011"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/tags?post=55011"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}