{"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\/cs\/blog\/administrirovanie\/database-as-sode-experience","title":{"rendered":"Zku\u0161enost \u201eDatabase as Code\u201c","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Zku\u0161enost \u201eDatabase as Code\u201c\" src=\"\/wp-content\/uploads\/2020\/06\/a1ac23deeded97559fbe787ed09184a5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>SQL, co m\u016f\u017ee b\u00fdt jednodu\u0161\u0161\u00ed? Ka\u017ed\u00fd z n\u00e1s m\u016f\u017ee napsat jednoduch\u00fd dotaz \u2013 zad\u00e1me <strong><em>select<\/em><\/strong>, uvedeme pot\u0159ebn\u00e9 sloupce, pak <strong><em>from<\/em><\/strong>, jm\u00e9no tabulky, trochu podm\u00ednek v <strong><em>where<\/em><\/strong> a je to \u2013 u\u017eite\u010dn\u00e1 data m\u00e1me v kapse, a to (t\u00e9m\u011b\u0159) nez\u00e1visle na tom, jak\u00e1 S\u0158BD je pr\u00e1v\u011b pod kapotou (nebo to mo\u017en\u00e1 nen\u00ed <noindex><a rel=\"nofollow\" href=\"https:\/\/osquery.io\/\">S\u0158BD v\u016fbec<\/a><\/noindex>). Jako v\u00fdsledek lze na pr\u00e1ci s t\u00e9m\u011b\u0159 jak\u00fdmkoli zdrojem dat (rela\u010dn\u00edm i jin\u00fdm) pohl\u00ed\u017eet jako na b\u011b\u017en\u00fd k\u00f3d (se v\u0161emi d\u016fsledky \u2014 verzov\u00e1n\u00ed, revize k\u00f3du, statick\u00e1 anal\u00fdza, automatizovan\u00e9 testy a tak d\u00e1le). To se t\u00fdk\u00e1 nejen samotn\u00fdch dat, sch\u00e9mat a migrac\u00ed, ale v\u016fbec cel\u00e9 \u010dinnosti \u00falo\u017ei\u0161t\u011b. V tomto \u010dl\u00e1nku se pod\u00edv\u00e1me na ka\u017edodenn\u00ed \u00fakoly a probl\u00e9my p\u0159i pr\u00e1ci s r\u016fzn\u00fdmi datab\u00e1zemi z pohledu \u201edatab\u00e1ze jako k\u00f3d\u201c.<\/p>\n<p><\/p>\n<p>A za\u010dneme hned s <noindex><a rel=\"nofollow\" href=\"https:\/\/www.yegor256.com\/2014\/12\/01\/orm-offensive-anti-pattern.html\">ORM<\/a><\/noindex>. Prvn\u00ed bitvy typu \u201eSQL vs ORM\u201c byly zaznamen\u00e1ny ji\u017e v <noindex><a rel=\"nofollow\" href=\"https:\/\/www.sql.ru\/forum\/904343\/orm-vs-sql\">p\u0159edpetrsk\u00e9 Rusko<\/a><\/noindex>.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<h5 id=\"obektno-relyacionnyy-maping\">Objektov\u011b-rela\u010dn\u00ed mapov\u00e1n\u00ed<\/h5>\n<p><\/p>\n<p>Zast\u00e1nci ORM tradi\u010dn\u011b oce\u0148uj\u00ed rychlost a jednoduchost v\u00fdvoje, nez\u00e1vislost na S\u0158BD a \u010distotu k\u00f3du. Pro mnoh\u00e9 z n\u00e1s k\u00f3d pr\u00e1ce s DB (a \u010dasto i samotn\u00e1 DB)<\/p>\n<p><\/p>\n<p>                        <b class=\"spoiler_title\">obvykle vypad\u00e1 p\u0159ibli\u017en\u011b takto\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>Model je obohacen chytr\u00fdmi anotacemi, a n\u011bkde v z\u00e1kulis\u00ed state\u010dn\u00e9 ORM generuje a vykon\u00e1v\u00e1 tuny n\u011bjak\u00e9ho SQL k\u00f3du. Mimochodem, v\u00fdvoj\u00e1\u0159i se sna\u017e\u00ed za ka\u017edou cenu odd\u011blit od sv\u00e9 DB kilometry abstrakc\u00ed, co\u017e sv\u011bd\u010d\u00ed o jist\u00e9 <noindex><a rel=\"nofollow\" href=\"https:\/\/www.sql.ru\/forum\/1303231\/prichiny-nenavisti-k-yazyku-sql\">\"SQL nen\u00e1visti\"<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Na druh\u00e9 stran\u011b barik\u00e1dy zast\u00e1nci \u010dist\u00e9ho \"handmade\"-SQL zd\u016fraz\u0148uj\u00ed mo\u017enost vyt\u011b\u017eit maximum ze sv\u00e9 DB bez dal\u0161\u00edch vrstev a abstrakc\u00ed. V d\u016fsledku toho vznikaj\u00ed \"data-centric\" projekty, kde se o datab\u00e1ze staraj\u00ed speci\u00e1ln\u011b vy\u0161kolen\u00ed lid\u00e9 (ti, kte\u0159\u00ed se naz\u00fdvaj\u00ed \"datab\u00e1rist\u00e9\", tak\u00e9 \"datab\u00e1z\u00e1ci\", tak\u00e9 \"b\u00e1zov\u00ed pracovn\u00edci\" atd.), a v\u00fdvoj\u00e1\u0159\u016fm z\u016fst\u00e1v\u00e1 pouze \"tahat\" hotov\u00e9 pohledy a ulo\u017een\u00e9 procedury, ani\u017e by se zab\u00fdvali detaily.<\/p>\n<p><\/p>\n<p>A co kdybychom vzali to nejlep\u0161\u00ed z obou sv\u011bt\u016f? Jak je to ud\u011bl\u00e1no ve skv\u011bl\u00e9m n\u00e1stroji s povzbudiv\u00fdm n\u00e1zvem <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/krisajenkins\/yesql\">Yesql<\/a><\/noindex>. Uvedu p\u00e1r \u0159\u00e1dk\u016f z obecn\u00e9 koncepce ve sv\u00e9m voln\u00e9m p\u0159ekladu, a podrobn\u011bji se s n\u00ed m\u016f\u017eete sezn\u00e1mit <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/krisajenkins\/yesql#rationale\">zde<\/a><\/noindex>.<\/p>\n<p><\/p>\n<blockquote><p>Clojure je skv\u011bl\u00fd jazyk pro vytv\u00e1\u0159en\u00ed DSL, ale SQL u\u017e samo o sob\u011b je \u00fa\u017easn\u00fd DSL, a nepot\u0159ebujeme dal\u0161\u00ed. S-v\u00fdrazy jsou n\u00e1dhern\u00e9, ale zde nic nov\u00e9ho do hry nevn\u00e1\u0161ej\u00ed. Nakonec dost\u00e1v\u00e1me z\u00e1vorky jen pro samotn\u00e9 z\u00e1vorky. Neshodujete se? Pak po\u010dkejte, a\u017e abstrahce nad datab\u00e1z\u00ed za\u010dne selh\u00e1vat, a vy za\u010dne bojovat s funkc\u00ed <em>(raw-sql)<\/em><\/p>\n<p>A co te\u010f? Poj\u010fme nechat SQL jako oby\u010dejn\u00e9 SQL \u2014 jeden soubor na jeden dotaz:<\/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 a pot\u00e9 si tento soubor p\u0159e\u010dt\u011bte a p\u0159eve\u010fte ho na b\u011b\u017enou funkci v Clojure:<\/p><\/blockquote>\n<p><\/p>\n<pre><code class=\"lisp\">(defqueries \"some\/where\/users_by_country.sql\"\n   {:connection db-spec})\n\n;;; Byla vytvo\u0159ena funkce s n\u00e1zvem `users-by-country`.\n;;; Pou\u017eijme ji:\n(users-by-country {:country_code \"GB\"})\n;=&gt; ({:name \"Kris\" :country_code \"GB\" ...} ...)<\/code><\/pre>\n<p><\/p>\n<blockquote><p>Zachov\u00e1n\u00edm principu \"SQL zvl\u00e1\u0161\u0165, Clojure zvl\u00e1\u0161\u0165\" z\u00edsk\u00e1te:<\/p>\n<ul>\n<li>\u017d\u00e1dn\u00e9 syntaktick\u00e9 p\u0159ekvapen\u00ed. Va\u0161e datab\u00e1ze (stejn\u011b jako ka\u017ed\u00e1 jin\u00e1) nen\u00ed 100% v souladu se standardem SQL \u2014 ale pro Yesql to nen\u00ed d\u016fle\u017eit\u00e9. Nikdy nebudete ztr\u00e1cet \u010das hled\u00e1n\u00edm funkc\u00ed s ekvivalentn\u00ed syntaxi SQL. Nikdy nebudete muset vr\u00e1tit se k funkci <em>(raw-sql \"some ('funky' :: SYNTAX)\")<\/em>.<\/li>\n<li>Nejlep\u0161\u00ed podpora editoru. V\u00e1\u0161 editor ji\u017e m\u00e1 skv\u011blou podporu SQL. Pokud uchov\u00e1te SQL jako SQL, m\u016f\u017eete ho prost\u011b pou\u017e\u00edt.<\/li>\n<li>Kompatibilita pro t\u00fdmy. Va\u0161i DBA mohou \u010d\u00edst a ps\u00e1t SQL, kter\u00e9 pou\u017e\u00edv\u00e1te ve sv\u00e9m projektu Clojure.<\/li>\n<li>Jednodu\u0161\u0161\u00ed nastaven\u00ed v\u00fdkonu. Pot\u0159ebujete vytvo\u0159it pl\u00e1n pro problematick\u00fd dotaz? To nen\u00ed probl\u00e9m, kdy\u017e je v\u00e1\u0161 dotaz b\u011b\u017en\u00e9 SQL.<\/li>\n<li>Op\u011btovn\u00e9 pou\u017eit\u00ed dotaz\u016f. P\u0159et\u00e1hn\u011bte tyto stejn\u00e9 SQL soubory do jin\u00fdch projekt\u016f, proto\u017ee je to prost\u011b star\u00fd dobr\u00fd SQL \u2014 sta\u010d\u00ed je sd\u00edlet.<\/li>\n<\/ul>\n<p>\n<\/p><\/blockquote>\n<p>Podle m\u011b je my\u0161lenka velmi cool a z\u00e1rove\u0148 velmi jednoduch\u00e1, co\u017e zp\u016fsobilo, \u017ee projekt z\u00edskal mnoho <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/krisajenkins\/yesql#other-languages\">n\u00e1sledovn\u00edk\u016f<\/a><\/noindex> v nejr\u016fzn\u011bj\u0161\u00edch jazyc\u00edch. A my se d\u00e1le pokus\u00edme uplatnit podobnou filozofii odd\u011blov\u00e1n\u00ed SQL k\u00f3du od v\u0161eho ostatn\u00edho daleko za hranice ORM.<\/p>\n<p><\/p>\n<h5 id=\"ide--db-menedzhery\">IDE &amp; DB mana\u017ee\u0159i<\/h5>\n<p><\/p>\n<p>Za\u010dneme s jednoduch\u00fdm ka\u017edodenn\u00edm \u00fakolem. \u010casto mus\u00edme hledat n\u011bjak\u00e9 objekty v datab\u00e1zi, nap\u0159\u00edklad naj\u00edt tabulku ve sch\u00e9matu a prozkoumat jej\u00ed strukturu (jak\u00e9 sloupce, kl\u00ed\u010de, indexy, omezen\u00ed a dal\u0161\u00ed se pou\u017e\u00edvaj\u00ed). A od jak\u00e9koliv grafick\u00e9 IDE nebo alespo\u0148 n\u011bjak\u00e9ho DB-managera o\u010dek\u00e1v\u00e1me p\u0159edev\u0161\u00edm tyto schopnosti. Aby to bylo rychl\u00e9 a nemuseli jsme \u010dekat p\u016fl hodiny, ne\u017e se zobraz\u00ed okno s pot\u0159ebn\u00fdmi informacemi (zejm\u00e9na p\u0159i pomal\u00e9m p\u0159ipojen\u00ed k vzd\u00e1len\u00e9 datab\u00e1zi), a abychom z\u00e1rove\u0148 dost\u00e1vali \u010derstv\u00e9 a aktu\u00e1ln\u00ed informace, a ne n\u011bco, co je ji\u017e ve vyrovn\u00e1vac\u00ed pam\u011bti. \u010c\u00edm slo\u017eit\u011bj\u0161\u00ed a v\u011bt\u0161\u00ed je datab\u00e1ze a \u010d\u00edm v\u00edc jich je, t\u00edm t\u011b\u017e\u0161\u00ed je to ud\u011blat.<\/p>\n<p><\/p>\n<p>Obvykle ale my\u0161 prost\u011b odlo\u017e\u00edm a nap\u00ed\u0161u k\u00f3d. \u0158ekn\u011bme, \u017ee je pot\u0159eba zjistit, jak\u00e9 tabulky (a s jak\u00fdmi vlastnostmi) se nach\u00e1zej\u00ed ve sch\u00e9matu \"HR\". Ve v\u011bt\u0161in\u011b DBMS lze \u017e\u00e1dan\u00e9ho v\u00fdsledku dos\u00e1hnout t\u00edmto prost\u00fdm dotazem z 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>Obsah t\u011bchto tabulek referenc\u00ed se od datab\u00e1ze k datab\u00e1zi li\u0161\u00ed v z\u00e1vislosti na schopnostech ka\u017ed\u00e9ho DBMS. Nap\u0159\u00edklad pro MySQL lze z t\u00e9to referen\u010dn\u00ed tabulky z\u00edskat specifick\u00e9 pro tuto datab\u00e1zi parametry tabulky:<\/p>\n<p><\/p>\n<pre><code class=\"sql\">select table_name\n     , storage_engine -- Pou\u017e\u00edvan\u00fd \"motor\" (\"MyISAM\", \"InnoDB\" atd.)\n     , row_format     -- Form\u00e1t \u0159\u00e1dku (\"Fixed\", \"Dynamic\" atd.)\n     , ...\n  from information_schema.tables\n where schema = 'HR'<\/code><\/pre>\n<p><\/p>\n<p>Oracle nezn\u00e1 information_schema, ale m\u00e1 <noindex><a rel=\"nofollow\" href=\"https:\/\/en.wikipedia.org\/wiki\/Oracle_metadata\">Oracle metadata<\/a><\/noindex>, a nast\u00e1vaj\u00ed tak velk\u00e9 probl\u00e9my:<\/p>\n<p><\/p>\n<pre><code class=\"sql\">select table_name\n     , pct_free       -- Minim\u00e1ln\u00ed voln\u00e9 m\u00edsto v bloku dat (%)\n     , pct_used       -- Minim\u00e1ln\u00ed pou\u017e\u00edvan\u00e9 m\u00edsto v bloku dat (%)\n     , last_analyzed  -- Datum posledn\u00edho z\u00edsk\u00e1n\u00ed statistik\n     , ...\n  from all_tables\n where owner = 'HR'<\/code><\/pre>\n<p><\/p>\n<p>Nejste v\u00fdjimkou ani ClickHouse:<\/p>\n<p><\/p>\n<pre><code class=\"sql\">select name\n     , engine -- Pou\u017e\u00edvan\u00fd \"motor\" (\"MergeTree\", \"Dictionary\" atd.)\n     , ...\n  from system.tables\n where database = 'HR'<\/code><\/pre>\n<p><\/p>\n<p>N\u011bco podobn\u00e9ho lze ud\u011blat i v Cassand\u0159e (kde jsou columnfamilies m\u00edsto tabulek a keyspace m\u00edsto sch\u00e9mat):<\/p>\n<p><\/p>\n<pre><code class=\"sql\">select columnfamily_name\n     , compaction_strategy_class  -- Strategie pro \u00fadr\u017ebu dat\n     , gc_grace_seconds           -- Doba \u017eivota nepot\u0159ebn\u00fdch dat\n     , ...\n  from system.schema_columnfamilies\n where keyspace_name = 'HR'<\/code><\/pre>\n<p><\/p>\n<p>Pro v\u011bt\u0161inu ostatn\u00edch datab\u00e1z\u00ed lze vymyslet podobn\u00e9 dotazy (i v Mongo existuje <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.mongodb.com\/manual\/reference\/system-collections\/#%3Cdatabase%3E.system.namespaces\">speci\u00e1ln\u00ed syst\u00e9mov\u00e1 kolekce<\/a><\/noindex>, kter\u00e1 obsahuje informace o v\u0161ech kolekc\u00edch v syst\u00e9mu).<\/p>\n<p><\/p>\n<p>Samoz\u0159ejm\u011b, t\u00edmto zp\u016fsobem lze z\u00edskat informace nejen o tabulk\u00e1ch, ale v\u016fbec o jak\u00e9mkoliv objektu. Pravideln\u011b laskav\u00ed lid\u00e9 sd\u00edl\u00ed takov\u00fd k\u00f3d pro r\u016fzn\u00e9 datab\u00e1ze, nap\u0159\u00edklad v s\u00e9rii \u010dl\u00e1nk\u016f na habru \"Funkce pro dokumentaci datab\u00e1z\u00ed PostgreSQL\" (<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>). Samoz\u0159ejm\u011b, m\u00edt v\u0161echny tyto dotazy v hlav\u011b a neust\u00e1le je ps\u00e1t je \"takov\u00e1 slast\", tak\u017ee v m\u00e9 obl\u00edben\u00e9 IDE\/editoru m\u00e1m p\u0159edem p\u0159ipravenou sadu snippetu pro \u010dasto pou\u017e\u00edvan\u00e9 dotazy, a sta\u010d\u00ed jen vyplnit jm\u00e9na objekt\u016f do \u0161ablony.<\/p>\n<p><\/p>\n<p>V\u00fdsledkem je, \u017ee takov\u00fd zp\u016fsob navigace a vyhled\u00e1v\u00e1n\u00ed objekt\u016f je mnohem flexibiln\u011bj\u0161\u00ed, \u0161et\u0159\u00ed spoustu \u010dasu a umo\u017e\u0148uje z\u00edskat p\u0159esn\u011b ty informace a v tom form\u00e1tu, jak\u00fd je pr\u00e1v\u011b pot\u0159eba (jak je pops\u00e1no v p\u0159\u00edsp\u011bvku <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/company\/JetBrains\/blog\/342094\">\"Export dat z datab\u00e1ze v jak\u00e9mkoli form\u00e1tu: co um\u00ed IDE na platform\u011b IntelliJ\"<\/a><\/noindex>).<\/p>\n<p><\/p>\n<h5 id=\"operacii-s-obektami\">Operace s objekty<\/h5>\n<p><\/p>\n<p>Po tom, co jsme na\u0161li a prozkoumali pot\u0159ebn\u00e9 objekty, je \u010das s nimi ud\u011blat n\u011bco u\u017eite\u010dn\u00e9ho. Samoz\u0159ejm\u011b, tak\u00e9 bez odtr\u017een\u00ed prst\u016f od kl\u00e1vesnice.<\/p>\n<p><\/p>\n<p>Nen\u00ed tajemstv\u00edm, \u017ee jednoduch\u00e9 odstran\u011bn\u00ed tabulky vypad\u00e1 t\u00e9m\u011b\u0159 stejn\u011b ve v\u0161ech datab\u00e1z\u00edch:<\/p>\n<p><\/p>\n<pre><code class=\"sql\">drop table hr.persons<\/code><\/pre>\n<p><\/p>\n<p>S vytvo\u0159en\u00edm tabulky je to u\u017e zaj\u00edmav\u011bj\u0161\u00ed. Prakticky ka\u017ed\u00e1 DBMS (v\u010detn\u011b mnoha NoSQL) um\u00ed v n\u011bjak\u00e9 podob\u011b \"create table\", a hlavn\u00ed \u010d\u00e1st se ani p\u0159\u00edli\u0161 neli\u0161\u00ed (n\u00e1zev, seznam sloupc\u016f, typy dat), ale ostatn\u00ed detaily se mohou z\u00e1sadn\u011b li\u0161it a z\u00e1vis\u00ed na intern\u00ed struktu\u0159e a mo\u017enostech konkr\u00e9tn\u00ed DBMS. M\u016fj obl\u00edben\u00fd p\u0159\u00edklad \u2013 v dokumentaci Oracle jsou pouze \"hol\u00e9\" BNF pro syntaxi \"create table\". <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/19\/sqlrf\/sql-language-reference.pdf\">zab\u00edraj\u00ed 31 str\u00e1nek<\/a><\/noindex>. Jin\u00e1 S\u0158BD maj\u00ed skromn\u011bj\u0161\u00ed mo\u017enosti, ale ka\u017ed\u00e1 z nich tak\u00e9 nab\u00edz\u00ed spoustu zaj\u00edmav\u00fdch a jedine\u010dn\u00fdch funkc\u00ed pro vytv\u00e1\u0159en\u00ed tabulek (<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>). Sotva n\u011bjak\u00fd grafick\u00fd \"wizard\" z dal\u0161\u00ed IDE (zejm\u00e9na univerz\u00e1ln\u00ed) dok\u00e1\u017ee pln\u011b pokr\u00fdt v\u0161echny tyto schopnosti, a pokud ano, bude to pohled pro siln\u00e9 nervy. Z\u00e1rove\u0148 spr\u00e1vn\u011b a v\u010das napsan\u00fd p\u0159\u00edkaz <strong><em>create table<\/em><\/strong> umo\u017en\u00ed bez pot\u00ed\u017e\u00ed vyu\u017e\u00edt v\u0161echny z nich, u\u010dinit ukl\u00e1d\u00e1n\u00ed a p\u0159\u00edstup k va\u0161im dat\u016fm spolehliv\u00fdmi, optim\u00e1ln\u00edmi a maxim\u00e1ln\u011b pohodln\u00fdmi.<\/p>\n<p><\/p>\n<p>Tak\u00e9 v mnoha DBMS existuj\u00ed sv\u00e9 specifick\u00e9 typy objekt\u016f, kter\u00e9 v jin\u00fdch DBMS chyb\u00ed. A m\u016f\u017eeme prov\u00e1d\u011bt operace nejen nad objekty DB, ale tak\u00e9 nad samotnou DBMS, nap\u0159\u00edklad \"zab\u00edt\" proces, osvobodit n\u011bjakou oblast pam\u011bti, zapnout sledov\u00e1n\u00ed, p\u0159epnout do re\u017eimu \"read only\" a mnoho dal\u0161\u00edho.<\/p>\n<p><\/p>\n<h5 id=\"a-teper-nemnogo-porisuem\">A te\u010f si trochu nakresl\u00edme.<\/h5>\n<p><\/p>\n<p>Jedn\u00edm z nejb\u011b\u017en\u011bj\u0161\u00edch \u00fakol\u016f je vytvo\u0159it diagram s objekty DB, na hezk\u00e9m obr\u00e1zku vid\u011bt objekty a vztahy mezi nimi. To zvl\u00e1dne prakticky ka\u017ed\u00e1 grafick\u00e1 IDE, jednotliv\u00e9 \"command line\" utilitky, specializovan\u00e9 grafick\u00e9 n\u00e1stroje a modela\u0159i. Kter\u00e9 v\u00e1m n\u011bco nakresl\u00ed \"jak um\u00ed\", a na tento proces lze m\u00edrn\u011b zap\u016fsobit pouze n\u011bkolika parametry v konfigura\u010dn\u00edm souboru nebo za\u0161krt\u00e1vac\u00edmi pol\u00ed\u010dky v rozhran\u00ed.<\/p>\n<p><\/p>\n<p>Ale tento probl\u00e9m lze vy\u0159e\u0161it mnohem jednodu\u0161eji, flexibiln\u011bji a elegantn\u011bji, a samoz\u0159ejm\u011b pomoc\u00ed k\u00f3du. Pro vytv\u00e1\u0159en\u00ed diagram\u016f jak\u00e9koli slo\u017eitosti m\u00e1me hned n\u011bkolik specializovan\u00fdch zna\u010dkovac\u00edch jazyk\u016f (DOT, GraphML atd.), a k nim celou \u0159adu aplikac\u00ed (GraphViz, PlantUML, Mermaid), kter\u00e9 um\u00ed \u010d\u00edst takov\u00e9 instrukce a vizualizovat v nejr\u016fzn\u011bj\u0161\u00edch form\u00e1tech. No a informace o objektech a vazb\u00e1ch mezi nimi u\u017e v\u00edme, jak z\u00edskat.<\/p>\n<p><\/p>\n<p>Uvedeme mal\u00fd p\u0159\u00edklad toho, jak by to mohlo vypadat, s pou\u017eit\u00edm PlantUML a <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/postgrespro\/blog\/316428\/\">demonstra\u010dn\u00ed datab\u00e1ze pro PostgreSQL.<\/a><\/noindex> (nalevo SQL dotaz, kter\u00fd vygeneruje pot\u0159ebnou instrukci pro PlantUML, a napravo v\u00fdsledek):<\/p>\n<p>\n<img decoding=\"async\" alt=\"Zku\u0161enost \u201eDatabase as Code\u201c\" 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>A pokud se trochu sna\u017e\u00edte, m\u016f\u017eete na z\u00e1klad\u011b <noindex><a rel=\"nofollow\" href=\"https:\/\/gist.github.com\/QuantumGhost\/0955a45383a0b6c0bc24f9654b3cb561\">ER \u0161ablony pro PlantUML<\/a><\/noindex> z\u00edskat n\u011bco, co se velmi podob\u00e1 skute\u010dn\u00e9 ER diagramu:<\/p>\n<p><\/p>\n<p>                        <b class=\"spoiler_title\">SQL dotaz je o n\u011bco slo\u017eit\u011bj\u0161\u00ed.<\/b><\/p>\n<pre><code class=\"sql\">-- Hlavi\u010dka\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-- Tabulky\nselect format(&#039;Table(%s, &quot;%s n informace o %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-- Vazby mezi tabulkami\nselect distinct ccu.table_name || &#039; &quot;1&quot; --&amp;gt; &quot;0..N&quot; &#039; || tc.table_name || format(&#039; : &quot;A %s m\u016f\u017ee m&iacute;t mnoho %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-- Z&aacute;pat&iacute;\nselect &#039;@enduml&#039;<\/code><\/pre>\n<p>\n<img decoding=\"async\" alt=\"Zku\u0161enost \u201eDatabase as Code\u201c\" src=\"\/wp-content\/uploads\/2020\/06\/bd45420a4fd1bdfcf20cbe74a0638c7b.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Pokud se pe\u010dliv\u011b pod\u00edv\u00e1te, mnoho vizualiza\u010dn\u00edch n\u00e1stroj\u016f pod kapotou pou\u017e\u00edv\u00e1 podobn\u00e9 dotazy. Pravda, tyto dotazy jsou obvykle hluboko <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/pgmodeler\/pgmodeler\/blob\/9c615c0b0871df3cd649983ce61e802b0ff0137b\/schemas\/catalog\/table.sch\">\"zat\u00ed\u017een\u00ed\" v k\u00f3du samotn\u00e9 aplikace a jsou slo\u017eit\u00e9 na pochopen\u00ed.<\/a><\/noindex>, nemluv\u011b o jejich jak\u00e9koliv modifikaci.<\/p>\n<p><\/p>\n<h5 id=\"metriki-i-monitoring\">Met\u0440\u0438\u043a\u0438 a monitorov\u00e1n\u00ed.<\/h5>\n<p><\/p>\n<p>P\u0159ejd\u011bme k tradi\u010dn\u011b slo\u017eit\u00e9mu t\u00e9matu \u2014 sledov\u00e1n\u00ed v\u00fdkonnosti datab\u00e1z\u00ed. R\u00e1d vzpomenu na mal\u00fd skute\u010dn\u00fd p\u0159\u00edb\u011bh, kter\u00fd mi vypr\u00e1v\u011bl \"jeden m\u016fj p\u0159\u00edtel\". Na jednom projektu \u017eil mocn\u00fd DBA, a m\u00e1lokdo z v\u00fdvoj\u00e1\u0159\u016f ho osobn\u011b znal nebo ho v\u016fbec kdy vid\u011bl (i kdy\u017e, podle pov\u011bst\u00ed, pracoval n\u011bkde v sousedn\u00ed budov\u011b). V hodin\u011b \"X\", kdy produk\u010dn\u00ed syst\u00e9m velk\u00e9ho retaileru op\u011bt za\u010d\u00ednal \"\u0161patn\u011b fungovat\", ti\u0161e pos\u00edlal screenshoty graf\u016f z Oracle Enterprise Manageru, na kter\u00fdch pe\u010dliv\u011b ozna\u010doval kritick\u00e9 oblasti \u010derven\u00fdm zv\u00fdraz\u0148ova\u010dem pro \"lep\u0161\u00ed p\u0159ehlednost\" (to, jemn\u011b \u0159e\u010deno, moc nepom\u00e1halo). A tak bylo t\u0159eba l\u00e9\u010dit podle t\u00e9to \"fotografie\". P\u0159\u00edstup k drahocenn\u00e9mu (v obou smyslech slova) Enterprise Manageru nikdo nem\u011bl, proto\u017ee syst\u00e9m je slo\u017eit\u00fd a drah\u00fd, a co kdyby \"v\u00fdvoj\u00e1\u0159i na n\u011bco narazili a v\u0161echno rozbili\". Tak\u017ee v\u00fdvoj\u00e1\u0159i empiricky nach\u00e1zeli m\u00edsto a p\u0159\u00ed\u010dinu zpomalen\u00ed a vyd\u00e1vali opravy. Pokud v nejbli\u017e\u0161\u00ed dob\u011b nep\u0159i\u0161el hroziv\u00fd dopis od DBA znovu, s \u00falevou si oddychli a vr\u00e1tili se ke sv\u00fdm aktu\u00e1ln\u00edm \u00fakol\u016fm (a\u017e do nov\u00e9ho Dopisu).<\/p>\n<p><\/p>\n<p>Ale proces sledov\u00e1n\u00ed m\u016f\u017ee vypadat mnohem z\u00e1bavn\u011bji a p\u0159\u00edv\u011btiv\u011bji, a co je nejd\u016fle\u017eit\u011bj\u0161\u00ed \u2014 b\u00fdt dostupn\u00fd a transparentn\u00ed pro v\u0161echny. Aspo\u0148 z\u00e1kladn\u00ed \u010d\u00e1st by m\u011bla b\u00fdt jako dopln\u011bk k hlavn\u00edm sledovac\u00edm syst\u00e9m\u016fm (kter\u00e9 jsou bezpochyby u\u017eite\u010dn\u00e9 a v mnoha p\u0159\u00edpadech nezbytn\u00e9). Ka\u017ed\u00e1 datab\u00e1zov\u00e1 platforma je ochotn\u00e1 a zcela zdarma sd\u00edlet informace o sv\u00e9m aktu\u00e1ln\u00edm stavu a v\u00fdkonnosti. V t\u00e9 sam\u00e9 \"krvav\u00e9\" Oracle DB lze prakticky jak\u00e9koli informace o v\u00fdkonnosti z\u00edskat ze syst\u00e9mov\u00fdch pohled\u016f, po\u010d\u00ednaje procesy a relacemi a kon\u010de stavem mezipam\u011bti (nap\u0159\u00edklad, <noindex><a rel=\"nofollow\" href=\"https:\/\/oracle-base.com\/dba\/scripts\">DBA Skripty<\/a><\/noindex>, sekce \"Monitoring\"). V PostgreSQL tak\u00e9 existuje cel\u00e1 \u0159ada syst\u00e9mov\u00fdch pohled\u016f pro <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/static\/monitoring-stats.html\">monitoring pr\u00e1ce datab\u00e1ze<\/a><\/noindex>, zejm\u00e9na takov\u00e9, kter\u00e9 jsou neoceniteln\u00e9 v ka\u017edodenn\u00edm \u017eivot\u011b ka\u017ed\u00e9ho DBA, jak\u00fdmi jsou <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>. V MySQL k tomu byla ur\u010dena dokonce samostatn\u00e1 sch\u00e9ma <noindex><a rel=\"nofollow\" href=\"https:\/\/dev.mysql.com\/doc\/refman\/8.0\/en\/performance-schema-table-descriptions.html\">performance_schema<\/a><\/noindex>. A v Mongo je zabudovan\u00fd <noindex><a rel=\"nofollow\" href=\"https:\/\/docs.mongodb.com\/manual\/tutorial\/manage-the-database-profiler\/\">profiler<\/a><\/noindex> , kter\u00fd agreguje data o v\u00fdkonu do syst\u00e9mov\u00e9 kolekce <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>Tak\u017ee, ozbrojeni n\u011bjak\u00fdm sb\u011bra\u010dem metrik (Telegraf, Metricbeat, Collectd), kter\u00fd um\u00ed prov\u00e1d\u011bt vlastn\u00ed sql dotazy, \u00falo\u017ei\u0161t\u011bm t\u011bchto metrik (InfluxDB, Elasticsearch, Timescaledb) a vizualiz\u00e1torem (Grafana, Kibana), lze z\u00edskat dostate\u010dn\u011b jednoduch\u00fd a flexibiln\u00ed monitorovac\u00ed syst\u00e9m, kter\u00fd bude \u00fazce integrov\u00e1n s dal\u0161\u00edmi syst\u00e9mov\u00fdmi metrikami (z\u00edskan\u00fdmi nap\u0159\u00edklad ze serveru aplikac\u00ed, z OS atd.). Jak je to nap\u0159\u00edklad ud\u011bl\u00e1no v pgwatch2, kde se pou\u017e\u00edv\u00e1 spojen\u00ed InfluxDB + Grafana a soubor dotaz\u016f na syst\u00e9mov\u00e9 pohledy, ke kter\u00fdm lze tak\u00e9 <noindex><a rel=\"nofollow\" href=\"https:\/\/github.com\/cybertec-postgresql\/pgwatch2#adding-metrics\">p\u0159idat vlastn\u00ed dotazy<\/a><\/noindex>.<\/p>\n<p><\/p>\n<h2 id=\"itogo\">Celkem<\/h2>\n<p><\/p>\n<p>A to je jen p\u0159ibli\u017en\u00fd seznam toho, co lze s na\u0161\u00ed DB pomoc\u00ed b\u011b\u017en\u00e9ho SQL k\u00f3du ud\u011blat. Jsem si jist\u00fd, \u017ee lze naj\u00edt je\u0161t\u011b spoustu vyu\u017eit\u00ed, napi\u0161te v koment\u00e1\u0159\u00edch. A o tom, jak (a co je nejd\u016fle\u017eit\u011bj\u0161\u00ed, pro\u010d) to v\u0161echno automatizovat a zahrnout do sv\u00e9ho CI\/CD pipeline, si promluv\u00edme p\u0159\u00ed\u0161t\u011b.<\/p>\n<p>Zdroj: <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.3 - 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\/cs\/blog\/administrirovanie\/database-as-sode-experience\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"cs_CZ\" \/>\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\/cs\/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 Experience | ProHoster","description":"SQL, co m\u016f\u017ee b\u00fdt jednodu\u0161\u0161\u00ed?","canonical_url":"https:\/\/prohoster.info\/cs\/blog\/administrirovanie\/database-as-sode-experience","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"cs_CZ","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\/cs\/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\/cs\/wp-json\/wp\/v2\/posts\/83649","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/comments?post=83649"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts\/83649\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/media\/83650"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/media?parent=83649"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/categories?post=83649"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/tags?post=83649"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}