{"id":83649,"date":"2020-06-02T07:42:21","date_gmt":"2020-06-02T05:42:21","guid":{"rendered":"https:\/\/prohoster.info\/blog\/administrirovanie\/database-as-sode-experience"},"modified":"2020-06-02T07:42:21","modified_gmt":"2020-06-02T05:42:21","slug":"database-as-sode-experience","status":"publish","type":"post","link":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/database-as-sode-experience","title":{"rendered":"\u00abAndmed kui kood\u00bb kogemus","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"\u00abAndmed kui kood\u00bb kogemus\" src=\"\/wp-content\/uploads\/2020\/06\/a1ac23deeded97559fbe787ed09184a5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>SQL, mis v\u00f5iks olla lihtsam? Iga\u00fchel meist on v\u00f5imalik kirjutada lihtne p\u00e4ring \u2014 kirjutame <strong><em>select<\/em><\/strong>, loetleme vajalikud veerud, seej\u00e4rel <strong><em>from<\/em><\/strong>, tabeli nimi, natuke tingimusi <strong><em>where<\/em><\/strong> ja k\u00f5ik \u2014 kasulikud andmed on meie k\u00e4sutuses, (peaaegu) s\u00f5ltumatult sellest, millisest andmebaasis\u00fcsteemist me r\u00e4\u00e4gime (v\u00f5ib-olla see ei ole isegi <noindex><a rel=\"nofollow\" href=\"https:\/\/osquery.io\/\">ande s\u00fcsteem)<\/a><\/noindex>). Seet\u00f5ttu saab praktiliselt iga andmeallikaga (suhtelise ja muu) t\u00f6\u00f6tlust k\u00e4sitleda nagu tavalist koodi (k\u00f5ikide tagaj\u00e4rgedega - versioonihaldus, koodi \u00fclevaatus, staatiline anal\u00fc\u00fcs, automaattestid ja k\u00f5ik see muu). See kehtib mitte ainult andmete, skeemide ja migratsioonide, vaid ka kogu teabehoidmise igap\u00e4evaelu kohta. Selles artiklis r\u00e4\u00e4gime igap\u00e4evastest \u00fclesannetest ja probleemidest, millega silmitsi seisavad erinevad andmebaasid, l\u00e4henedes &quot;andmebaas koodina&quot; temaatikale.<\/p>\n<p><\/p>\n<p>Ja alustame otse <noindex><a rel=\"nofollow\" href=\"https:\/\/www.yegor256.com\/2014\/12\/01\/orm-offensive-anti-pattern.html\">ORM<\/a><\/noindex>. Esimesed lahingud stiilis &quot;SQL vs ORM&quot; m\u00e4rgati juba <noindex><a rel=\"nofollow\" href=\"https:\/\/www.sql.ru\/forum\/904343\/orm-vs-sql\">eelk\u00e4ija Venemaal<\/a><\/noindex>.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h5 id=\"obektno-relyacionnyy-maping\">Objekt-relatsiooniline kaardistamine<\/h5>\n<p><\/p>\n<p>ORM-i toetajad hindavad traditsiooniliselt arendamise kiirust ja lihtsust, s\u00f5ltumatust andmebaasis\u00fcsteemist ning koodi puhtust. Paljude jaoks n\u00e4eb andmebaasit\u00f6\u00f6 kood (ja sageli isegi andmebaas ise)<\/p>\n<p><\/p>\n<p>                        <b class=\"spoiler_title\">tavaliselt n\u00e4eb v\u00e4lja umbes nii\u2026<\/b><\/p>\n<pre><code class=\"java\">@Entity\n@Table(name = &quot;stock&quot;, catalog = &quot;maindb&quot;, uniqueConstraints = {\n        @UniqueConstraint(columnNames = &quot;STOCK_NAME&quot;),\n        @UniqueConstraint(columnNames = &quot;STOCK_CODE&quot;) })\npublic class Stock implements java.io.Serializable {\n\n    @Id\n    @GeneratedValue(strategy = IDENTITY)\n    @Column(name = &quot;STOCK_ID&quot;, unique = true, nullable = false)\n    public Integer getStockId() {\n        return this.stockId;\n    }\n  ...<\/code><\/pre>\n<p><\/p>\n<p>Mudel on varustatud nutikate annotatsioonidega, samal ajal kui hiilgav ORM genereerib ja t\u00e4idab tohutult SQL-koodi. Pealegi p\u00fc\u00fcavad arendajad igasuguste abstraktsioonidega ennast oma andmebaasist eemal hoida, mis viitab teatud <noindex><a rel=\"nofollow\" href=\"https:\/\/www.sql.ru\/forum\/1303231\/prichiny-nenavisti-k-yazyku-sql\">&quot;SQL vihkamise&quot;<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Teisel pool barikaadi toetajad puhta \"handmade\"-SQL-i osas r\u00f5hutavad v\u00f5imalust oma andmebaasist maksimum v\u00e4lja pigistada ilma lisakihtide ja abstraktsioonideta. Selle tulemusena tekivad \"data-centric\" projektid, kus andmebaasidega tegelevad spetsiaalselt koolitatud inimesed (need on \"basiistid\", \"basiikud\", \"bazi-j\u00e4rjed\" jne), ning arendajatel j\u00e4\u00e4b vaid \"t\u00f5mmata\" valmis vaateid ja salvestatud protseduure, sukeldumata detailidesse.<\/p>\n<p><\/p>\n<p>Aga mis oleks, kui v\u00f5tta parimad omadused kummastki maailmast? Nii on tehtud selles suurep\u00e4rases t\u00f6\u00f6riistas, millel on eluj\u00f5uline nimi <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/krisajenkins\/yesql\">Yesql<\/a><\/noindex>. Toodan paar rida \u00fcldisest kontseptsioonist oma vabalt t\u00f5lgituna, aga rohkemate detailidega saab tutvuda <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/krisajenkins\/yesql#rationale\">siit<\/a><\/noindex>.<\/p>\n<p><\/p>\n<blockquote><p>Clojure on suurep\u00e4rane keel DSL-ide loomiseks, kuid SQL on juba iseenesest \u00e4ge DSL ning me ei vaja \u00fchtegi uut. S-expression\u2019id on kaunid, kuid siin ei lisa need midagi uut. L\u00f5puks saame ainult sulud sulude p\u00e4rast. Ei ole n\u00f5us? Oodake hetke, kui abstraktsioon andmebaasi kohal lekib ja alustate v\u00f5itlust funktsiooniga. <em>(raw-sql)<\/em><\/p>\n<p>Ja mis siis teha? J\u00e4tame SQL-i tavalise SQL-ina \u2014 \u00fcks fail \u00fche p\u00e4ringu jaoks:<\/p><\/blockquote>\n<p><\/p>\n<pre><code class=\"sql\">-- name: users-by-country\nselect *\n  from users\n where country_code = :country_code<\/code><\/pre>\n<p><\/p>\n<blockquote><p>\u2026 ning seej\u00e4rel lugege see fail ning muundage see tavaliseks Clojure funktsiooniks:<\/p><\/blockquote>\n<p><\/p>\n<pre><code class=\"lisp\">(defqueries \"some\/where\/users_by_country.sql\"\n   {:connection db-spec})\n\n;;; Funktsioon nimega `users-by-country` on loodud.\n;;; Kasutame seda:\n(users-by-country {:country_code \"GB\"})\n;=&gt; ({:name \"Kris\" :country_code \"GB\" ...} ...)<\/code><\/pre>\n<p><\/p>\n<blockquote><p>J\u00e4rgides printsiipi \"SQL eraldi, Clojure eraldi\", saate:<\/p>\n<ul>\n<li>Ei mingeid s\u00fcntaktilisi \u00fcllatusi. Teie andmebaas (nagu \u00fcksk\u00f5ik milline teine) ei vasta SQL standardile 100% \u2014 aga Yesql jaoks pole see oluline. Te kunagi ei raiska aega funktsioonide otsimisele, mille s\u00fcntaks on SQL-i omaga v\u00f5rreldav. Te ei pea kunagi tagasi minema funktsiooni juurde <em>(raw-sql \"some (\u2018funky\u2019 :: SYNTAX)\"))<\/em>.<\/li>\n<li>Parim toimetaja tugi. Teie toimetajal on juba suurep\u00e4rane SQL-tugi. Hoides SQL-d SQL-ina, saate seda lihtsalt kasutada.<\/li>\n<li>Klienditugi. Teie DBA-d saavad lugeda ja kirjutada SQL-i, mida kasutate oma Clojure projektis.<\/li>\n<li>Lihtsam j\u00f5udluse seadistamine. Kas peate koostama plaani probleemse p\u00e4ringu jaoks? See ei ole probleem, kui teie p\u00e4ring on tavaline SQL.<\/li>\n<li>P\u00e4ringute taaskasutamine. Looge need samad SQL-failid teistesse projektidesse, sest see on lihtsalt vana hea SQL \u2014 jagage seda lihtsalt.<\/li>\n<\/ul>\n<p>\n<\/p><\/blockquote>\n<p>Minu arvates on see idee v\u00e4ga \u00e4ge ja samas v\u00e4ga lihtne, mille t\u00f5ttu projekt on saanud palju <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/krisajenkins\/yesql#other-languages\">j\u00e4rgijad<\/a><\/noindex> erinevates keeltes. Proovime edasi rakendada sarnast filosoofiat, et eraldada SQL-kood k\u00f5igest muust kaugelt \u00fcle ORM-i piiri.<\/p>\n<p><\/p>\n<h5 id=\"ide--db-menedzhery\">IDE &amp; DB-haldurid<\/h5>\n<p><\/p>\n<p>Alustame lihtsast igap\u00e4evasest \u00fclesandest. Sage on vajadus otsida andmebaasist objekti, n\u00e4iteks leida skeemist tabel ja uurida selle struktuuri (millised veerud, v\u00f5tmed, indeksid, piirangud jne on kasutusel). Igal juhul ootame me igasugustelt graafilistelt IDE-delt v\u00f5i v\u00e4hemalt  minimaalsetelt DB-manager\u2019itelt, et need oskaksid just seda teha. Et see toimiks kiiresti ja me ei peaks ootama pool tundi, kuni avaneb aken vajaliku informatsiooniga (eriti aeglase kaugandmebaasi \u00fchenduse korral), ja et informatsioon oleks v\u00e4rske ja ajakohane, mitte vananenud cache\u2019itud andmed. Mida keerulisem ja suurem on andmebaas ja mida rohkem on neid, seda raskem on seda saavutada.<\/p>\n<p><\/p>\n<p>Kuid tavaliselt viskan hiire kaugele ja kirjutan lihtsalt koodi. Oletame, et on vajalik teada saada, millised tabelid (ja milliste omadustega) on skeemis \"HR\". Enamikus andmebaasi juhtimistarkvarades saab vajaliku tulemuse kergesti j\u00e4rgmist t\u00fc\u00fcpi p\u00e4ringuga information_schema-st:<\/p>\n<p><\/p>\n<pre><code class=\"sql\">select table_name\n     , ...\n  from information_schema.tables\n where schema = 'HR'<\/code><\/pre>\n<p><\/p>\n<p>Tabelite sisu varieerub kindlasti p\u00f5hjaliku andmebaasi ja iga S\u00dcBDB v\u00f5imete j\u00e4rgi. N\u00e4iteks MySQL-i puhul on v\u00f5imalik sama juhendi abil saada selle S\u00dcBDB spetsiifilisi tabeli parameetreid:<\/p>\n<p><\/p>\n<pre><code class=\"sql\">select table_name\n     , storage_engine -- Kasutatav \"mootor\" (\"MyISAM\", \"InnoDB\" jne)\n     , row_format     -- Rea formaat (\"Fixed\", \"Dynamic\" jne)\n     , ...\n  from information_schema.tables\n where schema = 'HR'<\/code><\/pre>\n<p><\/p>\n<p>Oracle ei kasuta information_schema, kuid tal on olemas <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Oracle_metadata\">Oracle metadata<\/a><\/noindex>, mis ei tekita suuri probleeme:<\/p>\n<p><\/p>\n<pre><code class=\"sql\">select table_name\n     , pct_free       -- minimaalne vabade kohtade prosent andmeplokis (%)\n     , pct_used       -- minimaalne kasutatud kohtade prosent andmeplokis (%)\n     , last_analyzed  -- Viimase statistika kogumise kuup\u00e4ev\n     , ...\n  from all_tables\n where owner = 'HR'<\/code><\/pre>\n<p><\/p>\n<p>Sama kehtib ka ClickHouse'i kohta:<\/p>\n<p><\/p>\n<pre><code class=\"sql\">valige nimi\n     , mootor -- Kasutatav \"mootor\" (\"MergeTree\", \"Dictionary\" jne)\n     , ...\n  from system.tables\n where andmebaas = 'HR'<\/code><\/pre>\n<p><\/p>\n<p>midagi sarnast saab teha ka Cassandra's (kus on columnfamilies tabelite asemel ja keyspace'id skeemide asemel):<\/p>\n<p><\/p>\n<pre><code class=\"sql\">select columnfamily_name\n     , compaction_strategy_class  -- Prahdihaldustrateegia\n     , gc_grace_seconds           -- Prahti eluaeg\n     , ...\n  from system.schema_columnfamilies\n where keyspace_name = 'HR'<\/code><\/pre>\n<p><\/p>\n<p>Enamik teisi andmebaase v\u00f5imaldab samuti sarnaste p\u00e4ringute koostamist (isegi Mongo-s on olemas <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.mongodb.com\/manual\/reference\/system-collections\/#%3Cdatabase%3E.system.namespaces\">spetsiaalne s\u00fcsteemi kogu<\/a><\/noindex>, mis sisaldab teavet k\u00f5ikide s\u00fcsteemi kogumite kohta).<\/p>\n<p><\/p>\n<p>Muidugi, selle meetodiga saab teavet saada mitte ainult tabelite, vaid ka igasuguste objektide kohta. Aeg-ajalt jagavad head inimesed sellist koodi erinevate andmebaaside jaoks, nagu n\u00e4iteks Habr'i artiklite seerias \"Funktsioonid PostgreSQL andmebaaside dokumenteerimiseks\" (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/post\/415575\">aib<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/post\/415897\">ben<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/post\/418597\">gim<\/a><\/noindex>). Loomulikult pole kogu selle hulga p\u00e4ringute meeles pidamine ja pidev nende sisestamine just \"m\u00f5nus\" tegevus, seet\u00f5ttu on mul oma lemmik IDE\/suurendajas eelnevalt koostatud kogum snippette sagedasti kasutatavate p\u00e4ringute jaoks, ja j\u00e4\u00e4b vaid objekti nimed mallide sisse tr\u00fckkida.<\/p>\n<p><\/p>\n<p>Seet\u00f5ttu on selline navigeerimise ja objektide otsimise meetod palju paindlikum, s\u00e4\u00e4stab aega ja v\u00f5imaldab saada just seda teavet ja sellisel viisil, nagu praegu vajalik (nagu on kirjeldatud postituses <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/JetBrains\/blog\/342094\">\"Andmete eksportimine andmebaasist mis tahes formaadis: mida oskavad IntelliJ platvormi IDE-d\"<\/a><\/noindex>).<\/p>\n<p><\/p>\n<h5 id=\"operacii-s-obektami\">Objektide toimingud<\/h5>\n<p><\/p>\n<p>P\u00e4rast seda, kui oleme leidnud ja uurinud vajalikud objektid, on aeg nendega midagi kasulikku teha. Loomulikult, hoides s\u00f5rmi klaviatuurilt lahus.<\/p>\n<p><\/p>\n<p>Pole saladus, et lihtne tabeli kustutamine n\u00e4eb v\u00e4lja peaaegu k\u00f5igis andmebaasides sama:<\/p>\n<p><\/p>\n<pre><code class=\"sql\">drop table hr.persons<\/code><\/pre>\n<p><\/p>\n<p>Aga tabeli loomine on juba huvitavam. Peaaegu iga andmebaasis\u00fcsteem (sealhulgas paljud NoSQL lahendused) suudab mingil kujul \"create table\" k\u00e4su t\u00e4ita, ning selle p\u00f5hiosad, nagu nimi, veergude loetelu ja andmet\u00fc\u00fcbid, j\u00e4\u00e4vad sarnasteks. Kuid muud detailid v\u00f5ivad dramaatiliselt erineda ning s\u00f5ltuvad konkreetse andmebaasis\u00fcsteemi sisemisest struktuurist ja v\u00f5imalustest. Minu lemmikn\u00e4ide on see, et Oracle'i dokumentatsioonis on ainult \"paljad\" BNF\u2019id \"create table\" s\u00fcntaksile. <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/19\/sqlrf\/sql-language-reference.pdf\">nakatab 31 lehek\u00fclge<\/a><\/noindex>. Teised andmebaasis\u00fcsteemid omavad tagasihoidlikumaid v\u00f5imalusi, kuid iga\u00fchel neist on samuti palju huvitavaid ja unikaalseid omadusi tabelite loomisel (<noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/static\/sql-createtable.html\">postgres<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/create-table.html\">mysql<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.cockroachlabs.com\/docs\/stable\/create-table.html#expanded\">cockroach<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.datastax.com\/en\/cql\/3.3\/cql\/cql_reference\/cqlCreateTable.html\">cassandra<\/a><\/noindex>). T\u00f5en\u00e4oliselt ei suuda \u00fckski graafiline \"wizard\" j\u00e4rgnevast IDE-st (eriti universaalne) t\u00e4ielikult katta k\u00f5iki neid v\u00f5imalusi, ja kui suudab, on see vaatepilt mitte n\u00f5rgan\u00e4rvilistele. Samuti on \u00f5igesti ja \u00f5igel ajal kirjutatud k\u00e4sk. <strong><em>create table<\/em><\/strong> v\u00f5imaldab h\u00f5lpsasti kasutada k\u00f5iki neid, tagades teie andmete talletamise ja juurdep\u00e4\u00e4su usaldusv\u00e4\u00e4rse, optimaalse ja maksimaalselt mugavana.<\/p>\n<p><\/p>\n<p>Paljudes andmebaasis\u00fcsteemides on ka oma spetsiifilised objektit\u00fc\u00fcbid, mida teistes andmebaasis\u00fcsteemides ei esine. Lisaks saame teostada toiminguid mitte ainult andmebaasi objektidega, vaid ka andmebaasis\u00fcsteemiga endaga, n\u00e4iteks \"tapma\" protsessi, vabastama m\u00f5nem\u00e4lu piirkonna, lubama j\u00e4lgimist, minema \"read only\" re\u017eiimi ja palju muud.<\/p>\n<p><\/p>\n<h5 id=\"a-teper-nemnogo-porisuem\">Ja n\u00fc\u00fcd natuke joonistame<\/h5>\n<p><\/p>\n<p>\u00dcks levinumaid \u00fclesandeid on andmebaasi objektide diagrammi koostamine, et n\u00e4ha ilusal pildil objekte ja nende vahelisi seoseid. Peaaegu iga graafiline IDE suudab seda teha, samuti eraldi k\u00e4surea utiliidid, spetsialiseeritud graafilised t\u00f6\u00f6riistad ja mudelid, mis joonistavad teile midagi \u201enagu oskavad\u201c, kuid sellele protsessile saab mingit m\u00f5ju avaldada vaid m\u00f5ne parameetri abil konfiguratsioonifailis v\u00f5i valikutega liideses.<\/p>\n<p><\/p>\n<p>Kuid selle probleemi saab lahendada palju lihtsamalt, paindlikumalt ja elegantsemalt, loomulikult koodi abil. Iga keerukuse diagrammide loomiseks on meil mitmeid spetsialiseeritud markeerimiskeeli (DOT, GraphML jne), ja nende jaoks terve hulk rakendusi (GraphViz, PlantUML, Mermaid), mis oskavad selliseid juhiseid lugeda ja visualiseerida erinevates formaatides. Teavet objektide ja nende vaheliste seoste kohta teame me juba kuidas hankida.<\/p>\n<p><\/p>\n<p>Toome v\u00e4ikese n\u00e4ite sellest, kuidas see v\u00f5iks v\u00e4lja n\u00e4ha, kasutades PlantUML ja <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/postgrespro\/blog\/316428\/\">demonstreerimist PostgreSQL andmebaasist<\/a><\/noindex> (vasakul SQL-p\u00e4ring, mis genereerib PlantUML jaoks vajaliku juhise, paremal on tulemus):<\/p>\n<p>\n<img decoding=\"async\" alt=\"\u00abAndmed kui kood\u00bb kogemus\" src=\"\/wp-content\/uploads\/2020\/06\/c5cb2a138df1527abe47cbf8d695cb36.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<pre><code class=\"sql\">select '@startuml'||chr(10)||'hide methods'||chr(10)||'hide stereotypes' union all\nselect distinct ccu.table_name || ' --|&gt; ' ||\n       tc.table_name as val\n  from table_constraints as tc\n  join key_column_usage as kcu\n    on tc.constraint_name = kcu.constraint_name\n  join constraint_column_usage as ccu\n    on ccu.constraint_name = tc.constraint_name\n where tc.constraint_type = 'FOREIGN KEY'\n   and tc.table_name ~ '.*' union all\nselect '@enduml'<\/code><\/pre>\n<p><\/p>\n<p>Ja kui natuke vaeva n\u00e4ha, siis saab ER-mallil PlantUML jaoks <noindex><a rel=\"nofollow\" href=\"https:\/\/gist.github.com\/QuantumGhost\/0955a45383a0b6c0bc24f9654b3cb561\">luua midagi, mis sarnaneb t\u00f5elise ER-diagrammiga:<\/a><\/noindex> SQL-p\u00e4ring on natuke keerulisem<\/p>\n<p><\/p>\n<p>                        <b class=\"spoiler_title\">SQL-p\u00e4ring on veidi keerulisem<\/b><\/p>\n<pre><code class=\"sql\">-- Pealkiri\nselect &#039;@startuml\n        !define Table(name,desc) class name as &quot;desc&quot; &lt;&lt; (T,#FFAAAA) &gt;&amp;gt;\n        !define primary_key(x) &lt;b&gt;x&lt;\/b&gt;\n        !define unique(x) &lt;color:green&gt;x&lt;\/color&gt;\n        !define not_null(x) &lt;u&gt;x&lt;\/u&gt;\n        hide methods\n        hide stereotypes&#039;\n union all\n-- Tabelid\nselect format(&#039;Table(%s, &quot;%s n information about %s&quot;) {&#039;||chr(10), table_name, table_name, table_name) ||\n       (select string_agg(column_name || &#039; &#039; || upper(udt_name), chr(10))\n          from information_schema.columns\n         where table_schema = &#039;public&#039;\n           and table_name = t.table_name) || chr(10) || &#039;}&#039;\n  from information_schema.tables t\n where table_schema = &#039;public&#039;\n union all\n-- Tabelite vahelised seosed\nselect distinct ccu.table_name || &#039; &quot;1&quot; --&amp;gt; &quot;0..N&quot; &#039; || tc.table_name || format(&#039; : &quot;A %s may have many %s&quot;&#039;, ccu.table_name, tc.table_name)\n  from information_schema.table_constraints as tc\n  join information_schema.key_column_usage as kcu on tc.constraint_name = kcu.constraint_name\n  join information_schema.constraint_column_usage as ccu on ccu.constraint_name = tc.constraint_name\n where tc.constraint_type = &#039;FOREIGN KEY&#039;\n   and ccu.constraint_schema = &#039;public&#039;\n   and tc.table_name ~ &#039;.*&#039;\n union all\n-- Jalus\nselect &#039;@enduml&#039;<\/code><\/pre>\n<p>\n<img decoding=\"async\" alt=\"\u00abAndmed kui kood\u00bb kogemus\" src=\"\/wp-content\/uploads\/2020\/06\/bd45420a4fd1bdfcf20cbe74a0638c7b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Kui hoolikalt vaadata, kasutavad paljud visualiseerimist\u00f6\u00f6riistad t\u00f5epoolest sarnaseid p\u00e4ringuid. T\u00f5si, need p\u00e4ringud on tavaliselt s\u00fcgavalt <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/pgmodeler\/pgmodeler\/blob\/9c615c0b0871df3cd649983ce61e802b0ff0137b\/schemas\/catalog\/table.sch\">\u201ekoodis sees\u201c ja keerulised m\u00f5ista<\/a><\/noindex>, r\u00e4\u00e4kimata nende muutmisest.<\/p>\n<p><\/p>\n<h5 id=\"metriki-i-monitoring\">M\u00f5\u00f5dikud ja j\u00e4lgimine<\/h5>\n<p><\/p>\n<p>Liigume edasi traditsiooniliselt keerulise teema juurde \u2014 andmebaasi j\u00f5udluse j\u00e4lgimine. Meenub \u00fcks v\u00e4ike t\u00f5estis\u00fcndinud lugu, mille r\u00e4\u00e4kis mulle \"\u00fcks minu s\u00f5ber\". \u00dches projektis elas-v\u00f5i-oli \u00fcks v\u00f5imas DBA, kelle isikuga ettev\u00f5tte arendajatest v\u00e4hesed olid isiklikult tuttavad v\u00f5i olid teda kunagi n\u00e4inud (kuigi kahte t\u00fc\u00fcpi r\u00e4\u00e4giti, et ta t\u00f6\u00f6tas kusagil naaberkorpus). \u201eX\u201d-tunnil, kui suure jaekaubanduse tootmis\u00fcsteem hakkas taas \u201ehalvasti end tundma\u201d, saatis ta vaikides ekraanipilte Oracle Enterprise Manageri graafikutest, valides kriitilised kohad ettevaatlikult punase markeriga \u201em\u00f5istmiseks\u201d (see, pehmelt \u00f6eldes, aitas v\u00e4he). Nii tuli neid \u201efotokaarte\u201d kasutada. Samas ei olnud kellelgi juurdep\u00e4\u00e4su kallile (m\u00f5lemas m\u00f5ttes) Enterprise Managerile, sest s\u00fcsteem on keeruline ja kallis. \u00c4kki leiavad arendajad midagi ja k\u00f5ik purunevad. Seet\u00f5ttu leidsid arendajad \u201eempriliselt\u201d aegluse koha ja p\u00f5hjuse ning lasid v\u00e4lja plaastri. Kui DBA \u00e4hvardav kiri ei saabunud l\u00e4hip\u00e4evil uuesti, then k\u00f5ik hingasid kergendatult v\u00e4lja ja naasid oma praeguste \u00fclesannete juurde (kuni j\u00e4rgmise kirjani).<\/p>\n<p><\/p>\n<p>Kuid j\u00e4lgimisprotsess v\u00f5ib olla palju l\u00f5busam ja s\u00f5bralikum, olles samas k\u00f5ikidele kergesti k\u00e4tte saadav ja l\u00e4bipaistev. V\u00e4hemalt selle p\u00f5hiosa, mis t\u00e4iendab peamisi j\u00e4lgimiss\u00fcsteeme (mis on kindlasti kasulikud ja paljude juhtumite puhul asendamatud). Iga andmebaasihalduss\u00fcsteem (DBMS) on valmis jagama teavet oma praeguse seisundi ja j\u00f5udluse kohta t\u00e4iesti tasuta. Sama \"veretuks\" Oracle DB-s on praktiliselt igasugune teave j\u00f5udluse kohta saadaval s\u00fcsteemivaatetelt, alates protsessidest ja sessioonidest kuni puhverkeskuse seisundini (n\u00e4iteks <noindex><a rel=\"nofollow\" href=\"https:\/\/oracle-base.com\/dba\/scripts\">DBA skriptid<\/a><\/noindex>, jaotis \"Monitoring\"). Postgresql-is on samuti rida s\u00fcsteemivaatest, et <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/static\/monitoring-stats.html\">andmebaasi j\u00e4lgimiseks<\/a><\/noindex>, sealhulgas sellised hindamatud, nagu <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/static\/monitoring-stats.html#PG-STAT-ACTIVITY-VIEW\">pg_stat_activity<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/static\/monitoring-stats.html#PG-STAT-DATABASE-VIEW\">pg_stat_database<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/static\/monitoring-stats.html#PG-STAT-BGWRITER-VIEW\">pg_stat_bgwriter<\/a><\/noindex>. MySQL-is on selleks isegi eraldi skeem <noindex><a rel=\"nofollow\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/performance-schema-table-descriptions.html\">performance_schema<\/a><\/noindex>. Ja Mongodb-s on sisseehitatud <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.mongodb.com\/manual\/tutorial\/manage-the-database-profiler\/\">profiler<\/a><\/noindex> andmete kogumiseks j\u00f5udluse kohta s\u00fcsteemi kogumisse <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.mongodb.com\/manual\/tutorial\/manage-the-database-profiler\/#view-profiler-data\">system.profile<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Seega, kasutades m\u00f5nda m\u00f5\u00f5diku kogumist (Telegraf, Metricbeat, Collectd), mis suudab sooritada kohandatud SQL-p\u00e4ringuid, m\u00f5\u00f5tmete salvestamise s\u00fcsteemi (InfluxDB, Elasticsearch, Timescaledb) ja visuaalset t\u00f6\u00f6riista (Grafana, Kibana), on v\u00f5imalik luua piisavalt kerge ja paindlik j\u00e4lgimiss\u00fcsteem, mis on tihedalt seotud teiste s\u00fcsteemi m\u00f5\u00f5tmistega (mille saadakse n\u00e4iteks rakenduste serverilt, ops\u00fcsteemilt jne). N\u00e4iteks on see tehtud pgwatch2-s, kus kasutatakse kombinatsiooni InfluxDB + Grafana ja komplekti p\u00e4ringutest s\u00fcsteemi vaadetele, millele saab samuti <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/cybertec-postgresql\/pgwatch2#adding-metrics\">lisada kohandatud p\u00e4ringuid<\/a><\/noindex>.<\/p>\n<p><\/p>\n<h2 id=\"itogo\">Kokku<\/h2>\n<p><\/p>\n<p>Ja see on ainult ligikaudne loetelu, mida saab meie andmebaasiga tavalise SQL-koodi abil teha. Olen kindel, et on v\u00f5imalik leida veel palju rakendusi, kirjutage kommentaaridesse. Ja sellest, kuidas (ja mis k\u00f5ige t\u00e4htsam, milleks) seda k\u00f5ik automatiseerida ja oma CI\/CD torustikku kaasata, r\u00e4\u00e4gime j\u00e4rgmine kord.<\/p>\n<p>Allikas: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/426833\/\">habr.com<\/a> <\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>SQL, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0449\u0435? \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0430\u0441 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u2014 \u043d\u0430\u0431\u0438\u0440\u0430\u0435\u043c select, \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438, \u0437\u0430\u0442\u0435\u043c from, \u0438\u043c\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u0439 \u0432 where \u0438 \u0432\u0441\u0435 \u2014 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0443 \u043d\u0430\u0441 \u0432 \u043a\u0430\u0440\u043c\u0430\u043d\u0435, \u043f\u0440\u0438\u0447\u0435\u043c (\u043f\u043e\u0447\u0442\u0438) \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0442\u043e\u0433\u043e \u043a\u0430\u043a\u0430\u044f \u0421\u0423\u0411\u0414 \u0432 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c (\u0430 \u043c\u043e\u0436\u0435\u0442 \u0438 \u043d\u0435 \u0421\u0423\u0411\u0414 \u0432\u043e\u0432\u0441\u0435). \u0412 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":83650,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-83649","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"SQL, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0449\u0435? \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0430\u0441 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u2014 \u043d\u0430\u0431\u0438\u0440\u0430\u0435\u043c select, \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438, \u0437\u0430\u0442\u0435\u043c from, \u0438\u043c\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u0439 \u0432 where \u0438 \u0432\u0441\u0435 \u2014 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0443 \u043d\u0430\u0441 \u0432 \u043a\u0430\u0440\u043c\u0430\u043d\u0435, \u043f\u0440\u0438\u0447\u0435\u043c (\u043f\u043e\u0447\u0442\u0438) \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0442\u043e\u0433\u043e \u043a\u0430\u043a\u0430\u044f \u0421\u0423\u0411\u0414 \u0432 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c (\u0430 \u043c\u043e\u0436\u0435\u0442 \u0438 \u043d\u0435 \u0421\u0423\u0411\u0414 \u0432\u043e\u0432\u0441\u0435). \u0412\" \/>\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\/et\/blog\/administrirovanie\/database-as-sode-experience\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"et_EE\" \/>\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\u00abDatabase as \u0421ode\u00bb Experience | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"SQL, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0449\u0435? \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0430\u0441 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u2014 \u043d\u0430\u0431\u0438\u0440\u0430\u0435\u043c select, \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438, \u0437\u0430\u0442\u0435\u043c from, \u0438\u043c\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u0439 \u0432 where \u0438 \u0432\u0441\u0435 \u2014 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0443 \u043d\u0430\u0441 \u0432 \u043a\u0430\u0440\u043c\u0430\u043d\u0435, \u043f\u0440\u0438\u0447\u0435\u043c (\u043f\u043e\u0447\u0442\u0438) \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0442\u043e\u0433\u043e \u043a\u0430\u043a\u0430\u044f \u0421\u0423\u0411\u0414 \u0432 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c (\u0430 \u043c\u043e\u0436\u0435\u0442 \u0438 \u043d\u0435 \u0421\u0423\u0411\u0414 \u0432\u043e\u0432\u0441\u0435). \u0412\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/database-as-sode-experience\" \/>\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-06-02T05:42:21+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-06-02T05:42:21+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\udd47\u201eDatabase as Code\u201c kogemus | ProHoster","description":"SQL, mis v\u00f5iks olla lihtsam? Iga\u00fchel meist on v\u00f5imalik kirjutada lihtne p\u00e4ring \u2014 kirjuta select, loetle vajalikud veerud, siis from, tabeli nimi, veidi tingimusi where ja k\u00f5ik \u2014 vajalikud andmed on meie k\u00e4es, s\u00f5ltumata sellest, milline andmebaasis\u00fcsteem on sel ajal tagak\u00fcljel (v\u00f5i pole see v\u00f5ib-olla isegi andmebaasis\u00fcsteem).","canonical_url":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/database-as-sode-experience","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"et_EE","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\u00abDatabase as \u0421ode\u00bb Experience | ProHoster","og:description":"SQL, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0449\u0435? \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0430\u0441 \u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u2014 \u043d\u0430\u0431\u0438\u0440\u0430\u0435\u043c select, \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438, \u0437\u0430\u0442\u0435\u043c from, \u0438\u043c\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u0439 \u0432 where \u0438 \u0432\u0441\u0435 \u2014 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0443 \u043d\u0430\u0441 \u0432 \u043a\u0430\u0440\u043c\u0430\u043d\u0435, \u043f\u0440\u0438\u0447\u0435\u043c (\u043f\u043e\u0447\u0442\u0438) \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0442\u043e\u0433\u043e \u043a\u0430\u043a\u0430\u044f \u0421\u0423\u0411\u0414 \u0432 \u044d\u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c (\u0430 \u043c\u043e\u0436\u0435\u0442 \u0438 \u043d\u0435 \u0421\u0423\u0411\u0414 \u0432\u043e\u0432\u0441\u0435). \u0412","og:url":"https:\/\/prohoster.info\/et\/blog\/administrirovanie\/database-as-sode-experience","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-06-02T05:42:21+00:00","article:modified_time":"2020-06-02T05:42:21+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"83649","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":null,"breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-02-28 15:13:28","updated":"2022-10-02 10:23:46"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/83649","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/comments?post=83649"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/83649\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media\/83650"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media?parent=83649"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/categories?post=83649"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/tags?post=83649"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}