SQL, apa yang lebih mudah? Setiap daripada kita boleh menulis permintaan mudah - kita menaip pilih, senaraikan lajur yang diperlukan, kemudian dari, nama jadual, beberapa syarat dalam di mana dan itu sahaja - data berguna ada dalam poket kami, dan (hampir) tidak kira DBMS mana yang berada di bawah hud pada masa itu (atau mungkin
Dan mari kita mulakan dari
Pemetaan objek-hubungan
Penyokong ORM secara tradisinya menghargai kepantasan dan kemudahan pembangunan, kebebasan daripada DBMS dan kod bersih. Bagi kebanyakan kita, kod untuk bekerja dengan pangkalan data (dan selalunya pangkalan data itu sendiri)
selalunya nampak macam ni...
@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 ini digantung dengan anotasi yang bijak, dan di sebalik tabir ORM yang berani menjana dan melaksanakan banyak kod SQL. Ngomong-ngomong, pembangun cuba sedaya upaya untuk mengasingkan diri mereka daripada pangkalan data mereka dengan abstraksi kilometer, yang menunjukkan beberapa
Di sisi lain penghadang, penganut SQL "buatan tangan" tulen mencatatkan keupayaan untuk memerah semua jus keluar dari DBMS mereka tanpa lapisan dan abstraksi tambahan. Akibatnya, projek "berpusatkan data" muncul, di mana orang yang terlatih khas terlibat dalam pangkalan data (mereka juga "ahli asas", mereka juga "ahli asas", mereka juga "tukang bas", dll.), dan pemaju hanya perlu "menarik" pandangan yang sudah siap dan prosedur tersimpan, tanpa pergi ke butiran.
Bagaimana jika kita mempunyai yang terbaik dari kedua-dua dunia? Bagaimana ini dilakukan dalam alat yang hebat dengan nama yang mengesahkan kehidupan
Clojure ialah bahasa yang menarik untuk mencipta DSL, tetapi SQL itu sendiri ialah DSL yang hebat, dan kami tidak memerlukan yang lain. Ungkapan-S bagus, tetapi ia tidak menambah apa-apa yang baharu di sini. Akibatnya, kami mendapat kurungan demi kurungan. Tidak setuju? Kemudian tunggu masa apabila abstraksi ke atas pangkalan data mula bocor dan anda mula berjuang dengan fungsi tersebut (raw-sql)
Jadi apa yang perlu saya lakukan? Mari tinggalkan SQL sebagai SQL biasa - satu fail setiap permintaan:
-- name: users-by-country
select *
from users
where country_code = :country_code
... dan kemudian baca fail ini, mengubahnya menjadi 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" ...} ...)
Dengan mematuhi prinsip "SQL dengan sendirinya, Clojure dengan sendirinya", anda mendapat:
- Tiada kejutan sintaksis. Pangkalan data anda (seperti mana-mana yang lain) tidak 100% mematuhi standard SQL - tetapi ini tidak penting untuk Yesql. Anda tidak akan membuang masa untuk memburu fungsi dengan sintaks setara SQL. Anda tidak perlu kembali ke fungsi (raw-sql "beberapa('funky'::SYNTAX)")).
- Sokongan editor terbaik. Editor anda sudah mempunyai sokongan SQL yang sangat baik. Dengan menyimpan SQL sebagai SQL anda boleh menggunakannya dengan mudah.
- Keserasian pasukan. DBA anda boleh membaca dan menulis SQL yang anda gunakan dalam projek Clojure anda.
- Penalaan prestasi yang lebih mudah. Perlu membina rancangan untuk pertanyaan bermasalah? Ini tidak menjadi masalah apabila pertanyaan anda adalah SQL biasa.
- Menggunakan semula pertanyaan. Seret dan lepaskan fail SQL yang sama ke dalam projek lain kerana ia hanyalah SQL lama biasa - kongsi sahaja.
Pada pendapat saya, idea itu sangat keren dan pada masa yang sama sangat mudah, berkat projek itu telah mendapat banyak keuntungan
Pengurus IDE & DB
Mari kita mulakan dengan tugas harian yang mudah. Selalunya kita perlu mencari beberapa objek dalam pangkalan data, sebagai contoh, mencari jadual dalam skema dan mengkaji strukturnya (apa lajur, kunci, indeks, kekangan, dll. yang digunakan). Dan daripada mana-mana IDE grafik atau pengurus DB kecil, pertama sekali, kami menjangkakan kebolehan ini dengan tepat. Supaya ia pantas dan anda tidak perlu menunggu setengah jam sehingga tetingkap dengan maklumat yang diperlukan ditarik (terutama dengan sambungan perlahan ke pangkalan data jauh), dan pada masa yang sama, maklumat yang diterima adalah segar dan relevan, dan bukan sampah sarap. Lebih-lebih lagi, lebih kompleks dan lebih besar pangkalan data dan lebih banyak bilangannya, lebih sukar untuk melakukan ini.
Tetapi biasanya saya membuang tetikus dan hanya menulis kod. Katakan anda perlu mengetahui jadual (dan sifat yang mana) terkandung dalam skema "HR". Dalam kebanyakan DBMS, hasil yang diingini boleh dicapai dengan pertanyaan mudah ini daripada information_schema:
select table_name
, ...
from information_schema.tables
where schema = 'HR'
Dari pangkalan data ke pangkalan data, kandungan jadual rujukan tersebut berbeza-beza bergantung pada keupayaan setiap DBMS. Dan, sebagai contoh, untuk MySQL, dari buku rujukan yang sama anda boleh mendapatkan parameter jadual khusus untuk DBMS ini:
select table_name
, storage_engine -- Используемый "движок" ("MyISAM", "InnoDB" etc)
, row_format -- Формат строки ("Fixed", "Dynamic" etc)
, ...
from information_schema.tables
where schema = 'HR'
Oracle tidak mengetahui information_schema, tetapi ia mempunyai
select table_name
, pct_free -- Минимум свободного места в блоке данных (%)
, pct_used -- Минимум используемого места в блоке данных (%)
, last_analyzed -- Дата последнего сбора статистики
, ...
from all_tables
where owner = 'HR'
ClickHouse tidak terkecuali:
select name
, engine -- Используемый "движок" ("MergeTree", "Dictionary" etc)
, ...
from system.tables
where database = 'HR'
Sesuatu yang serupa boleh dilakukan dalam Cassandra (yang mempunyai columnfamilies dan bukannya jadual dan ruang kekunci dan bukannya skema):
select columnfamily_name
, compaction_strategy_class -- Стратегия сборки мусора
, gc_grace_seconds -- Время жизни мусора
, ...
from system.schema_columnfamilies
where keyspace_name = 'HR'
Untuk kebanyakan pangkalan data lain, anda juga boleh membuat pertanyaan yang serupa (malah Mongo mempunyai
Sudah tentu, dengan cara ini anda boleh mendapatkan maklumat bukan sahaja mengenai jadual, tetapi mengenai sebarang objek secara umum. Dari semasa ke semasa, orang baik berkongsi kod sedemikian untuk pangkalan data yang berbeza, sebagai contoh, dalam siri artikel habra "Fungsi untuk mendokumentasikan pangkalan data PostgreSQL" (
Akibatnya, kaedah menavigasi dan mencari objek ini adalah lebih fleksibel, menjimatkan banyak masa, dan membolehkan anda mendapatkan maklumat yang tepat dalam bentuk yang kini diperlukan (seperti, contohnya, diterangkan dalam siaran
Operasi dengan objek
Selepas kami menemui dan mengkaji objek yang diperlukan, sudah tiba masanya untuk melakukan sesuatu yang berguna dengannya. Sememangnya, juga tanpa mengambil jari anda dari papan kekunci.
Bukan rahsia lagi bahawa hanya memadamkan jadual akan kelihatan sama dalam hampir semua pangkalan data:
drop table hr.persons
Tetapi dengan penciptaan jadual ia menjadi lebih menarik. Hampir mana-mana DBMS (termasuk banyak NoSQL) boleh "membuat jadual" dalam satu bentuk atau yang lain, dan bahagian utamanya akan berbeza sedikit (nama, senarai lajur, jenis data), tetapi butiran lain boleh berbeza secara mendadak dan bergantung pada peranti dalaman dan keupayaan DBMS tertentu. Contoh kegemaran saya ialah dalam dokumentasi Oracle hanya terdapat BNF "telanjang" untuk sintaks "buat jadual"
Selain itu, banyak DBMS mempunyai jenis objek khusus mereka sendiri yang tidak tersedia dalam DBMS lain. Selain itu, kita boleh melakukan operasi bukan sahaja pada objek pangkalan data, tetapi juga pada DBMS itu sendiri, sebagai contoh, "membunuh" proses, membebaskan beberapa kawasan memori, membolehkan pengesanan, beralih kepada mod "baca sahaja", dan banyak lagi.
Sekarang mari kita lukis sedikit
Salah satu tugas yang paling biasa ialah membina gambar rajah dengan objek pangkalan data dan melihat objek dan hubungan antara mereka dalam gambar yang cantik. Hampir mana-mana IDE grafik, utiliti "baris arahan" berasingan, alat grafik khusus dan pemodel boleh melakukan ini. Mereka akan menarik sesuatu untuk anda "sebaik mungkin," dan anda boleh mempengaruhi sedikit proses ini hanya dengan bantuan beberapa parameter dalam fail konfigurasi atau kotak pilihan dalam antara muka.
Tetapi masalah ini boleh diselesaikan dengan lebih mudah, lebih fleksibel dan elegan, dan sudah tentu dengan bantuan kod. Untuk mencipta gambar rajah dengan sebarang kerumitan, kami mempunyai beberapa bahasa penanda khusus (DOT, GraphML dll), dan bagi mereka serakan keseluruhan aplikasi (GraphViz, PlantUML, Mermaid) yang boleh membaca arahan tersebut dan menggambarkannya dalam pelbagai format . Nah, kita sudah tahu cara mendapatkan maklumat tentang objek dan hubungan antara mereka.
Berikut ialah contoh kecil tentang rupa ini, menggunakan PlantUML dan
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'
Dan jika anda mencuba sedikit, maka berdasarkan
Pertanyaan SQL adalah sedikit lebih 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'
Jika anda melihat dengan teliti, di bawah tudung banyak alat visualisasi juga menggunakan pertanyaan yang serupa. Benar, permintaan ini biasanya mendalam
Metrik dan pemantauan
Mari kita beralih kepada topik tradisional yang kompleks - pemantauan prestasi pangkalan data. Saya masih ingat kisah benar kecil yang diceritakan kepada saya oleh "salah seorang kawan saya." Pada projek lain terdapat DBA yang berkuasa tertentu, dan beberapa pemaju mengenalinya secara peribadi, atau pernah melihatnya secara peribadi (walaupun fakta bahawa, menurut khabar angin, dia bekerja di suatu tempat di bangunan sebelah) . Pada jam "X", apabila sistem poduction peruncit besar mula "berasa buruk" sekali lagi, dia secara senyap menghantar tangkapan skrin graf daripada Pengurus Perusahaan Oracle, di mana dia dengan teliti menyerlahkan tempat kritikal dengan penanda merah untuk "kefahaman" ( ini, secara ringkasnya, tidak banyak membantu). Dan berdasarkan "kad foto" ini saya terpaksa merawat. Pada masa yang sama, tiada siapa yang mempunyai akses kepada Pengurus Perusahaan (dalam kedua-dua erti kata) yang berharga, kerana sistem ini rumit dan mahal, tiba-tiba "pembangun tersandung pada sesuatu dan memecahkan segala-galanya." Oleh itu, pemaju "secara empirik" menemui lokasi dan punca brek dan mengeluarkan tampalan. Sekiranya surat ancaman daripada DBA tidak tiba lagi dalam masa terdekat, maka semua orang akan menarik nafas lega dan kembali kepada tugas semasa mereka (sehingga Surat baharu).
Tetapi proses pemantauan boleh kelihatan lebih menyeronokkan dan mesra, dan yang paling penting, boleh diakses dan telus untuk semua orang. Sekurang-kurangnya bahagian asasnya, sebagai tambahan kepada sistem pemantauan utama (yang pastinya berguna dan dalam banyak kes tidak boleh diganti). Mana-mana DBMS adalah percuma dan benar-benar percuma untuk berkongsi maklumat tentang keadaan dan prestasi semasanya. Dalam Oracle DB "berdarah" yang sama, hampir semua maklumat tentang prestasi boleh diperoleh daripada paparan sistem, daripada proses dan sesi kepada keadaan cache penimbal (contohnya,
Oleh itu, bersenjatakan beberapa jenis pengumpul metrik (Telegraf, Metricbeat, Collectd) yang boleh melakukan pertanyaan sql tersuai, penyimpanan metrik ini (InfluxDB, Elasticsearch, Timescaledb) dan visualizer (Grafana, Kibana), anda boleh mendapatkan yang agak mudah dan sistem pemantauan fleksibel yang akan disepadukan rapat dengan metrik seluruh sistem yang lain (diperolehi, contohnya, daripada pelayan aplikasi, daripada OS, dsb.). Sebagai contoh, ini dilakukan dalam pgwatch2, yang menggunakan kombinasi InfluxDB + Grafana dan satu set pertanyaan kepada paparan sistem, yang juga boleh diakses
Dalam jumlah
Dan ini hanyalah senarai anggaran perkara yang boleh dilakukan dengan pangkalan data kami menggunakan kod SQL biasa. Saya pasti anda boleh mencari banyak lagi kegunaan, tulis dalam komen. Dan kita akan bercakap tentang cara (dan yang paling penting mengapa) untuk mengautomasikan semua ini dan memasukkannya ke dalam saluran paip CI/CD anda pada masa akan datang.
Sumber: www.habr.com