Profiad «Cronfa Ddata fel Côd»

Profiad «Cronfa Ddata fel Côd»

SQL, beth allai fod yn haws? Gall pob un ohonom ysgrifennu cais syml - rydym yn teipio dewiswch, rhestrwch y colofnau gofynnol, yna o, enw tabl, ychydig o amodau yn lle a dyna i gyd - data defnyddiol yn ein poced, a (bron) waeth pa DBMS sydd o dan y cwfl bryd hynny (neu efallai ddim yn DBMS o gwbl). O ganlyniad, gellir ystyried gweithio gyda bron unrhyw ffynhonnell ddata (perthynol ac nid felly) o safbwynt cod cyffredin (gyda'r holl ganlyniadau - rheoli fersiwn, adolygu cod, dadansoddiad statig, profion awtomatig, a dyna i gyd). Ac mae hyn yn berthnasol nid yn unig i'r data ei hun, cynlluniau a mudo, ond yn gyffredinol i oes gyfan y storfa. Yn yr erthygl hon, byddwn yn siarad am dasgau bob dydd a phroblemau gweithio gyda chronfeydd data amrywiol o dan gwmpas "cronfa ddata fel cod".

A gadewch i ni ddechrau yn iawn gyda ORM. Gwelwyd y brwydrau cyntaf fel "SQL vs ORM" yn ôl i mewn cyn-Petrine Rus'.

Mapio perthynol i wrthrychau

Yn draddodiadol, mae cynigwyr ORM yn gwerthfawrogi cyflymder a rhwyddineb datblygiad, annibyniaeth o'r DBMS a phurdeb y cod. I lawer ohonom, y cod ar gyfer gweithio gyda'r gronfa ddata (ac yn aml y gronfa ddata ei hun)

mae fel arfer yn edrych fel hyn...

@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;
    }
  ...

Mae'r model wedi'i lapio mewn anodiadau clyfar, ac yn rhywle y tu ôl i'r llenni, mae ORM dewr yn cynhyrchu ac yn gweithredu tunnell o god SQL. Gyda llaw, mae datblygwyr yn ceisio gyda'u holl nerth i ynysu eu hunain o'u cronfa ddata gyda chilomedrau o dyniadau, sy'n dangos rhai "SQL casineb".

Ar ochr arall y barricades, mae ymlynwyr o "wneud â llaw" pur -SQL yn nodi'r gallu i wasgu'r holl sudd allan o'u DBMS heb haenau a thynnu ychwanegol. O ganlyniad, mae prosiectau "data-ganolog" yn ymddangos, lle mae pobl sydd wedi'u hyfforddi'n arbennig yn cymryd rhan yn y gronfa ddata (maent hefyd yn "sylfaenwyr", maent hefyd yn "sylfaenwyr", maent hefyd yn "bastardiaid", ac ati), a datblygwyr yn unig gorfod "tynnu" golygfeydd parod a gweithdrefnau wedi'u storio, heb fynd i fanylion.

A beth os cymerwch y gorau o'r ddau fyd? Sut mae'n cael ei wneud mewn teclyn gwych gydag enw sy'n cadarnhau bywyd Ydwql. Byddaf yn rhoi cwpl o linellau o'r cysyniad cyffredinol yn fy nghyfieithiad rhad ac am ddim, a gallwch ddod yn gyfarwydd ag ef yn fwy manwl yma.

Mae Clojure yn iaith cŵl ar gyfer adeiladu DSLs, ond mae SQL ei hun yn DSL cŵl ac nid oes angen un arall arnom. Mae ymadroddion S yn wych, ond nid ydynt yn ychwanegu unrhyw beth newydd yma. O ganlyniad, rydym yn cael cromfachau er mwyn cromfachau. Ddim yn cytuno? Yna arhoswch am y foment pan fydd y tynnu dros y gronfa ddata yn gollwng, a byddwch yn dechrau ymladd â'r swyddogaeth (amrai-sql)

A beth i'w wneud? Gadewch i ni adael SQL fel SQL arferol - un ffeil fesul cais:

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

...ac yna darllenwch y ffeil honno, gan ei throi'n swyddogaeth Clojure arferol:

(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" ...} ...)

Trwy gadw at yr egwyddor "SQL ar wahân, Clojure ar wahân", rydych chi'n cael:

  • Dim syndod syntactig. Nid yw eich cronfa ddata (fel unrhyw un arall) yn cydymffurfio 100% SQL - ond nid yw Yesql yn poeni. Ni fyddwch byth yn gwastraffu amser yn chwilio am swyddogaethau gyda chystrawen gyfatebol SQL. Nid oes yn rhaid i chi byth ddychwelyd i swyddogaeth (raw-sql "rhai ('ffynci'::SYNTAX)")).
  • Gwell cefnogaeth golygydd. Mae gan eich golygydd gefnogaeth SQL ardderchog eisoes. Trwy storio SQL fel SQL gallwch chi ei ddefnyddio.
  • Cydnawsedd Tîm. Gall eich DBAs ddarllen ac ysgrifennu'r SQL a ddefnyddiwch yn eich prosiect Clojure.
  • Tiwnio perfformiad haws. Angen adeiladu cynllun ar gyfer ymholiad problemus? Nid yw hyn yn broblem pan fydd eich ymholiad yn SQL rheolaidd.
  • Ailddefnyddio ymholiadau. Llusgwch yr un ffeiliau SQL hynny i brosiectau eraill oherwydd ei fod yn hen SQL da - dim ond ei rannu.

Yn fy marn i, mae'r syniad yn cŵl iawn ac ar yr un pryd yn syml iawn, diolch i'r hyn mae'r prosiect wedi ennill llawer dilynwyr mewn amrywiaeth o ieithoedd. Ac yna byddwn yn ceisio cymhwyso athroniaeth debyg o wahanu cod SQL oddi wrth bopeth arall ymhell y tu hwnt i'r ORM.

Rheolwyr DRhA a DB

Gadewch i ni ddechrau gyda thasg bob dydd syml. Yn aml mae'n rhaid i ni chwilio am rai gwrthrychau yn y gronfa ddata, er enghraifft, dod o hyd i dabl yn y sgema ac astudio ei strwythur (pa golofnau, allweddi, mynegeion, cyfyngiadau, ac ati sy'n cael eu defnyddio). Ac o unrhyw IDE graffigol neu reolwr DB bach, yn gyntaf oll, rydym yn aros am yr union alluoedd hyn. Fel ei fod yn gyflym ac nad oes rhaid iddo aros hanner awr nes bod ffenestr gyda'r wybodaeth angenrheidiol yn cael ei thynnu (yn enwedig gyda chysylltiad araf â chronfa ddata anghysbell), ac ar yr un pryd bod y wybodaeth a dderbynnir yn ffres ac yn berthnasol, a sothach heb ei storio. Ar ben hynny, po fwyaf cymhleth a mwyaf yw'r gronfa ddata a'r mwyaf yw eu nifer, y mwyaf anodd yw hi i'w wneud.

Ond fel arfer dwi'n taflu'r llygoden ymhell i ffwrdd a jest ysgrifennu'r côd. Gadewch i ni ddweud eich bod chi eisiau gwybod pa dablau (a pha briodweddau) sydd wedi'u cynnwys yn y sgema "AD". Yn y rhan fwyaf o DBMS, gellir cyflawni'r canlyniad a ddymunir gydag ymholiad mor syml o information_schema:

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

O gronfa ddata i gronfa ddata, mae cynnwys tablau chwilio o'r fath yn amrywio yn dibynnu ar allu pob DBMS. Ac, er enghraifft, ar gyfer MySQL, o'r un cyfeiriadur, gallwch gael paramedrau tabl sy'n benodol i'r DBMS hwn:

select table_name
     , storage_engine -- Используемый "движок" ("MyISAM", "InnoDB" etc)
     , row_format     -- Формат строки ("Fixed", "Dynamic" etc)
     , ...
  from information_schema.tables
 where schema = 'HR'

Nid yw Oracle yn gwybod information_schema, ond mae'n gwybod Metadata Oracle, ac nid oes unrhyw broblemau mawr:

select table_name
     , pct_free       -- Минимум свободного места в блоке данных (%)
     , pct_used       -- Минимум используемого места в блоке данных (%)
     , last_analyzed  -- Дата последнего сбора статистики
     , ...
  from all_tables
 where owner = 'HR'

Nid yw ClickHouse yn eithriad:

select name
     , engine -- Используемый "движок" ("MergeTree", "Dictionary" etc)
     , ...
  from system.tables
 where database = 'HR'

Gellir gwneud rhywbeth tebyg yn Cassandra (sydd â theuluoedd colofn yn lle tablau a bylchau allweddol yn lle sgemâu):

select columnfamily_name
     , compaction_strategy_class  -- Стратегия сборки мусора
     , gc_grace_seconds           -- Время жизни мусора
     , ...
  from system.schema_columnfamilies
 where keyspace_name = 'HR'

Ar gyfer y rhan fwyaf o gronfeydd data eraill, gallwch hefyd ddod o hyd i ymholiadau tebyg (mae gan Mongo hyd yn oed casgliad system arbennig, sy'n cynnwys gwybodaeth am yr holl gasgliadau yn y system).

Wrth gwrs, yn y modd hwn gallwch gael gwybodaeth nid yn unig am dablau, ond yn gyffredinol am unrhyw wrthrych. O bryd i'w gilydd, mae pobl garedig yn rhannu cod o'r fath ar gyfer gwahanol gronfeydd data, fel, er enghraifft, yn y gyfres o erthyglau habra "Swyddogaethau ar gyfer dogfennu cronfeydd data PostgreSQL" (ayb, ben, Campfa). Wrth gwrs, mae cadw'r holl fynydd hwn o ymholiadau yn fy mhen a'u teipio'n gyson yn bleser "o'r fath", felly yn fy hoff IDE / golygydd mae gen i set o bytiau wedi'u paratoi ymlaen llaw ar gyfer ymholiadau a ddefnyddir yn aml, a'r cyfan sy'n weddill yw teipiwch enwau'r gwrthrychau yn y templed.

O ganlyniad, mae'r ffordd hon o lywio a chwilio am wrthrychau yn llawer mwy hyblyg, yn arbed llawer o amser, yn caniatáu ichi gael yr union wybodaeth ac yn y ffurf y mae ei hangen arnoch nawr (fel, er enghraifft, a ddisgrifir yn y post). msgstr "Allforio data o gronfa ddata mewn unrhyw fformat: beth all DRhA ar blatfform IntelliJ ei wneud").

Gweithrediadau gyda gwrthrychau

Ar ôl i ni ddarganfod ac astudio'r gwrthrychau angenrheidiol, mae'n bryd gwneud rhywbeth defnyddiol gyda nhw. Yn naturiol, hefyd heb dynnu'ch bysedd oddi ar y bysellfwrdd.

Nid yw'n gyfrinach y bydd dileu tabl yn edrych yr un peth ym mron pob cronfa ddata:

drop table hr.persons

Ond gyda chreu'r tabl eisoes yn fwy diddorol. Gall bron unrhyw DBMS (gan gynnwys llawer o NoSQL) mewn rhyw ffurf neu'i gilydd "greu tabl", ac ni fydd ei brif ran hyd yn oed yn wahanol iawn (enw, rhestr o golofnau, mathau o ddata), ond gall manylion eraill amrywio'n ddramatig a dibynnu ar y ddyfais fewnol a galluoedd DBMS penodol. Fy hoff enghraifft yw mai dim ond un BNF "moel" sydd yn nogfennaeth Oracle ar gyfer y gystrawen "creu tabl" meddiannu 31 tudalen. Mae gan DBMS eraill alluoedd mwy cymedrol, ond mae gan bob un ohonynt hefyd lawer o nodweddion diddorol ac unigryw ar gyfer creu tablau (postgres, mysql, chwilen ddu, Cassandra). Mae'n annhebygol y bydd unrhyw "dewin" graffeg o'r DRhA nesaf (yn enwedig cyffredinol) yn gallu cwmpasu'r holl alluoedd hyn yn llawn, ac os gall, yna ni fydd yn olygfa i'r gwan o galon. Ar yr un pryd, datganiad ysgrifenedig cywir ac amserol creu bwrdd yn eich galluogi i ddefnyddio pob un ohonynt yn hawdd, gwneud storio a mynediad at eich data yn ddibynadwy, optimaidd ac mor gyfforddus â phosibl.

Hefyd, mae gan lawer o DBMS eu mathau penodol eu hunain o wrthrychau nad ydynt ar gael mewn DBMSs eraill. Ar ben hynny, gallwn berfformio gweithrediadau nid yn unig ar wrthrychau cronfa ddata, ond hefyd ar y DBMS ei hun, er enghraifft, "lladd" y broses, am ddim rhywfaint o ardal cof, galluogi olrhain, newid i "darllen yn unig" modd, a llawer mwy.

Ac yn awr gadewch i ni dynnu ychydig

Un o'r tasgau mwyaf cyffredin yw adeiladu diagram gyda gwrthrychau cronfa ddata, i weld y gwrthrychau a'r berthynas rhyngddynt mewn llun hardd. Gall bron unrhyw DRhA graffig, cyfleustodau "llinell orchymyn" ar wahân, offer graffig arbenigol a modelwyr wneud hyn. A fydd yn tynnu rhywbeth i chi "y gorau y gallant", a dim ond gyda chymorth ychydig o baramedrau yn y ffeil ffurfweddu neu'r blychau gwirio yn y rhyngwyneb y gallwch chi ddylanwadu ychydig ar y broses hon.

Ond gellir datrys y broblem hon mewn ffordd llawer symlach, mwy hyblyg a chain, ac wrth gwrs gyda chymorth cod. I adeiladu diagramau o unrhyw gymhlethdod, mae gennym nifer o ieithoedd marcio arbenigol ar unwaith (DOT, GraphML ac ati), ac ar eu cyfer - criw cyfan o gymwysiadau (GraphViz, PlantUML, Mermaid) sy'n gallu darllen cyfarwyddiadau o'r fath a'u delweddu mewn a amrywiaeth o fformatau. Wel, rydym eisoes yn gwybod sut i gael gwybodaeth am wrthrychau a'r berthynas rhyngddynt.

Gadewch i ni roi enghraifft fach o sut y gallai edrych fel defnyddio PlantUML a cronfa ddata demo ar gyfer PostgreSQL (ar y chwith mae'r ymholiad SQL a fydd yn cynhyrchu'r cyfarwyddyd gofynnol ar gyfer PlantUML, ac ar y dde mae'r canlyniad):

Profiad «Cronfa Ddata fel Côd»

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'

Ac os ceisiwch ychydig, yna ar sail Templed ER ar gyfer PlantUML gallwch chi gael rhywbeth tebyg iawn i ddiagram ER go iawn:

Mae ymholiad SQL ychydig yn fwy cymhleth

-- Шапка
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'

Profiad «Cronfa Ddata fel Côd»

Os edrychwch yn ofalus, o dan y cwfl, mae llawer o offer delweddu hefyd yn defnyddio ymholiadau tebyg. Yn wir, mae'r ceisiadau hyn fel arfer yn ddwfn "hardwired" i mewn i'r cod y cais ei hun ac yn anodd ei ddeallheb sôn am unrhyw addasiad ohonynt.

Metrigau a monitro

Gadewch i ni symud ymlaen at y pwnc anodd yn draddodiadol - monitro perfformiad cronfa ddata. Rwy'n cofio stori fach wir a adroddwyd wrthyf gan "un o fy ffrindiau". Ar y prosiect nesaf, roedd DBA pwerus yn byw yno, ac ychydig o'r datblygwyr oedd yn ei adnabod yn bersonol, ac yn wir erioed wedi ei weld yn y llygad (er gwaethaf y ffaith ei fod yn gweithio, yn ôl sibrydion, rhywle mewn adeilad cyfagos). Ar awr "X", pan ddechreuodd system poduction manwerthwr mawr "deimlo'n ddrwg" unwaith eto, anfonodd sgrinluniau o graffiau yn dawel oddi wrth y Rheolwr Menter Oracle, ac amlygodd yn ofalus leoedd hanfodol gyda marciwr coch ar gyfer "clirder" (ni wnaeth hyn, i'w roi'n ysgafn, helpu llawer). Ac roedd yn rhaid trin y "cerdyn llun" hwn. Ar yr un pryd, nid oedd gan neb fynediad at y Rheolwr Menter gwerthfawr (yn y ddau ystyr o'r gair), oherwydd mae'r system yn gymhleth ac yn ddrud, yn sydyn "bydd y datblygwyr yn baglu ar rywbeth ac yn torri popeth." Felly, mae'r datblygwyr "empirig" dod o hyd i'r lle ac achos y breciau a rhyddhau darn. Os na ddaeth y llythyr ofnadwy oddi wrth DBA eto yn y dyfodol agos, yna anadlodd pawb ochenaid o ryddhad a dychwelyd at eu tasgau presennol (tan y Llythyr newydd).

Ond gall y broses fonitro edrych yn fwy hwyliog a chyfeillgar, ac yn bwysicaf oll, yn hygyrch ac yn dryloyw i bawb. O leiaf ei ran sylfaenol, fel ychwanegiad at y prif systemau monitro (sy'n sicr yn ddefnyddiol ac mewn llawer o achosion na ellir eu hadnewyddu). Mae unrhyw DBMS yn rhydd ac yn rhad ac am ddim yn barod i rannu gwybodaeth am ei gyflwr a'i berfformiad presennol. Yn yr un Oracle DB "gwaedlyd", gellir cael bron unrhyw wybodaeth perfformiad o olygfeydd system, o brosesau a sesiynau i gyflwr y storfa byffer (er enghraifft, Sgriptiau DBA, adran "Monitro"). Mae gan Postgresql hefyd griw o safbwyntiau system ar gyfer monitro gweithrediad cronfa ddata, yn arbennig, y fath anhepgor ym mywyd beunyddiol unrhyw DBA ag pg_stat_gweithgaredd, pg_stat_cronfa ddata, pg_stat_bwriter. Yn MySQL, mae hyd yn oed sgema ar wahân wedi'i gynllunio ar gyfer hyn. sgema_perfformiad. A B Mongo adeiledig yn proffiliwr cyfuno data perfformiad i gasgliad system system.profile.

Felly, wedi'i arfogi â rhyw fath o gasglwr metrigau (Telegraf, Metricbeat, Collectd), a all weithredu ymholiadau sql arferol, storfa o'r metrigau hyn (InfluxDB, Elasticsearch, Timescaledb) a delweddwr (Grafana, Kibana), gallwch gael gweddol. system fonitro hawdd a hyblyg a fydd wedi'i hintegreiddio'n dynn â metrigau system gyfan eraill (a geir, er enghraifft, gan weinydd y cais, gan yr OS, ac ati). Fel, er enghraifft, mae'n cael ei wneud yn pgwatch2, sy'n defnyddio bwndel InfluxDB + Grafana a set o ymholiadau i farn system, a all hefyd fod yn ychwanegu ceisiadau personol.

Yn gyfan gwbl

A dim ond bras restr yw hon o'r hyn y gellir ei wneud gyda'n cronfa ddata gan ddefnyddio cod SQL cyffredin. Rwy'n siŵr y gallwch ddod o hyd i lawer mwy o geisiadau, ysgrifennwch y sylwadau. A byddwn yn siarad am sut (ac yn bwysicaf oll pam) i awtomeiddio hyn i gyd a'i gynnwys yn eich piblinell CI / CD y tro nesaf.

Ffynhonnell: hab.com

Ychwanegu sylw