Pangalaman "Database salaku Kode".

Pangalaman "Database salaku Kode".

SQL, naon anu tiasa langkung saderhana? Masing-masing urang tiasa nyerat pamundut saderhana - urang ngetik milih, daptar kolom nu diperlukeun, lajeng ti, ngaran tabel, sababaraha kaayaan di di mana sareng éta sadayana - data mangpaat aya dina saku urang, sareng (ampir) henteu paduli DBMS anu aya dina tiung dina waktos éta (atanapi meureun lain DBMS pisan). Hasilna, gawé bareng ampir sagala sumber data (relasional jeung teu kitu) bisa dianggap ti sudut pandang kode biasa (kalawan sagala rupa eta ngakibatkeun - kontrol versi, review kode, analisis statik, autotests, sarta éta sakabéh). Sarta ieu manglaku teu ukur keur data sorangan, schemas na migrasi, tapi sacara umum pikeun sakabéh kahirupan gudang. Dina artikel ieu kami baris ngobrol ngeunaan tugas sapopoé jeung masalah gawé bareng sagala rupa basis data dina lénsa "database salaku kode".

Sareng hayu urang mimitian langsung ti ORM. Pertempuran munggaran tina jinis "SQL vs ORM" ditingali deui pra-Petrine Rus'.

Pemetaan obyék-relasional

Ngadukung ORM sacara tradisional ngahargaan kagancangan sareng kagampangan pangwangunan, kamerdikaan tina DBMS sareng kode bersih. Kanggo sabagéan ageung urang, kodeu pikeun damel sareng pangkalan data (sareng sering database éta sorangan)

biasana siga kieu...

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

Modél ieu ngagantung kalawan annotations pinter, sarta wae balik layar a ORM gagah ngahasilkeun sarta executes ton sababaraha kode SQL. Ku jalan kitu, pamekar nyobian pangalusna maranéhanana pikeun ngasingkeun diri tina database maranéhanana jeung kilométer abstraksi, nu nunjukkeun sababaraha "SQL hate".

Di sisi séjén barikades, penganut murni "handmade" SQL catetan kamampuhan pikeun squeeze sagala jus kaluar tina DBMS maranéhanana tanpa lapisan tambahan sarta abstraksi. Hasilna, proyék "data-centric" muncul, dimana jalma dilatih husus aub dina database (aranjeunna oge "basicists", aranjeunna oge "basicists", aranjeunna oge "basdeners", jsb), sarta pamekar. ngan kudu "narik" pintonan siap-dijieun jeung prosedur disimpen, tanpa bade kana detil.

Kumaha upami urang ngagaduhan anu pangsaéna tina dua dunya? Kumaha ieu dipigawé dina alat éndah kalawan ngaran-affirming hirup Yesql. Kuring bakal masihan sababaraha garis tina konsép umum dina tarjamahan gratis kuring, sareng anjeun tiasa ngenalkeunana sacara langkung rinci. di dieu.

Clojure mangrupakeun basa tiis pikeun nyieun DSLs, tapi SQL sorangan mangrupakeun DSL tiis, sarta kami teu butuh nu sejen. S-ekspresi anu hébat, tapi maranéhna teu nambahan nanaon anyar di dieu. Hasilna, urang meunang kurung demi kurung. teu satuju? Teras antosan waktos nalika abstraksi dina pangkalan data mimiti bocor sareng anjeun mimiti gelut sareng fungsina (atah-sql)

Janten naon anu kuring kedah laksanakeun? Hayu urang tinggalkeun SQL salaku SQL biasa - hiji file per pamundut:

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

... lajeng baca file ieu, ngarobahna kana 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" ...} ...)

Ku adhering kana prinsip "SQL ku sorangan, Clojure ku sorangan", anjeun meunang:

  • Taya kejutan sintaksis. Database anjeun (sapertos anu sanés) henteu 100% patuh kana standar SQL - tapi ieu henteu masalah pikeun Yesql. Anjeun moal pernah miceunan waktos moro pikeun fungsi sareng sintaksis sarimbag SQL. Anjeun pernah kudu balik deui ka fungsi hiji (atah-sql "sababaraha ( 'funky':: SYNTAX)")).
  • Pangrojong éditor pangsaéna. Éditor anjeun parantos ngagaduhan dukungan SQL anu saé. Ku ngahemat SQL salaku SQL anjeun tiasa nganggo éta.
  • Kasaluyuan tim. DBA anjeun tiasa maca sareng nyerat SQL anu anjeun anggo dina proyék Clojure anjeun.
  • Tuning kinerja anu langkung gampang. Kudu ngawangun rencana pikeun query masalah? Ieu teu masalah lamun query anjeun SQL biasa.
  • Reusing queries. Séred sareng teundeun file SQL anu sami kana proyék-proyék sanés sabab éta ngan ukur SQL kuno - ngan bagikeun.

Dina pamanggih kuring, ideu pisan keren sareng dina waktos anu sami saderhana pisan, hatur nuhun pikeun proyékna parantos nampi seueur pengikut dina ragam basa. Sarta kami salajengna bakal coba nerapkeun hiji filosofi sarupa misahkeun kode SQL ti sagalana sejenna jauh saluareun ORM nu.

IDE & manajer DB

Hayu urang mimitian ku tugas sapopoé basajan. Sering urang kedah milarian sababaraha objék dina pangkalan data, contona, milarian tabel dina skéma sareng diajar strukturna (naon kolom, konci, indéks, konstrain, jsb anu dianggo). Sarta ti mana wae IDE grafis atawa saeutik DB-manajer, mimiti sagala, urang ngaharepkeun kahayang abilities ieu. Janten gancang sareng anjeun henteu kedah ngantosan satengah jam dugi ka jandela kalayan inpormasi anu diperyogikeun digambar (utamana kalayan sambungan anu laun ka pangkalan data jauh), sareng dina waktos anu sami, inpormasi anu ditampi seger sareng relevan, jeung teu sindangan junk. Sumawona, langkung kompleks sareng langkung ageung database sareng langkung ageung jumlahna, langkung sesah pikeun ngalakukeun ieu.

Tapi biasana kuring ngalungkeun beurit sareng ngan ukur nyerat kode. Hayu urang nyebutkeun anjeun kudu manggihan nu tabel (jeung nu sipat) dikandung dina "SDM" skéma. Dina kalolobaan DBMSs, hasil nu dipikahoyong bisa dihontal ku query basajan ieu ti information_schema:

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

Ti database ka database, eusi tabel rujukan misalna rupa-rupa gumantung kana kamampuhan unggal DBMS. Sareng, contona, pikeun MySQL, tina buku rujukan anu sami anjeun tiasa nampi parameter tabel khusus pikeun DBMS ieu:

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

Oracle teu nyaho information_schema, tapi boga Metadata Oracle, sareng teu aya masalah ageung timbul:

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

ClickHouse teu aya pengecualian:

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

Hal anu sami tiasa dilakukeun dina Cassandra (anu ngagaduhan kulawarga kolom tinimbang tabel sareng ruang konci tinimbang skéma):

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

Kanggo sabagéan ageung pangkalan data sanés, anjeun ogé tiasa mendakan patarosan anu sami (malah Mongo gaduh kumpulan sistem husus, nu ngandung émbaran ngeunaan sakabéh kumpulan dina sistem).

Tangtosna, ku cara ieu anjeun tiasa nampi inpormasi henteu ngan ukur ngeunaan tabel, tapi ngeunaan naon waé objék sacara umum. Ti jaman ka jaman, jalma-jalma bageur ngabagi kode sapertos kitu pikeun pangkalan data anu béda, sapertos, contona, dina séri artikel habra "Fungsi pikeun ngadokumentasikeun pangkalan data PostgreSQL" (Ayb, Ben, Tempat pitnes). Tangtosna, tetep sadayana gunung patarosan ieu dina sirah kuring sareng terus-terusan ngetik aranjeunna mangrupikeun kasenangan, janten dina IDE / redaktur karesep kuring kuring gaduh set snippét anu tos disiapkeun pikeun patarosan anu sering dianggo, sareng anu tetep nyaéta ngetik ngaran objék kana citakan.

Hasilna, metoda ieu nganapigasi sareng milarian obyék langkung fleksibel, ngahémat seueur waktos, sareng ngamungkinkeun anjeun kéngingkeun inpormasi dina bentuk anu ayeuna diperyogikeun (sapertos, contona, dijelaskeun dina tulisan. "Ékspor data tina pangkalan data dina format naon waé: naon anu tiasa dilakukeun ku IDE dina platform IntelliJ").

Operasi kalawan objék

Saatos urang mendakan sareng ngulik objék anu diperyogikeun, waktosna pikeun ngalakukeun anu mangpaat sareng aranjeunna. Alami, ogé tanpa nyokot ramo Anjeun off keyboard.

Henteu aya rahasia yén ngan saukur ngahapus méja bakal katingali sami dina ampir sadaya pangkalan data:

drop table hr.persons

Tapi kalayan kreasi méja janten langkung narik. Ampir sagala DBMS (kaasup loba NoSQL) bisa "nyieun tabel" dina hiji formulir atawa sejen, sarta bagian utama eta malah bakal rada béda (ngaran, daptar kolom, tipe data), tapi rinci sejenna bisa béda nyirorot sarta gumantung kana alat internal sareng kamampuan DBMS khusus. Conto karesep kuring nyaéta dina dokuméntasi Oracle ngan aya BNF "taranjang" pikeun sintaksis "nyieun méja" nempatan 31 kaca. DBMS séjén gaduh kamampuan anu langkung sederhana, tapi masing-masing gaduh seueur fitur anu pikaresepeun sareng unik pikeun nyiptakeun tabel (postgres, MySQL, kecoak, cassandra). Teu aya kamungkinan yén "wizard" grafis tina IDE anu sanés (utamana anu universal) bakal tiasa nutupan sadayana kamampuan ieu, sareng upami tiasa, éta moal janten tontonan pikeun anu pingsan. Dina waktu nu sarua, hiji pernyataan ditulis leres tur timely nyieun méja bakal ngidinan Anjeun pikeun gampang ngagunakeun sakabéh éta, sangkan neundeun jeung aksés ka data anjeun dipercaya, optimal sarta sakumaha nyaman sabisa.

Ogé, loba DBMSs boga tipe husus sorangan objék nu teu sadia di DBMSs séjén. Leuwih ti éta, urang tiasa ngalakukeun operasi teu ukur dina objék database, tapi ogé dina DBMS sorangan, contona, "maéhan" prosés, ngosongkeun sababaraha wewengkon memori, ngaktifkeun tracing, pindah ka mode "baca wungkul", sarta leuwih.

Ayeuna hayu urang ngagambar saeutik

Salah sahiji tugas anu paling umum nyaéta ngawangun diagram sareng objék database sareng ningali objék sareng sambungan antara aranjeunna dina gambar anu saé. Ampir sagala IDE grafis, misah "garis paréntah" Utiliti, parabot grafis husus sarta modelers tiasa ngalakukeun ieu. Aranjeunna baris ngagambar hal pikeun anjeun "sakumaha pangalusna aranjeunna tiasa," tur anjeun tiasa pangaruh prosés ieu saeutik ngan kalayan bantuan sababaraha parameter dina file konfigurasi atawa centang dina panganteur nu.

Tapi masalah ieu tiasa direngsekeun langkung saderhana, langkung fleksibel sareng elegan, sareng tangtosna kalayan bantosan kode. Pikeun nyieun diagram naon waé pajeulitna, kami ngagaduhan sababaraha basa markup khusus (DOT, GraphML jsb), sareng pikeun aranjeunna sadayana paburencay aplikasi (GraphViz, PlantUML, Mermaid) anu tiasa maca paréntah sapertos kitu sareng ngabayangkeunana dina sababaraha format. . Nya, urang parantos terang kumaha kéngingkeun inpormasi ngeunaan objék sareng hubunganana.

Ieu conto leutik kumaha ieu tiasa katingali, nganggo PlantUML sareng database demo pikeun PostgreSQL (di kénca mangrupa query SQL anu bakal ngahasilkeun instruksi diperlukeun pikeun PlantUML, sarta di katuhu nyaéta hasilna):

Pangalaman "Database salaku 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'

Tur upami Anjeun salah coba saeutik, lajeng dumasar kana ER template pikeun PlantUML anjeun tiasa kéngingkeun anu sami sareng diagram ER nyata:

Paménta SQL sakedik langkung 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'

Pangalaman "Database salaku Kode".

Lamun kasampak raket, handapeun tiung loba parabot visualisasi ogé ngagunakeun queries sarupa. Leres, requests ieu biasana deeply "hardwired" kana kode tina aplikasi sorangan jeung hese ngarti, teu nyebut sagala modifikasi aranjeunna.

Métrik sareng ngawaskeun

Hayu urang ngaléngkah ka topik tradisional kompléks - database performance monitoring . Kuring émut hiji carita nyata leutik anu dicaritakeun ka kuring ku "salah sahiji réréncangan kuring." Dina proyék séjén cicing hiji DBA kuat tangtu, sarta sababaraha pamekar terang anjeunna pribadi, atawa geus kungsi katempo manehna di jalma (sanajan kanyataan yén, nurutkeun rumor, anjeunna digawé wae di gedong salajengna). Dina jam "X", nalika sistem poduction tina pangecér badag mimiti "ngarasa goréng" sakali deui, anjeunna cicingeun ngirimkeun Potret layar grafik ti Oracle Enterprise Manager, dimana anjeunna taliti nyorot tempat kritis kalayan spidol beureum pikeun "comprehensibility" ( ieu, mun nempatkeun eta mildly, teu mantuan loba). Sarta dumasar kana ieu "kartu poto" Kuring kungsi ngubaran. Dina waktu nu sarua, teu saurang ogé miboga aksés ka adi (dina duanana itungan kecap) Manajer Perusahaan, sabab Sistemna rumit sareng mahal, ujug-ujug "pamekar titajong kana hiji hal sareng ngarobih sadayana." Ku alatan éta, pamekar "émpiris" kapanggih lokasi sarta ngabalukarkeun rem sarta ngarilis patch a. Lamun surat menacing ti DBA teu datang deui dina mangsa nu bakal datang, mangka dulur bakal ngambekan Hhh lega sarta balik deui ka tugas maranéhanana ayeuna (dugi ka Surat anyar).

Tapi prosés ngawaskeun tiasa katingali langkung senang sareng ramah, sareng anu paling penting, tiasa diaksés sareng transparan pikeun sadayana. Sahenteuna bagian dasarna, salaku tambahan kana sistem ngawaskeun utama (anu pasti mangpaat sareng dina seueur kasus teu tiasa diganti). Sakur DBMS gratis sareng leres-leres gratis pikeun ngabagi inpormasi ngeunaan kaayaan sareng kinerja ayeuna. Dina Oracle DB anu "getih" anu sami, ampir sadaya inpormasi ngeunaan pagelaran tiasa didapet tina tampilan sistem, mimitian ti prosés sareng sesi dugi ka kaayaan cache panyangga (contona, Aksara DBA, bagian "Monitoring"). Postgresql ogé ngagaduhan seueur pandangan sistem pikeun ngawas database, khususna anu penting pisan dina kahirupan sapopoe DBA mana waé, sapertos pg_stat_activity, pg_stat_database, pg_stat_bgwriter. MySQL malah gaduh skéma anu misah pikeun ieu. performance_schema. A Dina Mongo diwangun-di profiler aggregates data kinerja kana kumpulan sistem sistem.profil.

Ku kituna, angkatan sareng sababaraha jinis kolektor metrics (Telegraf, Metricbeat, Collectd) anu tiasa ngalakukeun query sql khusus, neundeun métrik ieu (InfluxDB, Elasticsearch, Timescaledb) sareng visualizer (Grafana, Kibana), anjeun tiasa nampi anu cukup gampang. sarta sistem ngawaskeun fléksibel nu bakal raket terpadu kalayan metrics sistem-lega lianna (diala, contona, ti server aplikasi, ti OS, jsb). Sapertos, contona, ieu dilakukeun dina pgwatch2, anu nganggo kombinasi InfluxDB + Grafana sareng sakumpulan patarosan pikeun pandangan sistem, anu ogé tiasa diaksés. nambahkeun queries custom.

dina total

Sareng ieu ngan ukur daptar perkiraan naon anu tiasa dilakukeun ku database kami nganggo kode SQL biasa. Kuring yakin anjeun tiasa mendakan seueur deui kagunaan, tulis dina koméntar. Sarta kami bakal ngobrol ngeunaan kumaha (jeung paling importantly naha) pikeun ngajadikeun otomatis sadaya ieu sareng kaasup kana CI / pipa CD Anjeun waktos salajengna.

sumber: www.habr.com

Tambahkeun komentar