{"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\/lv\/blog\/administrirovanie\/database-as-sode-experience","title":{"rendered":"\u201eDatu b\u0101ze k\u0101 koda\u201d pieredze","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"\u201eDatu b\u0101ze k\u0101 koda\u201d pieredze\" src=\"\/wp-content\/uploads\/2020\/06\/a1ac23deeded97559fbe787ed09184a5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>SQL, kas var b\u016bt vienk\u0101r\u0161\u0101k? Ikviens no mums var uzrakst\u012bt vienk\u0101r\u0161u vaic\u0101jumu \u2014 ierakst\u0101m <strong><em>select<\/em><\/strong>, uzskait\u0101m nepiecie\u0161am\u0101s kolonnas, tad <strong><em>no<\/em><\/strong>, tabulas nosaukumu, nedaudz nosac\u012bjumu sada\u013c\u0101 <strong><em>where<\/em><\/strong> un viss \u2014 noder\u012bgie dati ir m\u016bsu r\u012bc\u012bb\u0101, gandr\u012bz (l\u012bdz\u012bgi) neatkar\u012bgi no t\u0101, k\u0101da datub\u0101ze \u0161obr\u012bd tiek izmantota (un varb\u016bt tas nav <noindex><a rel=\"nofollow\" href=\"https:\/\/osquery.io\/\">visp\u0101r datub\u0101ze<\/a><\/noindex>). Rezult\u0101t\u0101 darbu praktiski ar jebkuru datu avotu (attiec\u012bgo un ne tik \u013coti) var uzskat\u012bt no parasta koda skatpunkta (ar visiem tam sekojo\u0161iem - versiju vad\u012bba, koda rev\u012bzija, statiska anal\u012bze, autom\u0101tiskie testi un taml\u012bdz\u012bgi). Un tas attiecas ne tikai uz datiem, sh\u0113m\u0101m un migr\u0101cij\u0101m, bet visp\u0101r uz visu glab\u0101tuves darb\u012bbu. \u0160aj\u0101 rakst\u0101 run\u0101sim par ikdienas uzdevumiem un probl\u0113m\u0101m, str\u0101d\u0101jot ar da\u017e\u0101d\u0101m DB, koncentr\u0113joties uz \"database as code\".<\/p>\n<p><\/p>\n<p>Un s\u0101ksim tie\u0161i ar <noindex><a rel=\"nofollow\" href=\"https:\/\/www.yegor256.com\/2014\/12\/01\/orm-offensive-anti-pattern.html\">ORM<\/a><\/noindex>. Pirmie \"SQL vs ORM\" c\u012b\u0146as tika nov\u0113rotas jau <noindex><a rel=\"nofollow\" href=\"https:\/\/www.sql.ru\/forum\/904343\/orm-vs-sql\">pirms P\u0113terburgas<\/a><\/noindex>.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h5 id=\"obektno-relyacionnyy-maping\">Objektu-rel\u0101ciju kart\u0113\u0161ana<\/h5>\n<p><\/p>\n<p>ORM atbalst\u012bt\u0101ji tradicion\u0101li nov\u0113rt\u0113 izstr\u0101des \u0101trumu un vienk\u0101r\u0161\u012bbu, neatkar\u012bbu no datub\u0101zes, un koda t\u012br\u012bbu. Daudziem no mums datu apstr\u0101des kods (un bie\u017ei ar\u012b pati datub\u0101ze)<\/p>\n<p><\/p>\n<p>                        <b class=\"spoiler_title\">parasti izskat\u0101s apm\u0113ram t\u0101\u2026<\/b><\/p>\n<pre><code class=\"java\">@Entity\n@Table(name = \"stock\", catalog = \"maindb\", uniqueConstraints = {\n        @UniqueConstraint(columnNames = \"STOCK_NAME\"),\n        @UniqueConstraint(columnNames = \"STOCK_CODE\") })\npublic class Stock implements java.io.Serializable {\n\n    @Id\n    @GeneratedValue(strategy = IDENTITY)\n    @Column(name = \"STOCK_ID\", unique = true, nullable = false)\n    public Integer getStockId() {\n        return this.stockId;\n    }\n  ...<\/code><\/pre>\n<p><\/p>\n<p>Modelis ir piepild\u012bts ar gudr\u0101m anot\u0101cij\u0101m, un kaut kur aiz ainas varon\u012bgais ORM \u0123ener\u0113 un izpilda tonnas k\u0101da SQL koda. Starp citu, izstr\u0101d\u0101t\u0101ji visiem sp\u0113kiem cen\u0161as atdal\u012bties no savas datub\u0101zes ar kilometriem abstrakciju, kas liecina par zin\u0101mu <noindex><a rel=\"nofollow\" href=\"https:\/\/www.sql.ru\/forum\/1303231\/prichiny-nenavisti-k-yazyku-sql\">\"SQL naida\"<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Otr\u0101 pus\u0113 barik\u0101d\u0113m t\u012br\u0101 \"handmade\"-SQL piekrit\u0113ji atz\u012bm\u0113 iesp\u0113ju izspiest visu no sava DB bez papildu sl\u0101\u0146iem un abstrakcij\u0101m. Rezult\u0101t\u0101 par\u0101d\u0101s \"data-centric\" projekti, kur ar b\u0101z\u0113m str\u0101d\u0101 speci\u0101li apm\u0101c\u012bti cilv\u0113ki (tie pa\u0161i \"b\u0101zisti\", \"b\u0101zoviki\", \"b\u0101zdiennieki\" utt.), un izstr\u0101d\u0101t\u0101jiem atliek tikai \"zvan\u012bt\" uz gatav\u0101m redz\u0113m un glab\u0101t\u0101m proced\u016br\u0101m, neiedzi\u013cinoties deta\u013c\u0101s.<\/p>\n<p><\/p>\n<p>Bet ko, ja \u0146em to lab\u0101ko no ab\u0101m pasaul\u0113m? K\u0101 tas ir izdar\u012bts lieliskaj\u0101 r\u012bk\u0101 ar dz\u012bvotsp\u0113j\u012bgu nosaukumu <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/krisajenkins\/yesql\">Yesql<\/a><\/noindex>. Sniedzu da\u017eus teikumus no visp\u0101r\u0113j\u0101s koncepcijas man\u0101 br\u012bv\u0101 tulkojum\u0101, bet pla\u0161\u0101k ar to var iepaz\u012bties <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/krisajenkins\/yesql#rationale\">\u0161eit<\/a><\/noindex>.<\/p>\n<p><\/p>\n<blockquote><p>Clojure ir lieliska valoda DSL veido\u0161anai, bet SQL jau pats par sevi ir lielisks DSL, un mums nevajag v\u0113l vienu. S-izteiksmes ir br\u012bni\u0161\u0137\u012bgas, bet \u0161eit t\u0101s neko jaunu nepievieno. Rezult\u0101t\u0101 m\u0113s ieg\u016bstam p\u0113das tikai t\u0101p\u0113c, ka t\u0101s ir p\u0113das. Nevienojaties? Tad gaidiet br\u012bdi, kad abstrakcija p\u0101r DB s\u0101ks pl\u016bst, un j\u016bs uzs\u0101ksiet c\u012b\u0146u ar funkciju <em>(raw-sql)<\/em><\/p>\n<p>Un ko dar\u012bt? Atst\u0101sim SQL parastu SQL \u2014 viens fails uz vienu piepras\u012bjumu:<\/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 un p\u0113c tam izlasiet \u0161o failu, p\u0101rv\u0113r\u0161ot to par parastu Clojure funkciju:<\/p><\/blockquote>\n<p><\/p>\n<pre><code class=\"lisp\">(defqueries \"some\/where\/users_by_country.sql\"\n   {:connection db-spec})\n\n;;; Funkcijai ar nosaukumu `users-by-country` ir izveidota.\n;;; Izmantojam to:\n(users-by-country {:country_code \"GB\"})\n;=&gt; ({:name \"Kris\" :country_code \"GB\" ...} ...)<\/code><\/pre>\n<p><\/p>\n<blockquote><p>Iev\u0113rojot principu \"SQL atsevi\u0161\u0137i, Clojure atsevi\u0161\u0137i\", j\u016bs ieg\u016bstat:<\/p>\n<ul>\n<li>Nav sintaktisku p\u0101rsteigumu. J\u016bsu datub\u0101ze (t\u0101pat k\u0101 jebkura cita) nav 100% sader\u012bga ar SQL standartu \u2014 bet Yesql tas nav svar\u012bgi. J\u016bs nekad net\u0113r\u0113siet laiku, mekl\u0113jot funkcijas ar SQL l\u012bdz\u012bgu sintaksi. Jums nekad neb\u016bs j\u0101atgrie\u017eas pie funkcijas <em>(raw-sql \"some (\u2018funky\u2019 :: SYNTAX)\")<\/em>.<\/li>\n<li>Lab\u0101k\u0101 redaktora atbalsts. J\u016bsu redaktors jau nodro\u0161ina izcilu SQL atbalstu. Saglab\u0101jot SQL k\u0101 SQL, j\u016bs to varat vienk\u0101r\u0161i izmantot.<\/li>\n<li>Komandas sader\u012bba. J\u016bsu DBA var las\u012bt un rakst\u012bt SQL, ko j\u016bs izmantojat sav\u0101 Clojure projekt\u0101.<\/li>\n<li>Vienk\u0101r\u0161\u0101ka veiktsp\u0113jas konfigur\u0101cija. Vai nepiecie\u0161ams izveidot pl\u0101nu problem\u0101tiskam piepras\u012bjumam? Nav probl\u0113mu, ja j\u016bsu piepras\u012bjums ir parasts SQL.<\/li>\n<li>P\u0101rstr\u0101des piepras\u012bjumi. P\u0101rvietojiet \u0161os pa\u0161us SQL failus uz citiem projektiem, jo tas ir tikai vecais labs SQL \u2014 vienk\u0101r\u0161i dalieties ar to.<\/li>\n<\/ul>\n<p>\n<\/p><\/blockquote>\n<p>Manupr\u0101t, ideja ir \u013coti laba un vienlaikus \u013coti vienk\u0101r\u0161a, pateicoties kurai projekts ir ieguvis daudzus <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/krisajenkins\/yesql#other-languages\">sekot\u0101jus<\/a><\/noindex> da\u017e\u0101d\u0101s valod\u0101s. Un m\u0113s turpin\u0101sim m\u0113\u0123in\u0101t pielietot l\u012bdz\u012bgu filozofiju, atdalot SQL kodu no visa p\u0101r\u0113j\u0101 t\u0101lu aiz ORM.<\/p>\n<p><\/p>\n<h5 id=\"ide--db-menedzhery\">IDE &amp; DB-p\u0101rvaldnieki<\/h5>\n<p><\/p>\n<p>S\u0101ksim ar vienk\u0101r\u0161u ikdieni\u0161\u0137u uzdevumu. Bie\u017ei n\u0101kas mekl\u0113t k\u0101dus objektus datu b\u0101z\u0113, piem\u0113ram, atrast tabulu sh\u0113m\u0101 un izp\u0113t\u012bt t\u0101s strukt\u016bru (k\u0101das kolonnas, atsl\u0113gas, indeksi, ierobe\u017eojumi utt. tiek izmantoti). Un no jebkuras grafisk\u0101s IDE vai pat vismaz\u0101k\u0101s DB p\u0101rvaldnieka, vispirms, m\u0113s gaid\u0101m tie\u0161i \u0161\u012bs sp\u0113jas. Lai viss notiktu \u0101tri un neb\u016btu j\u0101gaida pusstunda, kam\u0113r par\u0101d\u0101s logs ar nepiecie\u0161amo inform\u0101ciju (\u012bpa\u0161i, ja savienojums ar att\u0101lo datu b\u0101zi ir l\u0113ns), un taj\u0101 pa\u0161\u0101 laik\u0101, lai sa\u0146emt\u0101 inform\u0101cija b\u016btu svaiga un aktu\u0101la, nevis novecojusi ke\u0161atmi\u0146a. Jo sare\u017e\u0123\u012bt\u0101ka un liel\u0101ka ir datu b\u0101ze un jo vair\u0101k to ir, jo gr\u016bt\u0101k to izdar\u012bt.<\/p>\n<p><\/p>\n<p>Bet parasti es ar peli prom nometu un vienk\u0101r\u0161i rakstu kodu. Pie\u0146emsim, ir nepiecie\u0161ams uzzin\u0101t, k\u0101das tabulas (un ar k\u0101d\u0101m \u012bpa\u0161\u012bb\u0101m) ir sh\u0113m\u0101 'HR'. Liel\u0101kaj\u0101 da\u013c\u0101 DB vajadz\u012bgo rezult\u0101tu var ieg\u016bt ar \u0161\u0101du vienk\u0101r\u0161u piepras\u012bjumu no information_schema:<\/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>No datu b\u0101zes uz datu b\u0101zi t\u0101du tabulu-sarakstu saturs vari\u0113 atkar\u012bb\u0101 no katra DBMS sp\u0113j\u0101m. Un, piem\u0113ram, MySQL no \u0161\u012b pa\u0161a saraksta var ieg\u016bt \u0161ai DBMS specifiskus tabulas parametrus:<\/p>\n<p><\/p>\n<pre><code class=\"sql\">select table_name\n     , storage_engine -- Izmantot\u0101 'dzin\u0113ja' ('MyISAM', 'InnoDB' utt.)\n     , row_format     -- Rindas form\u0101ts ('Fixed', 'Dynamic' utt.)\n     , ...\n  from information_schema.tables\n where schema = 'HR'<\/code><\/pre>\n<p><\/p>\n<p>Oracle neizmanto information_schema, bet tam ir <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Oracle_metadata\">Oracle metadata<\/a><\/noindex>, un lielas probl\u0113mas nerodas:<\/p>\n<p><\/p>\n<pre><code class=\"sql\">select table_name\n     , pct_free       -- Minim\u0101lais br\u012bvas vietas procents datu blok\u0101\n     , pct_used       -- Minim\u0101lais izmantot\u0101s vietas procents datu blok\u0101\n     , last_analyzed  -- P\u0113d\u0113j\u0101 statistikas apkopo\u0161anas datums\n     , ...\n  from all_tables\n where owner = 'HR'<\/code><\/pre>\n<p><\/p>\n<p>Neiz\u0146\u0113mums ir ar\u012b ClickHouse:<\/p>\n<p><\/p>\n<pre><code class=\"sql\">select name\n     , engine -- Izmantot\u0101 'dzin\u0113ja' ('MergeTree', 'Dictionary' utt.)\n     , ...\n  from system.tables\n where database = 'HR'<\/code><\/pre>\n<p><\/p>\n<p>Kaut ko l\u012bdz\u012bgu var izdar\u012bt ar\u012b Cassandra (kur ir columnfamilies viet\u0101 tabul\u0101m un keyspace'ei viet\u0101 sh\u0113m\u0101m):<\/p>\n<p><\/p>\n<pre><code class=\"sql\">select columnfamily_name\n     , compaction_strategy_class  -- Atkritumu kompakcijas strat\u0113\u0123ija\n     , gc_grace_seconds           -- Atkritumu dz\u012bves laiks\n     , ...\n  from system.schema_columnfamilies\n where keyspace_name = 'HR'<\/code><\/pre>\n<p><\/p>\n<p>Liel\u0101kajai da\u013cai citu DB ar\u012b var izdom\u0101t l\u012bdz\u012bgus vaic\u0101jumus (pat Mongo ir <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.mongodb.com\/manual\/reference\/system-collections\/#%3Cdatabase%3E.system.namespaces\">\u012bpa\u0161a sist\u0113mas kolekcija<\/a><\/noindex>, kas satur inform\u0101ciju par vis\u0101m kolekcij\u0101m sist\u0113m\u0101).<\/p>\n<p><\/p>\n<p>Protams, \u0161\u0101d\u0101 veid\u0101 var ieg\u016bt inform\u0101ciju ne tikai par tabul\u0101m, bet visp\u0101r par jebkuru objektu. Periodiski labie cilv\u0113ki dal\u0101s ar \u0161\u0101du kodu da\u017e\u0101d\u0101m datu b\u0101z\u0113m, k\u0101, piem\u0113ram, s\u0113rij\u0101 Habr rakstu 'Funkcijas datu b\u0101zu PostgreSQL dokument\u0101cijai' (<noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/post\/415575\">aiib<\/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>). Protams, visu \u0161o piepras\u012bjumu kaudzi galv\u0101 tur\u0113t un past\u0101v\u012bgi tos rakst\u012bt \u2014 tas ir 'ne p\u0101r\u0101k pat\u012bkami', t\u0101p\u0113c man\u0101 iecien\u012btaj\u0101 IDE\/redaktora ir iepriek\u0161 sagatavota virkne fragmentu bie\u017ei izmantotajiem piepras\u012bjumiem, un atliek tikai ievad\u012bt objektu nosaukumus \u0161ablon\u0101.<\/p>\n<p><\/p>\n<p>Galu gal\u0101 \u0161\u0101ds navig\u0101cijas un objektu mekl\u0113\u0161anas veids ir daudz elast\u012bg\u0101ks, ietaupa laiku, \u013cauj ieg\u016bt tie\u0161i to inform\u0101ciju un taj\u0101 form\u0101, k\u0101d\u0101 t\u0101 pa\u0161laik ir nepiecie\u0161ama (k\u0101, piem\u0113ram, aprakst\u012bts ierakst\u0101 <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/JetBrains\/blog\/342094\">'Datu eksport\u0113\u0161ana no datu b\u0101zes jebkur\u0101 form\u0101t\u0101: ko sp\u0113j IDE platform\u0101 IntelliJ'<\/a><\/noindex>).<\/p>\n<p><\/p>\n<h5 id=\"operacii-s-obektami\">Darb\u012bbas ar objektiem<\/h5>\n<p><\/p>\n<p>P\u0113c tam, kad esam atradu\u0161i un izp\u0113t\u012bju\u0161i vajadz\u012bgos objektus, ir laiks ar tiem paveikt kaut ko noder\u012bgu. Protams, ar\u012b neatraujot pirkstus no tastat\u016bras.<\/p>\n<p><\/p>\n<p>Nav nosl\u0113pums, ka vienk\u0101r\u0161a tabulas dz\u0113\u0161ana izskat\u012bsies vien\u0101di gandr\u012bz vis\u0101s DB:<\/p>\n<p><\/p>\n<pre><code class=\"sql\">drop table hr.persons<\/code><\/pre>\n<p><\/p>\n<p>Ta\u010du tabulas izveido\u0161ana ir interesant\u0101ka. Praktiski jebkura DBMS (tai skait\u0101 ar\u012b daudzas NoSQL) sp\u0113j veikt 'create table', un t\u0101s galven\u0101 da\u013ca pat nedaudz at\u0161\u0137iras (v\u0101rds, kolonu saraksts, datu tipi), tom\u0113r p\u0101r\u0113j\u0101s deta\u013cas var iev\u0113rojami at\u0161\u0137irties un ir atkar\u012bgas no konkr\u0113t\u0101s DBMS iek\u0161\u0113j\u0101s uzb\u016bves un iesp\u0113j\u0101m. Mans m\u012b\u013c\u0101kais piem\u0113rs ir Oracle dokument\u0101cij\u0101 atrodam\u0101s 'tuk\u0161\u0101s' BNF sintakse 'create table' <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/19\/sqlrf\/sql-language-reference.pdf\">aiz\u0146em 31 lappusi<\/a><\/noindex>. Citas DBMS ir ar skromm\u0101k\u0101m iesp\u0113j\u0101m, bet katra no t\u0101m ar\u012b pied\u0101v\u0101 vair\u0101kas interesantas un unik\u0101las funkcijas tabulu izveid\u0113 (<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>). Maz ticams, ka k\u0101ds grafiskais 'wizard' no k\u0101das IDE (\u012bpa\u0161i univers\u0101las) sp\u0113s piln\u012bb\u0101 segt visas \u0161\u012bs iesp\u0113jas, un, ja tas sp\u0113s, tad tas b\u016bs skats, kas nav dom\u0101ts v\u0101ju nervu cilv\u0113kiem. Taj\u0101 pa\u0161\u0101 laik\u0101 pareizi un laic\u012bgi uzrakst\u012bts operators <strong><em>create table<\/em><\/strong> at\u013caus bez piep\u016bles izmantot visas no t\u0101m, nodro\u0161inot j\u016bsu datu glab\u0101\u0161anu un piek\u013cuvi dro\u0161i, optim\u0101li un maksim\u0101li \u0113rti.<\/p>\n<p><\/p>\n<p>T\u0101pat daudz\u0101s DBMS ir savi specifiskie objektu tipi, kuri tr\u016bkst cit\u0101s DBMS. Turkl\u0101t m\u0113s varam veikt oper\u0101cijas ne tikai ar datu b\u0101zes objektiem, bet ar\u012b ar pa\u0161u DBMS, piem\u0113ram, 'nogalin\u0101t' procesu, atbr\u012bvot k\u0101du atmi\u0146as zonu, iesl\u0113gt izseko\u0161anu, p\u0101riet uz 'read only' re\u017e\u012bmu un daudz ko citu.<\/p>\n<p><\/p>\n<h5 id=\"a-teper-nemnogo-porisuem\">Tagad nedaudz z\u012bm\u0113sim<\/h5>\n<p><\/p>\n<p>Viens no visizplat\u012bt\u0101kajiem uzdevumiem ir izveidot diagrammu ar datu b\u0101zes objektiem, uz skaistas bildes redz\u0113t objektus un attiec\u012bbas starp tiem. To sp\u0113j praktiski jebkura grafisk\u0101 IDE, atsevi\u0161\u0137i 'command line' r\u012bki, specializ\u0113ti grafiskie r\u012bki un model\u0113t\u0101ji. Tie jums z\u012bm\u0113s 'k\u0101 prot', un nedaudz ietekm\u0113t \u0161o procesu var tikai ar da\u017eiem parametriem konfigur\u0101cijas fail\u0101 vai \u0137eks\u012b\u0161iem saskarn\u0113.<\/p>\n<p><\/p>\n<p>Tom\u0113r \u0161o probl\u0113mu var atrisin\u0101t daudz vienk\u0101r\u0161\u0101k, elast\u012bg\u0101k un eleganti, un, protams, ar koda pal\u012bdz\u012bbu. \u013boti da\u017e\u0101du sare\u017e\u0123\u012bt\u012bbu diagrammu izveidei mums ir vair\u0101kas specializ\u0113tas iez\u012bm\u0113\u0161anas valodas (DOT, GraphML utt.), un identifikatori tiek las\u012bti kop\u0101 ar milz\u012bgu lietojumprogrammu skaitu (GraphViz, PlantUML, Mermaid), kas sp\u0113j interpret\u0113t \u0161\u0101das instrukcijas un vizualiz\u0113t da\u017e\u0101dos form\u0101tos. Bet inform\u0101ciju par objektiem un to attiec\u012bb\u0101m m\u0113s jau zin\u0101m, k\u0101 ieg\u016bt.<\/p>\n<p><\/p>\n<p>Sniedzam nelielu piem\u0113ru tam, k\u0101 tas var\u0113tu izskat\u012bties, izmantojot PlantUML un <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/postgrespro\/blog\/316428\/\">demonstr\u0101ciju datu b\u0101zi PostgreSQL<\/a><\/noindex> (pa kreisi SQL vaic\u0101jums, kas \u0123ener\u0113s nepiecie\u0161amo instrukciju PlantUML, bet pa labi ir rezult\u0101ts):<\/p>\n<p>\n<img decoding=\"async\" alt=\"\u201eDatu b\u0101ze k\u0101 koda\u201d pieredze\" 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>Un, ja nedaudz piestr\u0101d\u0101, tad, izmantojot <noindex><a rel=\"nofollow\" href=\"https:\/\/gist.github.com\/QuantumGhost\/0955a45383a0b6c0bc24f9654b3cb561\">ER veidni PlantUML<\/a><\/noindex> var ieg\u016bt kaut ko, kas stipri l\u012bdzin\u0101s \u012bstai ER diagrammai:<\/p>\n<p><\/p>\n<p>                        <b class=\"spoiler_title\">SQL vaic\u0101jums b\u016bs nedaudz sare\u017e\u0123\u012bt\u0101ks<\/b><\/p>\n<pre><code class=\"sql\">-- Galvene\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-- Tabulas\nselect format(&#039;Table(%s, &quot;%s n inform\u0101cija par %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-- Attiec\u012bbas starp tabul\u0101m\nselect distinct ccu.table_name || &#039; &quot;1&quot; --&amp;gt; &quot;0..N&quot; &#039; || tc.table_name || format(&#039; : &quot;A %s var b\u016bt daudz %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-- Apak&scaron;galvene\nselect &#039;@enduml&#039;<\/code><\/pre>\n<p>\n<img decoding=\"async\" alt=\"\u201eDatu b\u0101ze k\u0101 koda\u201d pieredze\" src=\"\/wp-content\/uploads\/2020\/06\/bd45420a4fd1bdfcf20cbe74a0638c7b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Ja uzman\u012bgi paskat\u0101s, tad daudzi vizualiz\u0101cijas r\u012bki zem v\u0101ka tie\u0161i t\u0101pat izmanto l\u012bdz\u012bgus vaic\u0101jumus. Tom\u0113r \u0161ie vaic\u0101jumi parasti ir dzi\u013ci <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/pgmodeler\/pgmodeler\/blob\/9c615c0b0871df3cd649983ce61e802b0ff0137b\/schemas\/catalog\/table.sch\">'iene\u0161anas' pa\u0161\u0101 lietojumprogramm\u0101 un t\u0101s ir gr\u016bti saprotamas<\/a><\/noindex>, nerun\u0101jot jau par to, lai tos main\u012btu.<\/p>\n<p><\/p>\n<h5 id=\"metriki-i-monitoring\">Metricas un uzraudz\u012bba<\/h5>\n<p><\/p>\n<p>P\u0101riesim pie tradicion\u0101li sare\u017e\u0123\u012bt\u0101s t\u0113mas \u2014 datu b\u0101zu veiktsp\u0113jas uzraudz\u012bba. Atcer\u0113\u0161os nelielu \u012bstu st\u0101stu, ko man st\u0101st\u012bja \"viens mans draugs\". Vien\u0101 projekt\u0101 dz\u012bvoja k\u0101ds varens DBA, un maz kas no izstr\u0101d\u0101t\u0101jiem bija paz\u012bstams ar vi\u0146u person\u012bgi, pat pamaz\u0101m redz\u0113ja vi\u0146u ac\u012bs (neskatoties uz to, ka vi\u0146\u0161, p\u0113c baum\u0101m, str\u0101d\u0101ja kaut kur blakus korpus\u0101).  \u201cX\u201d stund\u0101, kad liel\u0101 mazumtirdzniec\u012bbas sist\u0113ma uzs\u0101ka v\u0113l vienu reizi \u201csliktu pa\u0161saj\u016btu\u201d, vi\u0146\u0161 klusi s\u016bt\u012bja ekr\u0101nuz\u0146\u0113mumus no Oracle Enterprise Manager, kur vi\u0146\u0161 r\u016bp\u012bgi izc\u0113la kritisk\u0101s vietas ar sarkanu mar\u0137ieri \u201csapratnei\u201d (tas, maigi sakot, maz pal\u012bdz\u0113ja). Un t\u0101d\u0113j\u0101di p\u0113c \u0161\u012bs \u201cfotokartes\u201d n\u0101c\u0101s \u0101rst\u0113t. Taj\u0101 pa\u0161\u0101 laik\u0101 neviens nevar\u0113ja piek\u013c\u016bt d\u0101rgajam (abos noz\u012bm\u0113s) Enterprise Manager, jo sist\u0113ma ir sare\u017e\u0123\u012bta un d\u0101rga, p\u0113k\u0161\u0146i \u201cizstr\u0101d\u0101t\u0101ji kaut ko p\u0101rtrauc un viss sal\u016bzt\u201d. T\u0101p\u0113c izstr\u0101d\u0101t\u0101ji \u201cemp\u012brisk\u0101\u201d ce\u013c\u0101 atrada vietu un iemeslu aizkavei un izlaida labojumu. Ja uz DBA nopietno v\u0113stuli tuv\u0101kaj\u0101 laik\u0101 neatn\u0101ca atbildes v\u0113stule, visi ar atvieglojumu izelpoja un atgriez\u0101s pie saviem eso\u0161ajiem uzdevumiem (l\u012bdz jaunai v\u0113stulei).<\/p>\n<p><\/p>\n<p>Bet uzraudz\u012bbas process var izskat\u012bties daudz priec\u012bg\u0101ks un draudz\u012bg\u0101ks, un, kas ir svar\u012bg\u0101kais \u2014 pieejams un caursp\u012bd\u012bgs visiem. Vismaz pamata da\u013ca, k\u0101 papildin\u0101jums galvenaj\u0101m uzraudz\u012bbas sist\u0113m\u0101m (kas noteikti ir noder\u012bgas un daudzos gad\u012bjumos neaizst\u0101jamas). Jebkura DBMS br\u012bvi un absol\u016bti bez maksas ir gatava dal\u012bties ar inform\u0101ciju par savu pa\u0161reiz\u0113jo st\u0101vokli un veiktsp\u0113ju. Pat taj\u0101 pa\u0161\u0101 \u201casi\u0146u\u201d Oracle DB praktiski jebkuru inform\u0101ciju par veiktsp\u0113ju var ieg\u016bt no sist\u0113miskaj\u0101m skatiem, s\u0101kot no procesiem un sesij\u0101m un beidzot ar buferu ke\u0161a st\u0101vokli (piem\u0113ram, <noindex><a rel=\"nofollow\" href=\"https:\/\/oracle-base.com\/dba\/scripts\">DBA skripti<\/a><\/noindex>, sada\u013ca \u201cUzraudz\u012bba\u201d). Postgresql ar\u012b ir visa kaudze sist\u0113misku skatu par <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/static\/monitoring-stats.html\">datu b\u0101zu uzraudz\u012bbai<\/a><\/noindex>, \u012bpa\u0161i t\u0101di, kas ir neaizvietojami ikdienas dz\u012bv\u0113 jebkuram DBA, piem\u0113ram, <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 \u0161im nol\u016bkam ir pat atsevi\u0161\u0137a sh\u0113ma <noindex><a rel=\"nofollow\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/performance-schema-table-descriptions.html\">performance_schema<\/a><\/noindex>. Bet Mongo ieb\u016bv\u0113tais <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.mongodb.com\/manual\/tutorial\/manage-the-database-profiler\/\">profileris<\/a><\/noindex> apkopo veiktsp\u0113jas datus sist\u0113mas kolekcij\u0101 <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>T\u0101tad, apg\u016bstot k\u0101du metrikas apkopot\u0101ju (Telegraf, Metricbeat, Collectd), kas sp\u0113j izpild\u012bt piel\u0101gotus sql piepras\u012bjumus, metrikas glab\u0101tuvi (InfluxDB, Elasticsearch, Timescaledb) un vizualizatoru (Grafana, Kibana), var izveidot pietiekami vieglu un elast\u012bgu uzraudz\u012bbas sist\u0113mu, kas cie\u0161i integr\u0113ta ar cit\u0101m visp\u0101r\u0113j\u0101m metrik\u0101m (sa\u0146emt\u0101m, piem\u0113ram, no lietojumprogrammu servera, no oper\u0113t\u0101jsist\u0113mas utt.). K\u0101, piem\u0113ram, tas ir izdar\u012bts pgwatch2, kur tiek izmantota saikne InfluxDB + Grafana un komplekts piepras\u012bjumu uz sist\u0113miskajiem skatiem, kuriem var pievienot ar\u012b piel\u0101gotus piepras\u012bjumus. <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/cybertec-postgresql\/pgwatch2#adding-metrics\">pievienot piel\u0101gotus piepras\u012bjumus<\/a><\/noindex>.<\/p>\n<p><\/p>\n<h2 id=\"itogo\">Kop\u0113j\u0101 summa<\/h2>\n<p><\/p>\n<p>Un tas ir tikai aptuvens saraksts no t\u0101, ko var izdar\u012bt ar m\u016bsu datu b\u0101zi, izmantojot parasto SQL kodu. Esmu p\u0101rliecin\u0101ts, ka var atrast v\u0113l daudz pielietojumu, rakstiet koment\u0101ros. Par to, k\u0101 (un galvenais, k\u0101d\u0113\u013c) to visu automatiz\u0113t un iek\u013caut sav\u0101 CI\/CD pipeline, m\u0113s run\u0101sim n\u0101kamreiz.<\/p>\n<p>Avots: <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 5.0.4 - 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?\" \/>\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\/lv\/blog\/administrirovanie\/database-as-sode-experience\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"lv_LV\" \/>\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?\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/lv\/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\u00abDatabase as Code\u00bb pieredze | ProHoster","description":"SQL, kas var b\u016bt vienk\u0101r\u0161\u0101ks?","canonical_url":"https:\/\/prohoster.info\/lv\/blog\/administrirovanie\/database-as-sode-experience","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"lv_LV","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?","og:url":"https:\/\/prohoster.info\/lv\/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","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/posts\/83649","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/comments?post=83649"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/posts\/83649\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/media\/83650"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/media?parent=83649"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/categories?post=83649"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/lv\/wp-json\/wp\/v2\/tags?post=83649"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}