SQL, wat kin ienfâldiger wêze? Elk fan ús kin in ienfâldich fersyk skriuwe - wy typen útkieze, list de fereaske kolommen, dan fan, tabel namme, guon betingsten yn wêr en dat is alles - nuttige gegevens binne yn ús bûse, en (hast) nettsjinsteande hokker DBMS op dat stuit ûnder de motorkap is (of miskien
En lit ús begjinne rjocht fan
Objekt-relasjonele mapping
ORM-supporters wurdearje tradisjoneel snelheid en gemak fan ûntwikkeling, ûnôfhinklikens fan 'e DBMS en skjinne koade. Foar in protte fan ús is de koade foar it wurkjen mei de databank (en faaks de databank sels)
it sjocht der meastentiids sa út...
@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;
}
...
It model wurdt ophongen mei tûke annotaasjes, en earne efter de skermen genereart en útfiert in dappere ORM tonnen wat SQL-koade. Trouwens, ûntwikkelders besykje har bêst om harsels te isolearjen fan har database mei kilometers oan abstraksjes, wat oanjout op guon
Oan 'e oare kant fan' e barrikaden notearje oanhingers fan suver "hânmakke" SQL de mooglikheid om al it sap út har DBMS te drukken sûnder ekstra lagen en abstraksjes. Dêrtroch ferskine "data-sintraal" projekten, wêrby't spesjaal oplaat minsken belutsen binne by de databank (se binne ek "basicists", se binne ek "basicists", se binne ek "basdeners", ensfh.), En de ûntwikkelders allinne moatte "lûke" de klear makke werjeften en opslein prosedueres, sûnder yn te gean yn details.
Wat as wy it bêste fan beide wrâlden hiene? Hoe dit wurdt dien yn in prachtich ark mei in libben-befêstigjende namme
Clojure is in koele taal foar it meitsjen fan DSLs, mar SQL sels is in koele DSL, en wy hawwe net nedich in oar. S-útdrukkingen binne geweldich, mar se foegje hjir neat nij ta. As gefolch krije wy heakjes om 'e heakjes. Net mei iens? Wachtsje dan op it momint dat de abstraksje oer de databank begjint te lekken en jo begjinne te fjochtsjen mei de funksje (raw-sql)
Dus wat moat ik dwaan? Litte wy SQL litte as gewoane SQL - ien bestân per fersyk:
-- name: users-by-country
select *
from users
where country_code = :country_code
... en lês dan dit bestân, en feroaret it yn in gewoane Clojure-funksje:
(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" ...} ...)
Troch te folgjen oan it prinsipe "SQL troch himsels, Clojure troch himsels", krije jo:
- Gjin syntaktyske ferrassingen. Jo databank (lykas elke oare) is net 100% konform mei de SQL-standert - mar dit makket neat út foar Yesql. Jo sille noait tiid fergrieme op jacht nei funksjes mei SQL-lykweardige syntaksis. Jo sille nea hoege werom nei in funksje (raw-sql "some('funky'::SYNTAX)")).
- Bêste bewurker stipe. Jo bewurker hat al poerbêste SQL-stipe. Troch SQL te bewarjen as SQL kinne jo it gewoan brûke.
- Team komptabiliteit. Jo DBA's kinne de SQL lêze en skriuwe dy't jo brûke yn jo Clojure-projekt.
- Makliker prestaasje tuning. Moatte in plan bouwe foar in problematyske fraach? Dit is gjin probleem as jo query gewoane SQL is.
- Opnij brûke queries. Sleep en drop deselde SQL-bestannen yn oare projekten, om't it gewoan âlde SQL is - diel it gewoan.
Yn myn miening is it idee heul cool en tagelyk heul ienfâldich, wêrtroch't it projekt in protte opdien hat
IDE & DB behearders
Litte wy begjinne mei in ienfâldige deistige taak. Faak moatte wy sykje foar guon objekten yn 'e databank, bygelyks, fine in tabel yn it skema en studearje syn struktuer (wat kolommen, kaaien, yndeksen, beheinings, ensfh wurde brûkt). En fan elke grafyske IDE as in bytsje DB-manager ferwachtsje wy earst dizze kapasiteiten. Sadat it fluch is en jo net in healoere hoege te wachtsjen oant in finster mei de nedige ynformaasje tekene wurdt (benammen mei in trage ferbining mei in databank op ôfstân), en tagelyk de ûntfongen ynformaasje fris en relevant is, en net cache junk. Boppedat, hoe komplekser en grutter de databank en hoe grutter it oantal, hoe dreger it is om dit te dwaan.
Mar meastal smyt ik de mûs fuort en skriuw gewoan koade. Litte wy sizze dat jo moatte útfine hokker tabellen (en mei hokker eigenskippen) binne befette yn it "HR" skema. Yn 'e measte DBMS's kin it winske resultaat berikt wurde mei dizze ienfâldige query fan information_schema:
select table_name
, ...
from information_schema.tables
where schema = 'HR'
Fan databank nei databank ferskilt de ynhâld fan sokke referinsjetabellen ôfhinklik fan de mooglikheden fan elke DBMS. En, bygelyks, foar MySQL, út itselde referinsjeboek kinne jo tabelparameters krije spesifyk foar dit DBMS:
select table_name
, storage_engine -- Используемый "движок" ("MyISAM", "InnoDB" etc)
, row_format -- Формат строки ("Fixed", "Dynamic" etc)
, ...
from information_schema.tables
where schema = 'HR'
Oracle wit net information_schema, mar it hat
select table_name
, pct_free -- Минимум свободного места в блоке данных (%)
, pct_used -- Минимум используемого места в блоке данных (%)
, last_analyzed -- Дата последнего сбора статистики
, ...
from all_tables
where owner = 'HR'
ClickHouse is gjin útsûndering:
select name
, engine -- Используемый "движок" ("MergeTree", "Dictionary" etc)
, ...
from system.tables
where database = 'HR'
Iets fergelykber kin dien wurde yn Cassandra (dy't kolomfamyljes hat ynstee fan tabellen en kaaispaasjes ynstee fan skema's):
select columnfamily_name
, compaction_strategy_class -- Стратегия сборки мусора
, gc_grace_seconds -- Время жизни мусора
, ...
from system.schema_columnfamilies
where keyspace_name = 'HR'
Foar de measte oare databases kinne jo ek mei ferlykbere fragen komme (sels Mongo hat
Fansels kinne jo op dizze manier ynformaasje krije net allinich oer tabellen, mar oer elk objekt yn 't algemien. Fan tiid ta tiid diele freonlike minsken sokke koade foar ferskate databases, lykas, bygelyks, yn 'e searje fan habra-artikels "Funksjes foar it dokumintearjen fan PostgreSQL-databases" (
As resultaat is dizze metoade foar it navigearjen en sykjen nei objekten folle fleksibeler, besparret in protte tiid, en lit jo krekt de ynformaasje krije yn 'e foarm wêryn't it no nedich is (lykas bygelyks beskreaun yn 'e post
Operaasje mei objekten
Nei't wy de nedige objekten hawwe fûn en studearre, is it tiid om der wat nuttichs mei te dwaan. Fansels, ek sûnder jo fingers fan it toetseboerd te heljen.
It is gjin geheime dat it gewoan wiskjen fan in tabel itselde sil sjen yn hast alle databases:
drop table hr.persons
Mar mei it meitsjen fan 'e tafel wurdt it nijsgjirriger. Hast elke DBMS (ynklusyf in protte NoSQL) kin "tabel oanmeitsje" yn ien of oare foarm, en it haaddiel dêrfan sil sels in bytsje ferskille (namme, list mei kolommen, gegevenstypen), mar oare details kinne dramatysk ferskille en ôfhingje fan 'e ynterne apparaat en mooglikheden fan in spesifike DBMS. Myn favorite foarbyld is dat yn 'e Oracle-dokumintaasje d'r allinich "neaken" BNF's binne foar de syntaksis "tabel oanmeitsje"
Ek hawwe in protte DBMS's har eigen spesifike soarten objekten dy't net beskikber binne yn oare DBMS's. Boppedat kinne wy operaasjes net allinich útfiere op databankobjekten, mar ek op 'e DBMS sels, bygelyks in proses "deadzje", wat ûnthâldgebiet frijmeitsje, tracing ynskeakelje, oerskeakelje nei "allinich lêze" modus, en folle mear.
No litte wy in bytsje tekenje
Ien fan 'e meast foarkommende taken is om in diagram te bouwen mei databankobjekten en de objekten en ferbiningen tusken har te sjen yn in prachtige foto. Hast elke grafyske IDE, aparte "kommandoline" nutsbedriuwen, spesjalisearre grafyske ark en modelers kinne dit dwaan. Se sille wat foar jo tekenje "sa goed as se kinne", en jo kinne dit proses in bytsje beynfloedzje allinich mei help fan in pear parameters yn it konfiguraasjetriem of karfakjes yn 'e ynterface.
Mar dit probleem kin oplost wurde folle ienfâldiger, fleksibeler en elegant, en fansels mei help fan koade. Om diagrammen fan elke kompleksiteit te meitsjen, hawwe wy ferskate spesjalisearre opmaaktalen (DOT, GraphML ensfh), en foar har in heule fersprieding fan applikaasjes (GraphViz, PlantUML, Mermaid) dy't sokke ynstruksjes kinne lêze en visualisearje yn in ferskaat oan formaten . No, wy witte al hoe't jo ynformaasje kinne krije oer objekten en ferbiningen tusken har.
Hjir is in lyts foarbyld fan hoe't dit der útsjen kin, mei PlantUML en
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'
En as jo besykje in bytsje, dan basearre op
De SQL-query is in bytsje komplisearre
-- Шапка
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'
As jo nau sjogge, brûke in protte fisualisaasjeark ûnder de kap ek ferlykbere fragen. Wier, dizze oanfragen binne meastal djip
Metriken en tafersjoch
Litte wy trochgean nei in tradisjoneel kompleks ûnderwerp - monitoring fan databankprestaasjes. Ik herinner my in lyts wier ferhaal dat my ferteld waard troch "ien fan myn freonen." Op in oar projekt wenne in bepaalde krêftige DBA, en in pear fan 'e ûntwikkelders wisten him persoanlik, of hienen him oait persoanlik sjoen (nettsjinsteande it feit dat hy, neffens geroften, earne yn it folgjende gebou wurke). Op oere "X", doe't it poduksjesysteem fan in grutte retailer opnij begon te "min te fielen", stjoerde hy stil skermôfbyldings fan grafiken fan Oracle Enterprise Manager, wêrop hy krityske plakken foarsichtich markearre mei in reade marker foar "begryplikens" ( dit, om it myld te sizzen, hat net folle holpen). En op basis fan dizze "fotokaart" moast ik behannelje. Tagelyk hie gjinien tagong ta de kostbere (yn beide betsjuttingen fan it wurd) Enterprise Manager, om't it systeem is kompleks en djoer, ynienen "de ûntwikkelders stroffelje oer wat en brekke alles." Dêrom hawwe de ûntwikkelders "empirysk" de lokaasje en oarsaak fan 'e remmen fûn en in patch frijlitten. As de driigjende brief fan de DBA yn de heine takomst net wer oankaam, dan soe elkenien in suchtsje fan opluchting sykhelje en weromgean nei har hjoeddeistige taken (oant de nije Brief).
Mar it tafersjochproses kin leuker en freonliker útsjen, en it wichtichste, tagonklik en transparant foar elkenien. Op syn minst it basisdiel, as tafoeging oan 'e wichtichste monitoaringssystemen (dy't wis nuttich binne en yn in protte gefallen ûnferfangber binne). Elke DBMS is frij en absolút fergees om ynformaasje te dielen oer syn hjoeddeistige steat en prestaasjes. Yn deselde "bloedige" Oracle DB kin hast alle ynformaasje oer prestaasjes wurde krigen fan systeemwerjeften, fariearjend fan prosessen en sesjes oant de tastân fan 'e buffer-cache (bygelyks,
Sa kinne jo, bewapene mei in soarte fan metriken-samler (Telegraf, Metricbeat, Collectd) dy't oanpaste sql-fragen kinne útfiere, in opslach fan dizze metriken (InfluxDB, Elasticsearch, Timescaledb) en in visualizer (Grafana, Kibana), kinne jo in frij maklik krije en in fleksibele monitoaring systeem dat sil wurde nau yntegrearre mei oare systeem-wide metriken (ferkrigen, bygelyks, fan de applikaasje tsjinner, út it OS, ensfh). As, bygelyks, dit wurdt dien yn pgwatch2, dy't de kombinaasje InfluxDB + Grafana brûkt en in set fan queries nei systeemwerjeften, dy't ek tagonklik binne
Totaal
En dit is mar in ûngefear list fan wat kin wurde dien mei ús databank mei help fan reguliere SQL-koade. Ik bin der wis fan dat jo in protte mear gebrûk kinne fine, skriuw yn 'e kommentaren. En wy sille prate oer hoe (en it wichtichste wêrom) dit alles automatisearje en it folgjende kear yn jo CI / CD-pipeline opnimme.
Boarne: www.habr.com