Pengalaman "Database minangka Kode".

Pengalaman "Database minangka Kode".

SQL, apa sing luwih gampang? Saben kita bisa nulis panjalukan sing prasaja - kita ngetik pilih, dhaptar kolom sing dibutuhake, banjur saka, jeneng tabel, sawetara kahanan ing ngendi lan iku kabeh - data migunani ana ing kanthong kita, lan (meh) preduli saka DBMS ing hood ing wektu iku (utawa mungkin dudu DBMS babar pisan). AkibatΓ©, nggarap meh kabeh sumber data (relasional lan ora kaya) bisa dianggep saka sudut pandang kode biasa (karo kabeh sing ditrapake - kontrol versi, review kode, analisis statis, autotes, lan kabeh). Lan iki ditrapake ora mung kanggo data dhewe, skema lan migrasi, nanging umume kanggo kabeh urip panyimpenan. Ing artikel iki kita bakal ngomong babagan tugas saben dina lan masalah nggarap macem-macem database ing lensa "database minangka kode".

Lan ayo miwiti langsung saka ORM. Perang pisanan saka jinis "SQL vs ORM" ditemokake maneh pra-Petrine Rus'.

Pemetaan obyek-relasional

Panyengkuyung ORM kanthi tradisional ngurmati kacepetan lan gampang pangembangan, kamardikan saka DBMS lan kode sing resik. Kanggo akeh kita, kode kanggo nggarap database (lan asring database dhewe)

biasane katon kaya iki ...

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

Model kasebut digantung kanthi anotasi sing cerdas, lan ing endi wae ing mburi adegan, ORM sing gagah nggawe lan nglakokake pirang-pirang kode SQL. Miturut cara, pangembang nyoba sing paling apik kanggo ngisolasi awake dhewe saka database kanthi kilometer abstraksi, sing nuduhake sawetara "SQL sengit".

Ing sisih liya saka barricades, penganut murni "gawean tangan" SQL nyathet kemampuan kanggo remet kabeh jus metu saka DBMS sing tanpa lapisan tambahan lan abstraksi. Akibaté, proyèk "data-sentris" katon, ing ngendi wong sing dilatih khusus melu database (uga "basicists", uga "basicists", uga "basdeners", lan liya-liyane), lan pangembang. mung kudu "narik" tampilan sing wis siyap lan prosedur sing disimpen, tanpa mlebu rincian.

Apa yen kita duwe sing paling apik ing donya? Carane iki rampung ing alat apik banget karo jeneng-affirming urip Yesql. Aku bakal menehi sawetara baris saka konsep umum ing terjemahan gratis, lan sampeyan bisa ngerti kanthi luwih rinci. kene.

Clojure punika basa kelangan kanggo nggawe DSLs, nanging SQL dhewe DSL kelangan, lan kita ora perlu liyane. S-ekspresi gedhe, nanging ora nambah apa-apa anyar ing kene. AkibatΓ©, kita njaluk kurung kanggo kepentingan kurung. Ora setuju? Banjur ngenteni wayahe nalika abstraksi liwat database wiwit bocor lan sampeyan miwiti gelut karo fungsi (raw-sql)

Dadi apa sing kudu daklakoni? Ayo ninggalake SQL minangka SQL biasa - siji file saben panyuwunan:

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

... banjur waca file iki, ngowahi dadi fungsi Clojure biasa:

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

Kanthi netepi prinsip "SQL dhewe, Clojure dhewe", sampeyan entuk:

  • Ora ana kejutan sintaksis. Database sampeyan (kaya liyane) ora 100% tundhuk karo standar SQL - nanging iki ora masalah kanggo Yesql. Sampeyan ora bakal mbuwang wektu mburu fungsi kanthi sintaks sing padha karo SQL. Sampeyan ora bakal kudu bali menyang fungsi (raw-sql "sawetara ('funky'::SYNTAX)")).
  • Dhukungan editor paling apik. Editor sampeyan wis duwe dhukungan SQL sing apik banget. Kanthi nyimpen SQL minangka SQL sampeyan mung bisa nggunakake.
  • Kompatibilitas tim. DBA sampeyan bisa maca lan nulis SQL sing digunakake ing proyek Clojure.
  • Tuning kinerja luwih gampang. Apa sampeyan kudu nggawe rencana kanggo pitakon masalah? Iki ora dadi masalah nalika pitakon sampeyan yaiku SQL biasa.
  • Nganggo maneh pitakon. Seret lan selehake file SQL sing padha menyang proyek liyane amarga mung SQL lawas - mung nuduhake.

Ing mratelakake panemume, idea banget kelangan lan ing wektu sing padha banget prasaja, thanks kanggo kang project wis gained akeh pandherekipun ing macem-macem basa. Lan sabanjure kita bakal nyoba kanggo aplikasi filosofi padha misahake kode SQL saka kabeh liya adoh ngluwihi ORM.

Manajer IDE & DB

Ayo dadi miwiti karo tugas saben dinten prasaja. Asring kita kudu nggoleki sawetara obyek ing basis data, contone, golek tabel ing skema lan sinau strukture (kolom, tombol, indeks, kendala, lan liya-liyane). Lan saka sembarang IDE grafis utawa DB-manager sethitik, pisanan kabeh, kita nyana persis kabisan iki. Supaya cepet lan sampeyan ora kudu ngenteni setengah jam nganti jendhela kanthi informasi sing dibutuhake ditarik (utamane kanthi sambungan alon menyang database remot), lan ing wektu sing padha, informasi sing ditampa seger lan relevan, lan ora cached sampah. Kajaba iku, database sing luwih rumit lan luwih gedhe lan luwih akeh jumlahe, luwih angel ditindakake.

Nanging biasane aku mbuwang mouse lan mung nulis kode. Contone, sampeyan kudu ngerteni tabel endi (lan properti) sing ana ing skema "HR". Ing umume DBMS, asil sing dikarepake bisa digayuh kanthi pitakon prasaja saka information_schema:

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

Saka basis data menyang basis data, isi tabel referensi kasebut beda-beda gumantung saka kapabilitas saben DBMS. Lan, contone, kanggo MySQL, saka buku referensi sing padha sampeyan bisa entuk parameter tabel khusus kanggo DBMS iki:

select table_name
     , storage_engine -- Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ "Π΄Π²ΠΈΠΆΠΎΠΊ" ("MyISAM", "InnoDB" etc)
     , row_format     -- Π€ΠΎΡ€ΠΌΠ°Ρ‚ строки ("Fixed", "Dynamic" etc)
     , ...
  from information_schema.tables
 where schema = 'HR'

Oracle ora ngerti information_schema, nanging duwe Metadata Oracle, lan ora ana masalah gedhe:

select table_name
     , pct_free       -- ΠœΠΈΠ½ΠΈΠΌΡƒΠΌ свободного мСста Π² Π±Π»ΠΎΠΊΠ΅ Π΄Π°Π½Π½Ρ‹Ρ… (%)
     , pct_used       -- ΠœΠΈΠ½ΠΈΠΌΡƒΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠΎΠ³ΠΎ мСста Π² Π±Π»ΠΎΠΊΠ΅ Π΄Π°Π½Π½Ρ‹Ρ… (%)
     , last_analyzed  -- Π”Π°Ρ‚Π° послСднСго сбора статистики
     , ...
  from all_tables
 where owner = 'HR'

ClickHouse ora kajaba:

select name
     , engine -- Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ "Π΄Π²ΠΈΠΆΠΎΠΊ" ("MergeTree", "Dictionary" etc)
     , ...
  from system.tables
 where database = 'HR'

Bab sing padha bisa ditindakake ing Cassandra (sing duwe kolom kulawarga tinimbang tabel lan spasi tombol tinimbang skema):

select columnfamily_name
     , compaction_strategy_class  -- БтратСгия сборки мусора
     , gc_grace_seconds           -- ВрСмя ΠΆΠΈΠ·Π½ΠΈ мусора
     , ...
  from system.schema_columnfamilies
 where keyspace_name = 'HR'

Kanggo umume database liyane, sampeyan uga bisa nggawe pitakon sing padha (malah Mongo duwe koleksi sistem khusus, sing ngemot informasi babagan kabeh koleksi ing sistem).

Mesthi, kanthi cara iki sampeyan bisa entuk informasi ora mung babagan tabel, nanging babagan obyek apa wae ing umum. Saka wektu kanggo wektu, wong apik nuduhake kode kuwi kanggo database beda, kayata, contone, ing seri artikel habra "Fungsi kanggo ndokumentasikake database PostgreSQL" (Ayb, Ben, Gym). Mesthi wae, tetep kabeh pitakon ing sirahku lan terus-terusan ngetik kaya ngono, mula ing IDE / editor favorit, aku duwe potongan potongan sing wis disiapake kanggo pitakon sing asring digunakake, lan mung ngetik jeneng obyek menyang cithakan.

AkibatΓ©, cara navigasi lan nggoleki obyek iki luwih fleksibel, ngirit wektu akeh, lan ngidini sampeyan entuk persis informasi ing wangun sing saiki dibutuhake (kayata, contone, diterangake ing kiriman kasebut. "Ngekspor data saka database ing format apa wae: apa sing bisa ditindakake IDE ing platform IntelliJ").

Operasi karo obyek

Sawise kita nemokake lan sinau obyek sing dibutuhake, wektune kanggo nindakake perkara sing migunani. Alami, uga tanpa njupuk driji saka keyboard.

Ora ana rahasia manawa mung mbusak tabel bakal katon padha ing meh kabeh database:

drop table hr.persons

Nanging kanthi nggawe meja dadi luwih menarik. Meh kabeh DBMS (kalebu akeh NoSQL) bisa "nggawe tabel" ing salah siji wangun utawa liyane, lan bagean utama iku malah rada beda (jeneng, dhaftar kolom, jinis data), nanging rincian liyane bisa beda-beda dramatically lan gumantung ing piranti internal lan kapabilitas DBMS tartamtu. Conto favoritku yaiku ing dokumentasi Oracle mung ana BNF "wuda" kanggo sintaks "gawe tabel". ngisi 31 kaca. DBMS liyane nduweni kemampuan sing luwih andhap, nanging saben DBMS uga nduweni fitur sing menarik lan unik kanggo nggawe tabel (postgres, MySQL, kecoak, kasir). Ora mungkin "Tuntunan" grafis saka IDE liyane (utamane sing universal) bakal bisa nutupi kabeh kabisan kasebut, lan sanajan bisa, ora bakal dadi tontonan kanggo wong sing ora seneng. Ing wektu sing padha, statement ditulis kanthi bener lan pas wektune nggawe tabel bakal ngidini sampeyan gampang nggunakake kabeh, nggawe panyimpenan lan akses menyang data dipercaya, optimal lan nyaman sabisa.

Uga, akeh DBMS duwe jinis obyek tartamtu dhewe sing ora kasedhiya ing DBMS liyane. Menapa malih, kita bisa nindakake operasi ora mung ing obyek database, nanging uga ing DBMS dhewe, contone, "mateni" proses, mbebasake sawetara area memori, ngaktifake nelusuri, ngalih menyang mode "mung maca", lan akeh liyane.

Saiki ayo nggambar sethithik

Salah sawijining tugas sing paling umum yaiku nggawe diagram karo obyek database lan ndeleng obyek lan sambungan ing antarane gambar sing apik. Meh kabeh IDE grafis, utilitas "baris perintah" sing kapisah, alat grafis khusus lan modeler bisa nindakake iki. Dheweke bakal nggambar soko kanggo sampeyan "sing paling apik," lan sampeyan bisa mengaruhi proses iki mung kanthi bantuan sawetara paramèter ing file konfigurasi utawa kothak ing antarmuka.

Nanging masalah iki bisa ditanggulangi luwih prasaja, luwih fleksibel lan elegan, lan mesthi kanthi bantuan kode. Kanggo nggawe diagram saka kerumitan apa wae, kita duwe sawetara basa markup khusus (DOT, GraphML etc), lan kanggo wong-wong mau kabeh panyebaran aplikasi (GraphViz, PlantUML, Mermaid) sing bisa maca instruksi kasebut lan nggambarake ing macem-macem format. . Ya, kita wis ngerti carane entuk informasi babagan obyek lan sambungan ing antarane.

Iki minangka conto cilik babagan apa sing bisa katon, nggunakake PlantUML lan database demo kanggo PostgreSQL (ing sisih kiwa ana query SQL sing bakal ngasilake instruksi sing dibutuhake kanggo PlantUML, lan ing sisih tengen ana asil):

Pengalaman "Database minangka Kode".

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'

Lan yen sampeyan nyoba sethitik, banjur adhedhasar Cithakan ER kanggo PlantUML sampeyan bisa entuk sing meh padha karo diagram ER nyata:

Pitakonan SQL rada rumit

-- Π¨Π°ΠΏΠΊΠ°
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'

Pengalaman "Database minangka Kode".

Yen sampeyan ndeleng kanthi teliti, ing ngisor tudung akeh alat visualisasi uga nggunakake pitakon sing padha. Bener, panjaluk kasebut biasane jero "hardwired" menyang kode aplikasi dhewe lan angel dingerteni, ora kanggo sebutno modifikasi saka wong-wong mau.

Metrik lan ngawasi

Ayo pindhah menyang topik tradisional sing rumit - database performance monitoring . Aku kelingan crita nyata cilik sing dicritakake dening "salah sawijining kancaku." Ing proyek liyane, ana DBA sing kuat, lan sawetara pangembang ngerti dheweke kanthi pribadi, utawa wis nate ndeleng dheweke (senadyan kasunyatane, miturut gosip, dheweke kerja ing endi wae ing bangunan sabanjure). Ing jam "X", nalika sistem poduction saka pengecer gedhe wiwit "rasa ala" maneh, dheweke meneng ngirim gambar gambar saka Oracle Enterprise Manager, kang kasebut kanthi teliti, nyorot panggonan kritis karo tandha abang kanggo "comprehensibility" ( iki, kanggo sijine iku mildly, ora bantuan akeh). Lan adhedhasar "kertu foto" iki aku kudu nambani. Ing wektu sing padha, ora ana sing nduweni akses menyang larang regane (ing loro pangertèn saka tembung) Enterprise Manager, amarga sistem iki rumit lan larang, dumadakan "pangembang kesandhung lan ngrusak kabeh." Mulane, pangembang "empiris" nemokake lokasi lan sabab saka rem lan ngeculake tembelan. Yen layang ancaman saka DBA ora teka maneh ing mangsa ngarep, kabeh wong bakal ambegan lega lan bali menyang tugas saiki (nganti Surat anyar).

Nanging proses ngawasi bisa katon luwih nyenengake lan ramah, lan sing paling penting, bisa diakses lan transparan kanggo kabeh wong. Paling ora bagean dhasar, minangka tambahan kanggo sistem ngawasi utama (sing mesthi migunani lan ing akeh kasus irreplaceable). Sembarang DBMS gratis lan gratis kanggo nuduhake informasi babagan kahanan lan kinerja saiki. Ing Oracle DB sing padha "getih", meh kabeh informasi babagan kinerja bisa dipikolehi saka tampilan sistem, wiwit saka proses lan sesi nganti kahanan cache buffer (contone, Skrip DBA, bagean "Monitoring"). Postgresql uga duwe akeh tampilan sistem kanggo monitoring database, ing tartamtu sing indispensable ing urip saben dina saka sembarang DBA, kayata pg_stat_activity, pg_stat_database, pg_stat_bgwriter. MySQL malah duwe skema kapisah kanggo iki. kinerja_schema. A In Mongo built-in profiler nglumpukake data kinerja menyang koleksi sistem sistem.profil.

Mangkono, bersenjata karo sawetara jinis kolektor metrik (Telegraf, Metricbeat, Collectd) sing bisa nindakake pitakon sql khusus, panyimpenan metrik kasebut (InfluxDB, Elasticsearch, Timescaledb) lan visualisasi (Grafana, Kibana), sampeyan bisa entuk cukup gampang. lan sistem ngawasi fleksibel sing bakal digabungake rapet karo metrik sistem liyane (dipikolehi, contone, saka server aplikasi, saka OS, etc.). Contone, iki ditindakake ing pgwatch2, sing nggunakake kombinasi InfluxDB + Grafana lan sakumpulan pitakon menyang tampilan sistem, sing uga bisa diakses. nambah pitakon khusus.

Total

Lan iki mung dhaptar kira-kira apa sing bisa ditindakake karo database nggunakake kode SQL biasa. Aku manawa sampeyan bisa nemokake akeh liyane nggunakake, nulis ing komentar. Lan kita bakal ngomong babagan carane (lan sing paling penting kenapa) ngotomatisasi kabeh iki lan kalebu ing pipa CI / CD sabanjure.

Source: www.habr.com

Add a comment