"Datu-basea Kode gisa" Esperientzia

"Datu-basea Kode gisa" Esperientzia

SQL, zer izan liteke sinpleagoa? Gutako bakoitzak eskaera sinple bat idatzi dezake - idazten dugu hautatu, zerrendatu behar diren zutabeak, gero ra, taularen izena, baldintza batzuk barne non eta hori da guztia - datu erabilgarriak gure poltsikoan daude, eta (ia) edozein DBMS dagoen une horretan (edo agian ez batere DBMS bat). Ondorioz, ia edozein datu-iturrirekin lan egitea (erlazionala eta ez hain) kode arruntaren ikuspuntutik har daiteke (esan nahi duen guztiarekin: bertsio-kontrola, kodea berrikustea, analisi estatikoa, autotestak, eta hori guztia). Eta hori ez da soilik datuei, eskemei eta migrazioei aplikatzen, baizik eta, oro har, biltegiaren bizitza osorako. Artikulu honetan hainbat datu-baseekin lan egiteko eguneroko zereginei eta arazoei buruz hitz egingo dugu "datu-basea kode gisa".

Eta bertatik has gaitezen suge. "SQL vs ORM" motako lehen borrokak berriro nabaritu ziren Petrine Rusaren aurrekoa.

Objektu-erlazio mapak

ORMen aldekoek abiadura eta garapen erraztasuna, DBMSarekiko independentzia eta kode garbia baloratzen dituzte. Gutako askorentzat, datu-basearekin lan egiteko kodea (eta askotan datu-basea bera)

normalean horrelako zerbait izaten da...

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

Eredua oharpen burutsuekin zintzilikatuta dago, eta eszenaren atzean ORM ausart batek SQL kode asko sortzen eta exekutatzen ditu. Bide batez, garatzaileak ahalik eta gehien saiatzen ari dira beren datu-basetik isolatzen kilometroko abstrakzioekin, eta horrek adierazten du. "SQL gorrotoa".

Barrikaden beste aldean, "eskuz egindako" SQL hutsaren atxikimenduek euren DBMStik zuku guztia geruza eta abstrakzio gehigarririk gabe ateratzeko gaitasuna dutela ohartzen dira. Ondorioz, “data-centric” proiektuak agertzen dira, non datu-basean bereziki prestatuta dauden pertsonak parte hartzen duten («oinarrizkoak» ere badira, «oinarrizkoak» ere badira, «basdentzaileak» ere badira, etab.), eta garatzaileak. prest egindako ikuspegiak eta gordetako prozedurei "tira" besterik ez zaie egin behar, xehetasunetan sartu gabe.

Eta bi munduetako onena izango bagenu? Nola egiten den hau bizitza baieztatzen duen izena duen tresna zoragarri batean Yesql. Kontzeptu orokorreko lerro pare bat emango ditut nire doako itzulpenean, eta xehetasun gehiagorekin ezagutu dezakezu Hemen.

Clojure lengoaia polita da DSLak sortzeko, baina SQL bera DSL polita da, eta ez dugu beste bat behar. S-esamoldeak bikainak dira, baina hemen ez dute ezer berririk gehitzen. Ondorioz, kortxeteak lortzen ditugu parentesiengatik. Ez al zaude ados? Ondoren, itxaron datu-basearen gaineko abstrakzioa ihes egiten hasten den eta funtzioarekin borrokan hasten zarenean (raw-sql)

Beraz, zer egin behar dut? Utz dezagun SQL SQL arrunt gisa - eskaera bakoitzeko fitxategi bat:

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

... eta gero irakurri fitxategi hau, Clojure funtzio arrunt bihurtuz:

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

"SQL berez, Clojure berez" printzipioari atxikita, lortuko duzu:

  • Ezusteko sintaktikorik ez. Zure datu-basea (beste edozein bezala) ez da 100% SQL estandarra betetzen, baina honek ez du axola Yesql-entzat. Ez duzu inoiz denbora galduko SQL sintaxi baliokidea duten funtzioen bila. Ez duzu inoiz funtzio batera itzuli beharko (raw-sql "batzuk('funky'::SYNTAX)")).
  • Editorearen laguntza onena. Zure editoreak dagoeneko SQL laguntza bikaina du. SQL SQL gisa gordeta, besterik gabe erabil dezakezu.
  • Taldeen bateragarritasuna. Zure DBA-ek Clojure proiektuan erabiltzen duzun SQL irakurri eta idatzi dezakete.
  • Errendimenduaren doikuntza errazagoa. Kontsulta arazotsu baterako plan bat sortu behar duzu? Hau ez da arazoa zure kontsulta SQL arrunta denean.
  • Kontsultak berrerabiltzea. Arrastatu eta jaregin SQL fitxategi berberak beste proiektu batzuetan SQL zaharra besterik ez delako - partekatu besterik ez.

Nire ustez, ideia oso polita da eta aldi berean oso sinplea da, eta horri esker proiektuak asko irabazi ditu jarraitzaileak hainbat hizkuntzatan. Eta hurrengoan saiatuko gara aplikatzen SQL kodea ORMtik haratago dagoen guztia bereizteko antzeko filosofia bat aplikatzen.

IDE eta DB kudeatzaileak

Has gaitezen eguneroko zeregin sinple batekin. Askotan datu-basean objektu batzuk bilatu behar izaten ditugu, adibidez, eskeman taula bat aurkitu eta haren egitura aztertu (zer zutabe, gako, indize, murriztapen, etab. erabiltzen diren). Eta edozein IDE grafikotik edo DB-kudeatzaile txiki batetik, lehenik eta behin, gaitasun horiek zehatz-mehatz espero ditugu. Beraz, azkarra izan dadin eta ez duzu ordu erdi itxaron behar beharrezkoa den informazioa duen leiho bat marraztu arte (batez ere urruneko datu-base batera konexio motel batekin), eta, aldi berean, jasotako informazioa freskoa eta garrantzitsua da, eta ez cachean gordetako zaborra. Gainera, datu-basea zenbat eta konplexuagoa eta handiagoa izan eta zenbat eta kopuru handiagoa izan, orduan eta zailagoa da hori egitea.

Baina normalean sagua botatzen dut eta kodea idazten dut. Demagun "HR" eskeman zein taulak (eta zein propietaterekin) dauden aurkitu behar duzula. DBMS gehienetan, nahi den emaitza lor daiteke informazio_eskema-ko kontsulta sinple honekin:

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

Datu-base batetik bestera, erreferentzia-taulen edukia aldatu egiten da DBMS bakoitzaren gaitasunen arabera. Eta, adibidez, MySQL-rako, erreferentzia-liburu beretik DBMS honetarako taula-parametroak lor ditzakezu:

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

Oracle-k ez daki informazio_eskema, baina bai Oracle metadatuak, eta ez da arazo handirik sortzen:

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

ClickHouse ez da salbuespena:

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

Antzeko zerbait egin daiteke Cassandra-n (zutabe-familiak ditu taulak eta gako-guneak eskemaren ordez):

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

Beste datu-base gehienetarako, antzeko kontsultak ere egin ditzakezu (Mongok ere baditu sistema-bilketa berezia, sistemako bilduma guztiei buruzko informazioa jasotzen duena).

Jakina, modu honetan taulei buruz ez ezik, oro har edozein objekturi buruzko informazioa lor dezakezu. Noizean behin, pertsona jatorrak datu-base desberdinetarako kode hori partekatzen du, adibidez, habra artikuluen seriean "PostgreSQL datu-baseak dokumentatzeko funtzioak" (Ayb, Ben, Gimnasioa). Jakina, kontsulten mendi guztia buruan edukitzea eta etengabe idaztea oso plazerra da, beraz, nire IDE/editore gogokoenean maiz erabiltzen diren kontsultetarako aldez aurretik prestatutako zati bat daukat, eta geratzen dena idaztea da. objektuen izenak txantiloian.

Ondorioz, objektuak nabigatzeko eta bilatzeko metodo hau askoz malguagoa da, denbora asko aurrezten du eta orain beharrezkoa den moduan informazio zehatza lortzeko aukera ematen du (adibidez, argitalpenean azaltzen den bezala). "Datu-base batetik datuak edozein formatuan esportatzea: zer egin dezaketen IDEek IntelliJ plataforman").

Objektuekin eragiketak

Beharrezko objektuak aurkitu eta aztertu ondoren, haiekin zerbait erabilgarria egiteko garaia da. Noski, baita hatzak teklatutik kendu gabe ere.

Ez da sekretua taula bat ezabatzeak ia datu-base guztietan itxura bera izango duela:

drop table hr.persons

Baina mahaiaren sorrerarekin interesgarriagoa bihurtzen da. Ia edozein DBMS (NoSQL asko barne) "taula" modu batean edo bestean "sortu" dezake, eta zati nagusia apur bat ere desberdina izango da (izena, zutabeen zerrenda, datu-motak), baina beste xehetasun batzuk nabarmen desberdinak izan daitezke eta araberakoak izango dira. barne gailua eta DBMS jakin baten gaitasunak. Nire adibiderik gogokoena da Oracleko dokumentazioan BNF "biluziak" baino ez daudela "sortu taula" sintaxirako. 31 orrialde hartzen ditu. Beste DBMS batzuek gaitasun xumeagoak dituzte, baina horietako bakoitzak taulak sortzeko ezaugarri interesgarri eta berezi asko ditu (postgres, mysql, labezomorro, Cassandra). Nekez izango da beste IDE bateko "morroi" grafikoren bat (batez ere unibertsala) gaitasun horiek guztiak guztiz estaltzeko gai izango denik, eta ahal badu ere, ez da ikuskizun bat izango bihotz ahulentzat. Aldi berean, zuzen eta garaiz idatzitako adierazpena taula sortu horiek guztiak erraz erabiltzeko aukera emango dizu, biltegiratzea eta zure datuetarako sarbidea fidagarri, optimo eta ahalik eta erosoen egiteko.

Gainera, DBMS askok beste DBMS batzuetan eskuragarri ez dauden objektu mota espezifikoak dituzte. Gainera, datu-baseko objektuetan ez ezik, DBMSn bertan ere eragiketak egin ditzakegu, adibidez, prozesu bat "hil", memoria-eremu bat askatu, jarraipena gaitu, "irakurtzeko soilik" modura aldatu eta askoz gehiago.

Orain marraztu dezagun pixka bat

Zeregin ohikoenetako bat datu-baseko objektuekin diagrama bat eraikitzea da eta haien arteko objektuak eta konexioak irudi eder batean ikustea da. Ia edozein IDE grafiko, "komando-lerroko" utilitate bereiziek, tresna grafiko espezializatuek eta modelatzaileek egin dezakete. Zerbait marraztuko dizute "ahal duten moduan", eta prozesu honetan apur bat eragin dezakezu konfigurazio fitxategiko parametro batzuen edo interfazeko kontrol-laukien laguntzarekin.

Baina arazo hau askoz errazagoa, malguagoa eta dotoreagoa konpon daiteke, eta noski kodearen laguntzaz. Edozein konplexutasuneko diagramak sortzeko, hainbat marka-lengoaia espezializatu ditugu (DOT, GraphML eta abar), eta horientzako aplikazio-sakabanaketa oso bat (GraphViz, PlantUML, Mermaid) argibideak irakurri eta hainbat formatutan ikus ditzaketenak. . Bada, jada badakigu objektuei eta haien arteko loturei buruzko informazioa nola lortu.

Hona hemen hau nolakoa izan daitekeen adibide txiki bat, PlantUML eta PostgreSQL-rako demo datu-basea (ezkerrean PlantUMLrako beharrezko instrukzioa sortuko duen SQL kontsulta bat dago, eta eskuinaldean emaitza):

"Datu-basea Kode gisa" Esperientzia

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'

Eta pixka bat saiatzen bazara, orduan oinarrituta PlantUMLrako ER txantiloia benetako ER diagrama baten antzeko zerbait lor dezakezu:

SQL kontsulta pixka bat zailagoa da

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

"Datu-basea Kode gisa" Esperientzia

Arretaz begiratuz gero, kanpaiaren azpian bistaratzeko tresna askok ere antzeko kontsultak erabiltzen dituzte. Egia da, eskaera hauek sakonak izan ohi dira "hardwired" aplikazioaren beraren kodean eta ulertzea zaila da, horien aldaketarik gabe.

Metrikoak eta jarraipena

Goazen tradizionalki konplexua den gai batera: datu-baseen errendimenduaren jarraipena. Gogoan dut "nire lagunetako batek" kontatu zidan benetako istorio txiki bat. Beste proiektu batean DBA indartsu bat bizi zen, eta garatzaileetatik gutxik ezagutzen zuten pertsonalki, edo inoiz ikusi zuten pertsonalki (zurrumurruen arabera, ondoko eraikinean nonbait lan egin zuen arren). "X" orduan, dendari handi baten produkzio-sistema berriro "txarto sentitzen" hasi zenean, isilik bidali zituen Oracle Enterprise Manager-en grafikoen pantaila-argazkiak, zeinetan arreta handiz nabarmendu zituen toki kritikoak "ulergarritasunerako" marka gorri batekin ( honek, gutxi esanda, ez zuen asko lagundu). Eta “argazki-txartel” horretan oinarrituta tratatu behar izan nuen. Aldi berean, inork ez zuen sarbide preziatua (hitzaren bi zentzuetan) Enterprise Managerra, zeren sistema konplexua eta garestia da, bat-batean "garatzaileek zerbaitekin estropezu egiten dute eta dena apurtzen dute". Hori dela eta, garatzaileek "enpirikoki" balazten kokapena eta kausa aurkitu zuten eta adabaki bat kaleratu zuten. DBAren gutun mehatxagarria etorkizun hurbilean berriro iristen ez balitz, denek arnasa hartuko lukete eta oraingo zereginetara itzuliko litzateke (Gutun berrira arte).

Baina jarraipen-prozesua dibertigarriagoa eta atseginagoa izan daiteke, eta, batez ere, eskuragarri eta gardenagoa denentzat. Bere oinarrizko zatia bederen, monitorizazio sistema nagusien gehigarri gisa (baliagarriak eta kasu askotan ordezkaezinak direnak, zalantzarik gabe). Edozein DBMS libre eta guztiz doakoa da bere egungo egoerari eta errendimenduari buruzko informazioa partekatzeko. Oracle DB "odoltsu" berean, errendimenduari buruzko ia edozein informazio lor daiteke sistemaren ikuspegietatik, prozesu eta saioetatik hasi eta buffer cachearen egoeraraino (adibidez, DBA gidoiak, "Segimendua" atala). Postgresql-ek sistemaren ikuspegi ugari ditu datu-baseen jarraipena, bereziki edozein DBAren eguneroko bizitzan ezinbestekoak direnak, esaterako pg_stat_activity, pg_stat_database, pg_stat_bgwriter. MySQL-k horretarako eskema berezi bat ere badu. errendimendu_eskema. A In Mongo eraikia profilatzailea errendimendu-datuak sistema-bilduma batean biltzen ditu sistema.profila.

Horrela, sql kontsulta pertsonalizatuak, metrika hauen biltegiratze bat (InfluxDB, Elasticsearch, Timescaledb) eta bistaratzaile bat (Grafana, Kibana) egin ditzaketen metrika-biltzaile mota batekin (Telegraf, Metricbeat, Collectd), nahiko erraz lor dezakezu. eta monitorizazio-sistema malgu bat, sistema osoko beste metrika batzuekin estuki integratuko dena (adibidez, aplikazioen zerbitzaritik, OStik, etab. lortutakoa). Esaterako, pgwatch2-n egiten den moduan, InfluxDB + Grafana konbinazioa eta sistema-ikuspegietarako kontsulta-multzo bat erabiltzen dituena, zeina ere atzitu daiteke. gehitu kontsulta pertsonalizatuak.

Guztira

Eta hau gure datu-basearekin SQL kode arrunta erabiliz egin daitekeenaren gutxi gorabeherako zerrenda besterik ez da. Ziur asko erabilera gehiago aurkituko dituzula, idatzi iruzkinetan. Eta hau guztia nola (eta garrantzitsuena zergatik) automatizatu eta hurrengoan zure CI/CD kanalizazioan sartzeari buruz hitz egingo dugu.

Iturria: www.habr.com

Gehitu iruzkin berria