SQL, kas gali būti paprasčiau? Kiekvienas iš mūsų gali parašyti paprastą užklausą – spausdiname pasirinkti, išvardykite reikiamus stulpelius, tada nuo, lentelės pavadinimas, kai kurios sąlygos kur ir viskas – naudingi duomenys yra mūsų kišenėje ir (beveik) nepriklausomai nuo to, kuri DBVS tuo metu yra po gaubtu (o gal
Ir pradėkime nuo pat
Objektų ir santykių kartografavimas
ORM šalininkai tradiciškai vertina greitį ir kūrimo lengvumą, nepriklausomybę nuo DBVS ir švarų kodą. Daugeliui iš mūsų darbo su duomenų baze (o dažnai ir pačia duomenų baze) kodas
dažniausiai atrodo maždaug taip...
@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;
}
...
Modelis pakabintas su protingomis anotacijomis, o kažkur užkulisiuose narsus ORM generuoja ir vykdo daugybę SQL kodų. Beje, kūrėjai visomis išgalėmis stengiasi atsiriboti nuo savo duomenų bazės su kilometrais abstrakcijų, o tai rodo,
Kitoje barikadų pusėje gryno „rankų darbo“ SQL šalininkai pastebi galimybę išspausti visas sultis iš savo DBVS be papildomų sluoksnių ir abstrakcijų. Dėl to atsiranda „į duomenis orientuoti“ projektai, kur į duomenų bazę įtraukiami specialiai apmokyti žmonės (jie irgi „bazistai“, taip pat „bazistai“, taip pat „basdeneriai“ ir t. t.), kūrėjai. belieka „ištraukti“ jau paruoštus vaizdus ir saugomas procedūras, nesigilinant į smulkmenas.
O kas, jei turėtume geriausią iš abiejų pasaulių? Kaip tai daroma nuostabiame įrankyje gyvybę patvirtinančiu pavadinimu
„Clojure“ yra puiki DSL kūrimo kalba, tačiau pats SQL yra puikus DSL ir mums nereikia kitos. S-išraiškos puikios, bet čia nieko naujo neprideda. Dėl to skliausteliuose gauname skliaustus. Nesutikti? Tada palaukite momento, kai pradės nutekėti duomenų bazės abstrakcija ir pradėsite kovoti su funkcija (raw-sql)
Taigi ką turėčiau daryti? Palikime SQL kaip įprastą SQL – po vieną failą užklausoje:
-- name: users-by-country
select *
from users
where country_code = :country_code
... ir tada perskaitykite šį failą, paversdami jį įprasta Clojure funkcija:
(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" ...} ...)
Laikydamiesi principo „SQL pats, Clojure pats“ gaunate:
- Jokių sintaksinių netikėtumų. Jūsų duomenų bazė (kaip ir bet kuri kita) nėra 100% suderinama su SQL standartu, tačiau tai neturi reikšmės Yesql. Niekada negaišite laiko ieškodami funkcijų su SQL lygiaverte sintaksė. Jums niekada nereikės grįžti prie funkcijos (raw-sql "some('funky'::SYNTAX)")).
- Geriausias redaktoriaus palaikymas. Jūsų redaktorius jau turi puikų SQL palaikymą. Išsaugoję SQL kaip SQL, galite tiesiog jį naudoti.
- Komandos suderinamumas. Jūsų DBA gali skaityti ir rašyti SQL, kurį naudojate savo Clojure projekte.
- Lengvesnis našumo derinimas. Reikia sudaryti probleminės užklausos planą? Tai nėra problema, kai jūsų užklausa yra įprasta SQL.
- Pakartotinis užklausų naudojimas. Nuvilkite tuos pačius SQL failus į kitus projektus, nes tai tiesiog senas SQL – tiesiog pasidalykite juo.
Mano nuomone, idėja yra labai šauni ir tuo pačiu labai paprasta, kurios dėka projektas įgijo daug
IDE ir DB vadovai
Pradėkime nuo paprastos kasdienės užduoties. Dažnai duomenų bazėje tenka ieškoti kai kurių objektų, pavyzdžiui, schemoje rasti lentelę ir ištirti jos struktūrą (kokie stulpeliai, raktai, indeksai, apribojimai ir pan. naudojami). Ir iš bet kurios grafinės IDE ar mažos DB tvarkyklės pirmiausia tikimės būtent tokių gebėjimų. Kad būtų greita ir nereikėtų laukti pusvalandžio, kol bus nubraižytas langas su reikiama informacija (ypač lėtai prisijungus prie nuotolinės duomenų bazės), o tuo pačiu gaunama informacija būtų šviežia ir aktuali, o ne talpykloje saugomo šlamšto. Be to, kuo sudėtingesnė ir didesnė duomenų bazė ir kuo didesnis jų skaičius, tuo sunkiau tai padaryti.
Bet dažniausiai išmetu pelę ir tiesiog rašau kodą. Tarkime, kad reikia išsiaiškinti, kurios lentelės (ir su kokiomis savybėmis) yra „HR“ schemoje. Daugumoje DBVS norimą rezultatą galima pasiekti naudojant šią paprastą užklausą iš information_schema:
select table_name
, ...
from information_schema.tables
where schema = 'HR'
Nuo duomenų bazės iki duomenų bazės tokių nuorodų lentelių turinys skiriasi priklausomai nuo kiekvienos DBVS galimybių. Ir, pavyzdžiui, MySQL, iš tos pačios žinyno galite gauti šiai DBVS būdingus lentelės parametrus:
select table_name
, storage_engine -- Используемый "движок" ("MyISAM", "InnoDB" etc)
, row_format -- Формат строки ("Fixed", "Dynamic" etc)
, ...
from information_schema.tables
where schema = 'HR'
Oracle nežino information_schema, bet žino
select table_name
, pct_free -- Минимум свободного места в блоке данных (%)
, pct_used -- Минимум используемого места в блоке данных (%)
, last_analyzed -- Дата последнего сбора статистики
, ...
from all_tables
where owner = 'HR'
ClickHouse nėra išimtis:
select name
, engine -- Используемый "движок" ("MergeTree", "Dictionary" etc)
, ...
from system.tables
where database = 'HR'
Kažką panašaus galima padaryti naudojant „Cassandra“ (kurioje vietoj lentelių yra stulpelių šeimos, o vietoj schemų – klavišų tarpai):
select columnfamily_name
, compaction_strategy_class -- Стратегия сборки мусора
, gc_grace_seconds -- Время жизни мусора
, ...
from system.schema_columnfamilies
where keyspace_name = 'HR'
Daugumoje kitų duomenų bazių taip pat galite pateikti panašias užklausas (net Mongo turi
Žinoma, tokiu būdu galite gauti informacijos ne tik apie lenteles, bet apskritai apie bet kokį objektą. Kartkartėmis malonūs žmonės dalijasi tokiu skirtingų duomenų bazių kodu, kaip, pavyzdžiui, habra straipsnių serijoje „PostgreSQL duomenų bazių dokumentavimo funkcijos“ (
Dėl to šis naršymo ir objektų paieškos būdas yra daug lankstesnis, sutaupo daug laiko ir leidžia gauti būtent tokią informaciją, kokia ji dabar reikalinga (kaip, pavyzdžiui, aprašyta įraše
Operacijos su objektais
Radę ir ištyrę reikalingus objektus, laikas su jais nuveikti ką nors naudingo. Natūralu, taip pat neatitraukiant pirštų nuo klaviatūros.
Ne paslaptis, kad tiesiog ištrynus lentelę beveik visose duomenų bazėse atrodys vienodai:
drop table hr.persons
Tačiau sukūrus lentelę tampa įdomiau. Beveik bet kuri DBVS (įskaitant daugelį NoSQL) gali „sukurti lentelę“ viena ar kita forma, o pagrindinė jos dalis net šiek tiek skirsis (pavadinimas, stulpelių sąrašas, duomenų tipai), tačiau kitos detalės gali labai skirtis ir priklausyti nuo vidinis įrenginys ir konkrečios DBVS galimybės. Mano mėgstamiausias pavyzdys yra tas, kad „Oracle“ dokumentacijoje yra tik „nuogi“ BNF „sukurti lentelę“ sintaksei.
Be to, daugelis DBVS turi savo specifinius objektų tipus, kurių nėra kitose DBVS. Be to, galime atlikti operacijas ne tik su duomenų bazės objektais, bet ir su pačia DBVS, pavyzdžiui, „nužudyti“ procesą, atlaisvinti dalį atminties, įjungti sekimą, perjungti į „tik skaitymo“ režimą ir dar daugiau.
Dabar šiek tiek pieškime
Viena iš dažniausiai atliekamų užduočių yra sukurti diagramą su duomenų bazės objektais ir pamatyti objektus bei jų ryšius gražiame paveikslėlyje. Tai gali padaryti beveik bet kuri grafinė IDE, atskiros „komandinės eilutės“ paslaugos, specializuoti grafiniai įrankiai ir modeliuotojai. Jie nupieš ką nors už jus „kiek gali“, o jūs galite šiek tiek paveikti šį procesą tik naudodami kelis parametrus konfigūracijos faile arba sąsajos žymimuosius laukelius.
Tačiau šią problemą galima išspręsti daug paprasčiau, lanksčiau ir elegantiškiau, ir, žinoma, naudojant kodą. Norėdami sukurti bet kokio sudėtingumo diagramas, turime keletą specializuotų žymėjimo kalbų (DOT, GraphML ir kt.) ir joms daugybę programų (GraphViz, PlantUML, Mermaid), kurios gali skaityti tokias instrukcijas ir vizualizuoti jas įvairiais formatais. . Na, mes jau žinome, kaip gauti informacijos apie objektus ir ryšius tarp jų.
Štai mažas pavyzdys, kaip tai galėtų atrodyti naudojant PlantUML ir
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'
Ir jei šiek tiek pabandysi, tada remiantis
SQL užklausa yra šiek tiek sudėtingesnė
-- Шапка
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'
Jei atidžiai pažvelgsite, daugelis vizualizacijos įrankių po gaubtu taip pat naudoja panašias užklausas. Tiesa, šie prašymai dažniausiai būna gilūs
Metrika ir stebėjimas
Pereikime prie tradiciškai sudėtingos temos – duomenų bazės veikimo stebėjimo. Prisimenu nedidelę tikrą istoriją, kurią man papasakojo „vienas iš mano draugų“. Kitame projekte gyveno tam tikras galingas DBA, ir tik nedaugelis kūrėjų jį pažinojo asmeniškai arba kada nors buvo jį matę (nepaisant to, kad, remiantis gandais, jis dirbo kažkur kitame pastate). „X“ valandą, kai didelio mažmenininko podukcijos sistema vėl pradėjo „blogai jaustis“, jis tyliai išsiuntė „Oracle Enterprise Manager“ grafikų ekrano kopijas, kuriose raudonu „suprantamumo“ žymekliu kruopščiai paryškino svarbiausias vietas ( tai, švelniai tariant, nelabai padėjo). Ir pagal šią „nuotraukų kortelę“ turėjau gydytis. Tuo pačiu metu niekas neturėjo prieigos prie brangaus (abiem šio žodžio prasmėmis) įmonės vadovo, nes sistema yra sudėtinga ir brangi, staiga „kūrėjai ant kažko suklumpa ir viską sulaužo“. Todėl kūrėjai „empiriškai“ surado stabdžių vietą ir priežastį bei išleido pleistrą. Jei grėsmingas laiškas iš DBA artimiausiu metu vėl nepasiektų, tada visi lengviau atsikvėptų ir grįžtų prie savo dabartinių užduočių (iki naujo Laiško).
Tačiau stebėjimo procesas gali atrodyti linksmesnis ir draugiškesnis, o svarbiausia – visiems prieinamas ir skaidrus. Bent jau pagrindinė jo dalis, kaip priedas prie pagrindinių stebėjimo sistemų (kurios tikrai naudingos ir daugeliu atvejų nepakeičiamos). Bet kuri DBVS gali laisvai ir visiškai nemokamai dalytis informacija apie dabartinę jos būseną ir veikimą. Toje pačioje „kruvinoje“ Oracle DB iš sistemos rodinių galima gauti beveik bet kokią informaciją apie našumą, pradedant nuo procesų ir seansų iki buferio talpyklos būsenos (pvz.,
Taigi, apsiginklavę tam tikru metrikų rinktuvu (Telegraf, Metricbeat, Collectd), galinčiu atlikti pasirinktines sql užklausas, šios metrikos saugyklą (InfluxDB, Elasticsearch, Timescaledb) ir vizualizatorių (Grafana, Kibana), galite gauti gana nesunkiai. ir lanksti stebėjimo sistema, kuri bus glaudžiai integruota su kitomis visos sistemos metrikomis (gaunama, pavyzdžiui, iš programų serverio, iš OS ir pan.). Kaip, pavyzdžiui, tai daroma pgwatch2, kuris naudoja InfluxDB + Grafana derinį ir užklausų rinkinį sistemos rodiniams, kuriuos taip pat galima pasiekti
Iš viso
Ir tai tik apytikslis sąrašas, ką galima padaryti su mūsų duomenų baze naudojant įprastą SQL kodą. Esu tikras, kad rasite daug daugiau naudojimo būdų, parašykite komentaruose. Ir mes kalbėsime apie tai, kaip (ir, svarbiausia, kodėl) visa tai automatizuoti ir įtraukti į savo CI/CD konvejerį kitą kartą.
Šaltinis: www.habr.com