Uzoefu wa "Hifadhi kama Kanuni".

Uzoefu wa "Hifadhi kama Kanuni".

SQL, ni nini kinachoweza kuwa rahisi zaidi? Kila mmoja wetu anaweza kuandika ombi rahisi - tunaandika teua, orodhesha safu wima zinazohitajika, basi kutoka, jina la jedwali, hali fulani ndani ambapo na hiyo ndiyo yote - data muhimu iko kwenye mfuko wetu, na (karibu) bila kujali ni DBMS gani iko chini ya kofia wakati huo (au labda sio DBMS hata kidogo) Kama matokeo, kufanya kazi na karibu chanzo chochote cha data (kimahusiano na sivyo) kinaweza kuzingatiwa kutoka kwa mtazamo wa msimbo wa kawaida (pamoja na yote ambayo inamaanisha - udhibiti wa toleo, uhakiki wa msimbo, uchanganuzi tuli, majaribio ya kiotomatiki, na ndivyo tu). Na hii inatumika sio tu kwa data yenyewe, schemas na uhamiaji, lakini kwa ujumla kwa maisha yote ya hifadhi. Katika nakala hii tutazungumza juu ya kazi za kila siku na shida za kufanya kazi na hifadhidata anuwai chini ya lensi ya "database kama nambari".

Na wacha tuanze kutoka ORM. Vita vya kwanza vya aina ya "SQL vs ORM" viligunduliwa nyuma kabla ya Petrine Rus.

Ramani ya kitu na uhusiano

Wafuasi wa ORM kawaida huthamini kasi na urahisi wa maendeleo, uhuru kutoka kwa DBMS na nambari safi. Kwa wengi wetu, nambari ya kufanya kazi na hifadhidata (na mara nyingi hifadhidata yenyewe)

kawaida inaonekana kama hii ...

@Entity
@Table(name = "stock", catalog = "maindb", uniqueConstraints = {
        @UniqueConstraint(columnNames = "STOCK_NAME"),
        @UniqueConstraint(columnNames = "STOCK_CODE") })
public class Stock implements java.io.Serializable {

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "STOCK_ID", unique = true, nullable = false)
    public Integer getStockId() {
        return this.stockId;
    }
  ...

Muundo huo umewekwa kwa maelezo mahiri, na mahali fulani nyuma ya pazia ORM shujaa hutengeneza na kutekeleza tani za msimbo fulani wa SQL. Kwa njia, watengenezaji wanajaribu bora yao kujitenga na hifadhidata yao na kilomita za vifupisho, ambayo inaonyesha baadhi. "SQL chuki".

Kwa upande mwingine wa vizuizi, wafuasi wa SQL safi "iliyotengenezwa kwa mikono" wanaona uwezo wa kufinya juisi yote kutoka kwa DBMS yao bila tabaka za ziada na vifupisho. Kama matokeo, miradi ya "data-centric" inaonekana, ambapo watu waliofunzwa maalum wanahusika katika hifadhidata (pia ni "basicist", pia ni "basicist", pia ni "basdeners", nk), na watengenezaji. lazima tu "kuvuta" maoni yaliyotengenezwa tayari na taratibu zilizohifadhiwa, bila kuingia katika maelezo.

Je, ikiwa tungekuwa na ulimwengu bora zaidi wa wote wawili? Jinsi hii inafanywa katika chombo cha ajabu kilicho na jina la kuthibitisha maisha Ndiyoql. Nitatoa mistari michache kutoka kwa dhana ya jumla katika tafsiri yangu ya bure, na unaweza kuifahamisha kwa undani zaidi. hapa.

Clojure ni lugha nzuri ya kuunda DSL, lakini SQL yenyewe ni DSL nzuri, na hatuhitaji nyingine. Maneno ya S ni mazuri, lakini hayaongezi chochote kipya hapa. Matokeo yake, tunapata mabano kwa ajili ya mabano. Je, hukubaliani? Kisha subiri wakati ambapo uondoaji juu ya hifadhidata huanza kuvuja na uanze kupigana na kazi (sql ghafi)

Kwa hiyo nifanye nini? Wacha tuache SQL kama SQL ya kawaida - faili moja kwa ombi:

-- name: users-by-country
select *
  from users
 where country_code = :country_code

... kisha usome faili hii, na kuibadilisha kuwa kazi ya kawaida ya Clojure:

(defqueries "some/where/users_by_country.sql"
   {:connection db-spec})

;;; A function with the name `users-by-country` has been created.
;;; Let's use it:
(users-by-country {:country_code "GB"})
;=> ({:name "Kris" :country_code "GB" ...} ...)

Kwa kuambatana na kanuni ya "SQL peke yake, Clojure peke yake", unapata:

  • Hakuna mshangao wa kisintaksia. Hifadhidata yako (kama nyingine yoyote) hailingani 100% na kiwango cha SQL - lakini hii haijalishi kwa Yesql. Kamwe hautapoteza wakati kutafuta vitendaji na syntax sawa ya SQL. Hutawahi kurudi kwenye kipengele cha kukokotoa (raw-sql "baadhi ('funky'::SYNTAX)")).
  • Usaidizi bora wa mhariri. Mhariri wako tayari ana usaidizi bora wa SQL. Kwa kuhifadhi SQL kama SQL unaweza kuitumia tu.
  • Utangamano wa timu. DBA zako zinaweza kusoma na kuandika SQL unayotumia katika mradi wako wa Clojure.
  • Urekebishaji rahisi wa utendaji. Je! unahitaji kuunda mpango wa swali lenye shida? Hili sio tatizo wakati hoja yako ni SQL ya kawaida.
  • Kutumia maswali tena. Buruta na uangushe faili hizo hizo za SQL kwenye miradi mingine kwa sababu ni SQL ya zamani tu - ishiriki tu.

Kwa maoni yangu, wazo ni baridi sana na wakati huo huo ni rahisi sana, shukrani ambayo mradi umepata wengi wafuasi katika lugha mbalimbali. Na tutajaribu tena kutumia falsafa sawa ya kutenganisha msimbo wa SQL kutoka kwa kila kitu kingine zaidi ya ORM.

Wasimamizi wa IDE na DB

Wacha tuanze na kazi rahisi ya kila siku. Mara nyingi tunapaswa kutafuta vitu vingine kwenye hifadhidata, kwa mfano, kupata jedwali kwenye schema na kusoma muundo wake (ni nguzo gani, funguo, faharisi, vikwazo, nk hutumiwa). Na kutoka kwa IDE yoyote ya picha au meneja mdogo wa DB, kwanza kabisa, tunatarajia uwezo huu haswa. Ili kwamba ni haraka na huna kusubiri nusu saa hadi dirisha na taarifa muhimu inatolewa (hasa kwa uunganisho wa polepole kwenye hifadhidata ya mbali), na wakati huo huo, habari iliyopokelewa ni safi na inafaa, na sio takataka iliyohifadhiwa. Kwa kuongezea, kadiri hifadhidata inavyozidi kuwa ngumu na kubwa na idadi yao kubwa, ndivyo ilivyo ngumu zaidi kufanya hivi.

Lakini kawaida mimi hutupa panya na kuandika nambari tu. Wacha tuseme unahitaji kujua ni meza gani (na ni mali gani) zilizomo kwenye schema ya "HR". Katika DBMS nyingi, matokeo unayotaka yanaweza kupatikana kwa swali hili rahisi kutoka kwa information_schema:

select table_name
     , ...
  from information_schema.tables
 where schema = 'HR'

Kutoka hifadhidata hadi hifadhidata, yaliyomo kwenye jedwali kama hizo za kumbukumbu hutofautiana kulingana na uwezo wa kila DBMS. Na, kwa mfano, kwa MySQL, kutoka kwa kitabu hicho cha kumbukumbu unaweza kupata vigezo vya jedwali maalum kwa DBMS hii:

select table_name
     , storage_engine -- Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ "Π΄Π²ΠΈΠΆΠΎΠΊ" ("MyISAM", "InnoDB" etc)
     , row_format     -- Π€ΠΎΡ€ΠΌΠ°Ρ‚ строки ("Fixed", "Dynamic" etc)
     , ...
  from information_schema.tables
 where schema = 'HR'

Oracle hajui information_schema, lakini ina Metadata ya Oracle, na hakuna shida kubwa zinazotokea:

select table_name
     , pct_free       -- ΠœΠΈΠ½ΠΈΠΌΡƒΠΌ свободного мСста Π² Π±Π»ΠΎΠΊΠ΅ Π΄Π°Π½Π½Ρ‹Ρ… (%)
     , pct_used       -- ΠœΠΈΠ½ΠΈΠΌΡƒΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠ³ΠΎ мСста Π² Π±Π»ΠΎΠΊΠ΅ Π΄Π°Π½Π½Ρ‹Ρ… (%)
     , last_analyzed  -- Π”Π°Ρ‚Π° послСднСго сбора статистики
     , ...
  from all_tables
 where owner = 'HR'

ClickHouse sio ubaguzi:

select name
     , engine -- Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ "Π΄Π²ΠΈΠΆΠΎΠΊ" ("MergeTree", "Dictionary" etc)
     , ...
  from system.tables
 where database = 'HR'

Kitu kama hicho kinaweza kufanywa katika Cassandra (ambayo ina safu familia badala ya meza na nafasi muhimu badala ya schemas):

select columnfamily_name
     , compaction_strategy_class  -- БтратСгия сборки мусора
     , gc_grace_seconds           -- ВрСмя ΠΆΠΈΠ·Π½ΠΈ мусора
     , ...
  from system.schema_columnfamilies
 where keyspace_name = 'HR'

Kwa hifadhidata zingine nyingi, unaweza pia kuja na maswali sawa (hata Mongo anayo mkusanyiko maalum wa mfumo, ambayo ina taarifa kuhusu makusanyo yote katika mfumo).

Bila shaka, kwa njia hii unaweza kupata taarifa si tu kuhusu meza, lakini kuhusu kitu chochote kwa ujumla. Mara kwa mara, watu wema hushiriki msimbo kama huo kwa hifadhidata tofauti, kama, kwa mfano, katika safu ya vifungu vya habra "Kazi za kuweka kumbukumbu za hifadhidata za PostgreSQL" (Ayb, Ben, ukumbi wa michezo) Kwa kweli, kuweka maswali mengi kichwani mwangu na kuyaandika kila mara ni jambo la kufurahisha sana, kwa hivyo katika IDE/mhariri ninayependa nina seti ya vijisehemu vilivyotayarishwa awali kwa maswali yanayotumiwa mara kwa mara, na kilichobaki ni kuandika tu. majina ya vitu kwenye kiolezo.

Kama matokeo, njia hii ya kuvinjari na kutafuta vitu ni rahisi zaidi, huokoa muda mwingi, na hukuruhusu kupata habari haswa katika fomu ambayo inahitajika sasa (kama, kwa mfano, ilivyoelezewa kwenye chapisho. "Kusafirisha data kutoka kwa hifadhidata katika muundo wowote: IDE zinaweza kufanya nini kwenye jukwaa la IntelliJ").

Operesheni na vitu

Baada ya kupata na kusoma vitu muhimu, ni wakati wa kufanya kitu muhimu nao. Kwa kawaida, pia bila kuchukua vidole vyako kwenye kibodi.

Sio siri kuwa kufuta tu jedwali kutaonekana sawa katika hifadhidata zote:

drop table hr.persons

Lakini kwa kuundwa kwa meza inakuwa ya kuvutia zaidi. Takriban DBMS yoyote (pamoja na NoSQL nyingi) inaweza "kuunda meza" kwa namna moja au nyingine, na sehemu yake kuu itatofautiana kidogo (jina, orodha ya safu, aina za data), lakini maelezo mengine yanaweza kutofautiana kwa kiasi kikubwa na hutegemea. kifaa cha ndani na uwezo wa DBMS maalum. Mfano wangu ninaoupenda zaidi ni kwamba katika hati za Oracle kuna BNF "uchi" tu za syntax ya "unda jedwali". kuchukua kurasa 31. DBMS zingine zina uwezo wa kawaida zaidi, lakini kila moja yao pia ina sifa nyingi za kupendeza na za kipekee za kuunda meza (postgres, mysql, mende, Cassandra) Haiwezekani kwamba "mchawi" wowote wa kielelezo kutoka kwa IDE nyingine (haswa ya ulimwengu wote) ataweza kufunika uwezo huu wote, na hata ikiwa inaweza, haitakuwa tamasha kwa moyo dhaifu. Wakati huo huo, taarifa iliyoandikwa kwa usahihi na kwa wakati tengeneza meza itakuruhusu kuzitumia zote kwa urahisi, kufanya hifadhi na ufikiaji wa data yako kuwa ya kuaminika, bora na ya kustarehesha iwezekanavyo.

Pia, DBMS nyingi zina aina zao maalum za vitu ambazo hazipatikani katika DBMS zingine. Kwa kuongezea, tunaweza kufanya shughuli sio tu kwenye vitu vya hifadhidata, lakini pia kwenye DBMS yenyewe, kwa mfano, "kuua" mchakato, fungua eneo fulani la kumbukumbu, wezesha ufuatiliaji, ubadilishe kwa hali ya "kusoma tu", na mengi zaidi.

Sasa hebu tuchore kidogo

Moja ya kazi za kawaida ni kujenga mchoro na vitu vya database na kuona vitu na uhusiano kati yao katika picha nzuri. Takriban IDE yoyote ya picha, huduma tofauti za "mstari wa amri", zana maalum za picha na viundaji vinaweza kufanya hivi. Watakuchorea kitu "kadiri wawezavyo," na unaweza kuathiri mchakato huu kidogo tu kwa usaidizi wa vigezo vichache kwenye faili ya usanidi au visanduku vya kuteua kwenye kiolesura.

Lakini tatizo hili linaweza kutatuliwa rahisi zaidi, rahisi zaidi na kifahari, na bila shaka kwa msaada wa kanuni. Ili kuunda michoro ya ugumu wowote, tunayo lugha kadhaa maalum za alama (DOT, GraphML n.k), ​​na kwao utawanyiko mzima wa programu (GraphViz, PlantUML, Mermaid) ambazo zinaweza kusoma maagizo kama haya na kuibua katika muundo tofauti. . Kweli, tayari tunajua jinsi ya kupata habari juu ya vitu na viunganisho kati yao.

Hapa kuna mfano mdogo wa jinsi hii inaweza kuonekana, kwa kutumia PlantUML na hifadhidata ya demo ya PostgreSQL (upande wa kushoto ni swali la SQL ambalo litatoa maagizo yanayohitajika kwa PlantUML, na upande wa kulia ni matokeo):

Uzoefu wa "Hifadhi kama Kanuni".

select '@startuml'||chr(10)||'hide methods'||chr(10)||'hide stereotypes' union all
select distinct ccu.table_name || ' --|> ' ||
       tc.table_name as val
  from table_constraints as tc
  join key_column_usage as kcu
    on tc.constraint_name = kcu.constraint_name
  join constraint_column_usage as ccu
    on ccu.constraint_name = tc.constraint_name
 where tc.constraint_type = 'FOREIGN KEY'
   and tc.table_name ~ '.*' union all
select '@enduml'

Na ukijaribu kidogo, basi kulingana na ER kiolezo kwa PlantUML unaweza kupata kitu sawa na mchoro halisi wa ER:

Swala la SQL ni gumu zaidi

-- Π¨Π°ΠΏΠΊΠ°
select '@startuml
        !define Table(name,desc) class name as "desc" << (T,#FFAAAA) >>
        !define primary_key(x) <b>x</b>
        !define unique(x) <color:green>x</color>
        !define not_null(x) <u>x</u>
        hide methods
        hide stereotypes'
 union all
-- Π’Π°Π±Π»ΠΈΡ†Ρ‹
select format('Table(%s, "%s n information about %s") {'||chr(10), table_name, table_name, table_name) ||
       (select string_agg(column_name || ' ' || upper(udt_name), chr(10))
          from information_schema.columns
         where table_schema = 'public'
           and table_name = t.table_name) || chr(10) || '}'
  from information_schema.tables t
 where table_schema = 'public'
 union all
-- Бвязи ΠΌΠ΅ΠΆΠ΄Ρƒ Ρ‚Π°Π±Π»ΠΈΡ†Π°ΠΌΠΈ
select distinct ccu.table_name || ' "1" --> "0..N" ' || tc.table_name || format(' : "A %s may haven many %s"', ccu.table_name, tc.table_name)
  from information_schema.table_constraints as tc
  join information_schema.key_column_usage as kcu on tc.constraint_name = kcu.constraint_name
  join information_schema.constraint_column_usage as ccu on ccu.constraint_name = tc.constraint_name
 where tc.constraint_type = 'FOREIGN KEY'
   and ccu.constraint_schema = 'public'
   and tc.table_name ~ '.*'
 union all
-- Подвал
select '@enduml'

Uzoefu wa "Hifadhi kama Kanuni".

Ukiangalia kwa karibu, chini ya kofia zana nyingi za taswira pia hutumia maswali sawa. Kweli, maombi haya kwa kawaida ni ya kina "hardwired" kwenye msimbo wa programu yenyewe na ni vigumu kuelewa, bila kutaja marekebisho yoyote yao.

Vipimo na ufuatiliaji

Wacha tuendelee kwenye mada changamano ya jadi - ufuatiliaji wa utendaji wa hifadhidata. Nakumbuka hadithi ndogo ya kweli iliyosimuliwa kwangu na "mmoja wa marafiki zangu." Katika mradi mwingine kulikuwa na DBA fulani yenye nguvu, na wachache wa watengenezaji walimjua kibinafsi, au wamewahi kumuona ana kwa ana (licha ya ukweli kwamba, kulingana na uvumi, alifanya kazi mahali fulani katika jengo linalofuata). Saa ya "X", wakati mfumo wa utaftaji wa muuzaji mkubwa ulianza "kujisikia vibaya" tena, alituma kimya picha za skrini kutoka kwa Oracle Enterprise Manager, ambayo alionyesha kwa uangalifu maeneo muhimu na alama nyekundu ya "kueleweka" ( hii, kuiweka kwa upole, haikusaidia sana). Na kulingana na "kadi ya picha" hii nilipaswa kutibu. Wakati huo huo, hakuna mtu aliyekuwa na upatikanaji wa thamani (kwa maana zote mbili za neno) Meneja wa Biashara, kwa sababu mfumo ni mgumu na wa gharama kubwa, ghafla "watengenezaji hujikwaa juu ya kitu na kuvunja kila kitu." Kwa hivyo, watengenezaji "kwa nguvu" walipata eneo na sababu ya breki na wakatoa kiraka. Ikiwa barua ya kutisha kutoka kwa DBA haikufika tena katika siku za usoni, basi kila mtu angepumua na kurudi kwenye kazi zao za sasa (mpaka Barua mpya).

Lakini mchakato wa ufuatiliaji unaweza kuonekana kuwa wa kufurahisha zaidi na wa kirafiki, na muhimu zaidi, kupatikana na kwa uwazi kwa kila mtu. Angalau sehemu yake ya msingi, kama nyongeza ya mifumo kuu ya ufuatiliaji (ambayo kwa hakika ni muhimu na katika hali nyingi haiwezi kurejeshwa). DBMS yoyote ni bure na bila malipo kabisa kushiriki habari kuhusu hali na utendaji wake wa sasa. Katika Oracle DB ile ile ya β€œdamu”, karibu taarifa yoyote kuhusu utendakazi inaweza kupatikana kutoka kwa mitazamo ya mfumo, kuanzia michakato na vipindi hadi hali ya akiba ya akiba (kwa mfano, Hati za DBA, sehemu ya "Ufuatiliaji"). Postgresql pia ina rundo zima la maoni ya mfumo kwa ufuatiliaji wa hifadhidata, hasa zile ambazo ni za lazima katika maisha ya kila siku ya DBA yoyote, kama vile pg_stat_shughuli, pg_stat_database, pg_stat_bgwriter. MySQL hata ina schema tofauti ya hii. performance_schema. A Katika Mongo iliyojengwa ndani profaili hujumlisha data ya utendaji katika mkusanyiko wa mfumo mfumo.wasifu.

Kwa hivyo, ikiwa na aina fulani ya mkusanyaji wa vipimo (Telegraf, Metricbeat, Collectd) ambayo inaweza kutekeleza maswali maalum ya sql, uhifadhi wa metriki hizi (InfluxDB, Elasticsearch, Timescaledb) na taswira (Grafana, Kibana), unaweza kupata rahisi sana. na mfumo wa ufuatiliaji unaonyumbulika ambao utaunganishwa kwa karibu na vipimo vingine vya mfumo mzima (zinazopatikana, kwa mfano, kutoka kwa seva ya programu, kutoka kwa OS, nk). Kama, kwa mfano, hii inafanywa katika pgwatch2, ambayo hutumia mchanganyiko wa InfluxDB + Grafana na seti ya maswali kwa maoni ya mfumo, ambayo yanaweza pia kupatikana. ongeza maswali maalum.

Katika jumla ya

Na hii ni orodha ya takriban ya kile kinachoweza kufanywa na hifadhidata yetu kwa kutumia msimbo wa kawaida wa SQL. Nina hakika unaweza kupata matumizi mengi zaidi, andika kwenye maoni. Na tutazungumza juu ya jinsi (na muhimu zaidi kwa nini) kubinafsisha haya yote na kuyajumuisha kwenye bomba lako la CI/CD wakati ujao.

Chanzo: mapenzi.com

Kuongeza maoni