SQL, mikä voisi olla yksinkertaisempaa? Jokainen meistä voi kirjoittaa yksinkertaisen pyynnön - me kirjoitamme valita, luettele sitten tarvittavat sarakkeet alkaen, taulukon nimi, joitain ehtoja jossa ja siinä kaikki - hyödyllistä dataa on taskussamme ja (melkein) riippumatta siitä mikä DBMS on konepellin alla tuolloin (tai ehkä
Ja aloitetaan heti
Objekti-relaatiokartoitus
ORM:n kannattajat arvostavat perinteisesti nopeutta ja helppoutta kehitystä, riippumattomuutta DBMS:stä ja puhdasta koodia. Monille meistä tietokannan (ja usein itse tietokannan) kanssa työskentelyn koodi
se näyttää yleensä tältä...
@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;
}
...
Malli on ripustettu älykkäillä huomautuksilla, ja jossain kulissien takana urhoollinen ORM luo ja suorittaa tonnia SQL-koodia. Muuten, kehittäjät yrittävät parhaansa mukaan eristää itsensä tietokannastaan kilometrien abstraktioilla, mikä viittaa
Barrikadien toisella puolella puhtaan "käsintehdyn" SQL:n kannattajat huomaavat kykynsä puristaa kaikki mehu pois DBMS-järjestelmästään ilman ylimääräisiä kerroksia ja abstraktioita. Tuloksena syntyy "tietokeskeisiä" projekteja, joissa tietokantaan ovat mukana erikoiskoulutetut ihmiset (he ovat myös "perusmiehiä", he ovat myös "perusaattoreita", he ovat myös "basdenereita" jne.) ja kehittäjät. tarvitsee vain "vetää" valmiit näkemykset ja tallennetut menettelyt yksityiskohtiin menemättä.
Mitä jos meillä olisi molempien maailmojen parhaat puolet? Kuinka tämä tehdään upealla työkalulla, jolla on elämää vahvistava nimi
Clojure on hieno kieli DSL:ien luomiseen, mutta SQL itsessään on hieno DSL, emmekä tarvitse toista. S-lausekkeet ovat hienoja, mutta ne eivät lisää tähän mitään uutta. Seurauksena on, että saamme kiinnikkeet kiinnikkeiden vuoksi. Ei ole samaa mieltä? Odota sitten hetkeä, jolloin tietokannan ylittävä abstraktio alkaa vuotaa ja alat taistella funktion kanssa (raw-sql)
Eli mitä minun pitäisi tehdä? Jätetään SQL tavalliseksi SQL:ksi - yksi tiedosto per pyyntö:
-- name: users-by-country
select *
from users
where country_code = :country_code
... ja lue sitten tämä tiedosto muuttamalla se tavalliseksi Clojure-funktioksi:
(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" ...} ...)
Noudattamalla "SQL itsessään, Clojure itsessään" -periaatetta saat:
- Ei syntaktisia yllätyksiä. Tietokantasi (kuten mikään muu) ei ole 100% SQL-standardin mukainen - mutta tällä ei ole merkitystä Yesql:lle. Et koskaan tuhlaa aikaa SQL-vastaavan syntaksin funktioiden metsästämiseen. Sinun ei koskaan tarvitse palata toimintoon (raw-sql "some('funky'::SYNTAX)")).
- Paras editorin tuki. Editorillasi on jo erinomainen SQL-tuki. Tallentamalla SQL:n SQL:nä voit yksinkertaisesti käyttää sitä.
- Joukkueen yhteensopivuus. DBA:si voivat lukea ja kirjoittaa SQL:ää, jota käytät Clojure-projektissasi.
- Helpompi suorituskyvyn viritys. Tarvitsetko suunnitelman ongelmallista kyselyä varten? Tämä ei ole ongelma, kun kyselysi on tavallinen SQL.
- Kyselyjen uudelleenkäyttö. Vedä ja pudota samat SQL-tiedostot muihin projekteihin, koska se on pelkkä vanha SQL - jaa se.
Minusta idea on erittäin siisti ja samalla hyvin yksinkertainen, minkä ansiosta projekti on saanut paljon
IDE- ja DB-päälliköt
Aloitetaan yksinkertaisesta jokapäiväisestä tehtävästä. Usein joudumme etsimään tietokannasta joitain objekteja, esimerkiksi etsimään kaaviosta taulukon ja tutkimaan sen rakennetta (mitä sarakkeita, avaimia, indeksejä, rajoitteita jne. käytetään). Ja miltä tahansa graafiselta IDE:ltä tai pieneltä DB-managerilta odotamme ensinnäkin juuri näitä kykyjä. Jotta se on nopeaa ja sinun ei tarvitse odottaa puolta tuntia, kunnes tarvittavat tiedot on piirretty (etenkin jos yhteys on hidas etätietokantaan), ja samalla vastaanotettu tieto on tuoretta ja relevanttia, eikä välimuistissa olevaa roskaa. Lisäksi mitä monimutkaisempi ja suurempi tietokanta ja mitä enemmän niitä on, sitä vaikeampaa se on tehdä.
Mutta yleensä heitän hiiren pois ja kirjoitan vain koodin. Oletetaan, että sinun on selvitettävä, mitkä taulukot (ja millä ominaisuuksilla) sisältyvät "HR"-skeemaan. Useimmissa DBMS-järjestelmissä haluttu tulos voidaan saavuttaa tällä yksinkertaisella kyselyllä information_schema:
select table_name
, ...
from information_schema.tables
where schema = 'HR'
Tietokannasta tietokantaan tällaisten viitetaulukoiden sisältö vaihtelee kunkin DBMS:n ominaisuuksien mukaan. Ja esimerkiksi MySQL:lle, samasta hakuteoksesta saat tälle tietokantajärjestelmälle ominaiset taulukkoparametrit:
select table_name
, storage_engine -- Используемый "движок" ("MyISAM", "InnoDB" etc)
, row_format -- Формат строки ("Fixed", "Dynamic" etc)
, ...
from information_schema.tables
where schema = 'HR'
Oracle ei tunne information_schemaa, mutta se tietää
select table_name
, pct_free -- Минимум свободного места в блоке данных (%)
, pct_used -- Минимум используемого места в блоке данных (%)
, last_analyzed -- Дата последнего сбора статистики
, ...
from all_tables
where owner = 'HR'
ClickHouse ei ole poikkeus:
select name
, engine -- Используемый "движок" ("MergeTree", "Dictionary" etc)
, ...
from system.tables
where database = 'HR'
Jotain vastaavaa voidaan tehdä Cassandrassa (jossa on sarakeperheet taulukoiden sijaan ja avainvälit skeemojen sijaan):
select columnfamily_name
, compaction_strategy_class -- Стратегия сборки мусора
, gc_grace_seconds -- Время жизни мусора
, ...
from system.schema_columnfamilies
where keyspace_name = 'HR'
Useimmille muille tietokannoille voit myös keksiä samanlaisia kyselyitä (jopa Mongolla on
Tietenkin tällä tavalla voit saada tietoa ei vain taulukoista, vaan mistä tahansa objektista yleensä. Ajoittain ystävälliset ihmiset jakavat tällaista koodia eri tietokantoihin, kuten esimerkiksi habra-artikkelisarjassa "PostgreSQL-tietokantojen dokumentointitoiminnot" (
Tämän seurauksena tämä tapa navigoida ja etsiä kohteita on paljon joustavampi, säästää paljon aikaa ja antaa sinun saada tarkalleen tiedot siinä muodossa, jossa ne nyt ovat tarpeen (kuten esimerkiksi viestissä on kuvattu
Toiminnot esineiden kanssa
Kun olemme löytäneet ja tutkineet tarvittavat esineet, on aika tehdä niille jotain hyödyllistä. Luonnollisesti myös ilman sormia näppäimistöltä.
Ei ole mikään salaisuus, että pelkkä taulukon poistaminen näyttää samalta lähes kaikissa tietokannoista:
drop table hr.persons
Mutta taulukon luomisen myötä siitä tulee mielenkiintoisempaa. Melkein mikä tahansa DBMS (mukaan lukien monet NoSQL:t) voi "luoda taulukon" muodossa tai toisessa, ja suurin osa siitä eroaa jopa hieman (nimi, sarakeluettelo, tietotyypit), mutta muut yksityiskohdat voivat vaihdella dramaattisesti ja riippua sisäinen laite ja tietyn DBMS:n ominaisuudet. Suosikkiesimerkkini on, että Oraclen dokumentaatiossa on vain "alasti" BNF:t "luo taulukko" -syntaksille.
Lisäksi monilla DBMS-järjestelmillä on omat tietyntyyppiset objektinsa, joita ei ole saatavilla muissa DBMS-järjestelmissä. Lisäksi voimme suorittaa toimintoja tietokantaobjektien lisäksi myös itse DBMS:lle, esimerkiksi "tappaa" prosessin, vapauttaa jonkin verran muistialuetta, ottaa käyttöön jäljityksen, vaihtaa "vain luku"-tilaan ja paljon muuta.
Piirretään nyt vähän
Yksi yleisimmistä tehtävistä on rakentaa kaavio tietokantaobjekteista ja nähdä objektit ja niiden väliset yhteydet kauniissa kuvassa. Lähes mikä tahansa graafinen IDE, erilliset "komentorivi"-apuohjelmat, erikoistuneet graafiset työkalut ja mallintajat voivat tehdä tämän. He piirtävät sinulle jotain "niin kuin pystyvät", ja voit vaikuttaa tähän prosessiin hieman vain muutaman parametrin avulla konfiguraatiotiedostossa tai käyttöliittymän valintaruuduilla.
Mutta tämä ongelma voidaan ratkaista paljon yksinkertaisemmin, joustavammin ja tyylikkäämmin, ja tietysti koodin avulla. Kaiken monimutkaisten kaavioiden luomiseksi meillä on useita erikoistuneita merkintäkieliä (DOT, GraphML jne.) ja niille koko joukko sovelluksia (GraphViz, PlantUML, Mermaid), jotka voivat lukea tällaisia ohjeita ja visualisoida ne useissa eri muodoissa. . Tiedämme jo, kuinka saada tietoa esineistä ja niiden välisistä yhteyksistä.
Tässä on pieni esimerkki siitä, miltä tämä voisi näyttää käyttämällä PlantUML- ja
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'
Ja jos yrität vähän, niin sen perusteella
SQL-kysely on hieman monimutkaisempi
-- Шапка
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'
Jos katsot tarkasti, monet visualisointityökalut käyttävät myös samanlaisia kyselyitä. Totta, nämä pyynnöt ovat yleensä syvällisiä
Mittarit ja seuranta
Siirrytään perinteisesti monimutkaiseen aiheeseen - tietokannan suorituskyvyn seurantaan. Muistan pienen tositarinan, jonka minulle kertoi "yksi ystäväni". Toisessa projektissa asui tietty voimakas DBA, ja harvat kehittäjät tunsivat hänet henkilökohtaisesti tai olivat koskaan nähneet häntä henkilökohtaisesti (huolimatta siitä, että hän työskenteli huhujen mukaan jossain viereisessä rakennuksessa). Tunnilla “X”, kun suuren jälleenmyyjän poduction-järjestelmä alkoi taas “tuntua pahalta”, hän lähetti hiljaa kuvakaappauksia kaavioista Oracle Enterprise Managerista, joissa hän korosti huolellisesti kriittiset paikat punaisella ”ymmärrettävyyden” merkillä ( tämä, lievästi sanottuna, ei auttanut paljon). Ja tämän "valokuvakortin" perusteella minun piti hoitaa. Samaan aikaan kenelläkään ei ollut pääsyä arvokkaaseen (sanan molemmissa merkityksissä) Enterprise Manageriin, koska järjestelmä on monimutkainen ja kallis, yhtäkkiä "kehittäjät kompastuvat johonkin ja rikkovat kaiken". Siksi kehittäjät löysivät "empiirisesti" jarrujen sijainnin ja syyn ja julkaisivat korjaustiedoston. Jos DBA:n uhkaava kirje ei saapuisi uudelleen lähitulevaisuudessa, niin kaikki henkäisivät helpotuksesta ja palaisivat nykyisiin tehtäviinsä (uuteen kirjeeseen asti).
Mutta seurantaprosessi voi näyttää hauskempaa ja ystävällisempää, ja mikä tärkeintä, kaikkien saatavilla ja läpinäkyvämpää. Ainakin sen perusosa, lisäyksenä tärkeimpiin valvontajärjestelmiin (jotka ovat varmasti hyödyllisiä ja monissa tapauksissa korvaamattomia). Mikä tahansa DBMS on vapaasti ja täysin maksuton jakaa tietoa sen nykyisestä tilasta ja suorituskyvystä. Samassa "verisessä" Oracle DB:ssä lähes kaikki tiedot suorituskyvystä voidaan saada järjestelmänäkymistä, prosesseista ja istunnoista puskurin välimuistin tilaan (esim.
Siten aseistettuna jonkinlaisella metriikkakerääjällä (Telegraf, Metricbeat, Collectd), joka pystyy suorittamaan mukautettuja sql-kyselyitä, näiden mittareiden tallennustilalla (InfluxDB, Elasticsearch, Timescaledb) ja visualisoijalla (Grafana, Kibana), voit saada melko helpon ja joustava seurantajärjestelmä, joka integroidaan tiiviisti muihin järjestelmän laajuisiin mittareihin (saatu esimerkiksi sovelluspalvelimelta, käyttöjärjestelmästä jne.). Kuten esimerkiksi, tämä tehdään pgwatch2:ssa, joka käyttää InfluxDB + Grafana -yhdistelmää ja kyselyjoukkoa järjestelmänäkymiin, joihin pääsee myös
Yhteensä
Ja tämä on vain likimääräinen luettelo siitä, mitä voidaan tehdä tietokannassamme käyttämällä tavallista SQL-koodia. Olen varma, että löydät monia muita käyttötapoja, kirjoita kommentteihin. Ja puhumme siitä, kuinka (ja mikä tärkeintä, miksi) automatisoida tämä kaikki ja sisällyttää se CI/CD-putkistoon seuraavan kerran.
Lähde: will.com