SQL, чӣ метавонад соддатар бошад? Ҳар яки мо метавонем дархости оддӣ нависед - мо менависем интихоб кунед, сутунҳои лозимиро номбар кунед, пас аз, номи ҷадвал, баъзе шартҳо дар ки дар ва ҳамааш ин аст - маълумоти муфид дар ҷайби мо ва (қариб) новобаста аз он ки дар он вақт кадом DBMS зери сарпӯш аст (ё шояд).
Ва биёед рост аз он оғоз кунем
Харитасозии релятсионӣ ба объект
Тарафдорони ORM ба таври анъанавӣ суръат ва осонии рушд, мустақилият аз DBMS ва рамзи тозаро қадр мекунанд. Барои бисёре аз мо, рамзи кор бо пойгоҳи додаҳо (ва аксар вақт худи пойгоҳи додаҳо)
одатан чунин ба назар мерасад ...
@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;
}
...
Модел бо эзоҳҳои оқилона овезон карда шудааст ва дар ҷое паси парда як ORM далерона тоннаҳо коди SQL-ро тавлид ва иҷро мекунад. Дар омади гап, таҳиягарон кӯшиш мекунанд, ки худро аз пойгоҳи додаҳои худ бо километрҳои абстраксия ҷудо кунанд, ки ин нишон медиҳад, ки баъзе
Дар тарафи дигари баррикадаҳо, ҷонибдорони SQL-и холиси "дастсохт" қобилияти фишурдани тамоми шарбатро аз DBMS бидуни қабатҳои иловагӣ ва абстраксияҳо қайд мекунанд. Дар натиља лоињањои «дата-марказї» пайдо мешаванд, ки дар онњо ба базаи маълумот одамони махсус омўзонидашуда љалб карда мешаванд (онњо њам «асосист», онњо њам «базисист», њам «басденер» ва ѓайра) ва тањиягарон. бе тафсилот танҳо бояд намудҳои тайёр ва расмиёти ҳифзшударо “кашад”.
Чӣ мешавад, агар мо беҳтарини ҳарду ҷаҳонро дошта бошем? Чӣ тавр ин дар як асбоби аҷиб бо номи тасдиқкунандаи ҳаёт анҷом дода мешавад
Clojure як забони олӣ барои эҷоди DSLҳо аст, аммо худи SQL як DSL-и олӣ аст ва ба мо забони дигаре лозим нест. Ифодаи S бузург аст, аммо онҳо дар ин ҷо чизи нав илова намекунанд. Дар натиҷа, мо ба хотири қавс қавс ба даст меорем. розӣ нестед? Пас лаҳзаеро интизор шавед, ки абстраксия аз пойгоҳи додаҳо ба ихроҷ шурӯъ мекунад ва шумо бо функсия мубориза мебаред (raw-sql)
Пас, ман бояд чӣ кор кунам? Биёед SQL-ро ҳамчун SQL муқаррарӣ гузорем - як файл барои як дархост:
-- name: users-by-country
select *
from users
where country_code = :country_code
... ва он гоҳ ин файлро хонед ва онро ба функсияи муқаррарии Clojure табдил диҳед:
(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" ...} ...)
Бо риояи принсипи "SQL худ аз худ, Clojure худ аз худ", шумо ба даст меоред:
- Ҳеҷ гуна тааҷҷубовар нест. Пойгоҳи шумо (мисли ҳама гуна дигар) 100% бо стандарти SQL мувофиқ нест - аммо ин барои Yesql муҳим нест. Шумо ҳеҷ гоҳ вақтро барои шикори функсияҳо бо синтаксиси муодили SQL сарф намекунед. Шумо ҳеҷ гоҳ набояд ба функсия баргардед (raw-sql "баъзе('funky'::SYNTAX)")).
- Дастгирии беҳтарин муҳаррир. Муҳаррири шумо аллакай дастгирии аълои SQL дорад. Бо захира кардани SQL ҳамчун SQL шумо метавонед онро танҳо истифода баред.
- Мутобиқати даста. DBA-ҳои шумо метавонанд SQL-ро, ки шумо дар лоиҳаи Clojure истифода мебаред, хонда ва нависад.
- Танзими иҷрои осонтар. Оё шумо бояд нақшаи як дархости мушкилро таҳия кунед? Вақте ки дархости шумо SQL муқаррарӣ аст, ин мушкилот нест.
- Истифодаи такрории дархостҳо. Он файлҳои SQL-ро ба лоиҳаҳои дигар кашед ва партоед, зеро он танҳо SQL-и оддии кӯҳна аст - танҳо онро мубодила кунед.
Ба андешаи ман, идея хеле аҷиб ва дар айни замон хеле содда аст, ки ба шарофати он лоиҳа бисёр чизҳоро ба даст овард
Менеҷерони IDE ва DB
Биёед бо як вазифаи оддии ҳаррӯза оғоз кунем. Аксар вақт ба мо лозим меояд, ки баъзе объектҳоро дар базаи маълумот ҷустуҷӯ кунем, масалан, ҷадвалро дар схема пайдо кунем ва сохтори онро омӯзем (кадом сутунҳо, калидҳо, индексҳо, маҳдудиятҳо ва ғайра истифода мешаванд). Ва аз ҳама гуна IDE графикӣ ё каме мудири DB, пеш аз ҳама, мо маҳз ин қобилиятҳоро интизорем. Барои он ки он зуд бошад ва ба шумо лозим нест, ки ним соат интизор шавед, то равзанаи дорои маълумоти зарурӣ (хусусан бо пайвасти суст ба пойгоҳи додаҳои дурдаст) ва ҳамзамон, маълумоти гирифташуда тоза ва мувофиқ бошад, ва партовҳои кэш нашудаанд. Гузашта аз ин, базаи маълумот ҳар қадар мураккабтар ва калонтар бошад ва шумораи онҳо зиёд бошад, иҷрои ин кор ҳамон қадар мушкилтар мешавад.
Аммо одатан ман мушро мепартоям ва танҳо код менависам. Фарз мекунем, ки шумо бояд бифаҳмед, ки кадом ҷадвалҳо (ва бо кадом хосиятҳо) дар схемаи "HR" мавҷуданд. Дар аксари DBMS, натиҷаи дилхоҳро бо ин дархости оддӣ аз information_schema ба даст овардан мумкин аст:
select table_name
, ...
from information_schema.tables
where schema = 'HR'
Аз махзани маълумот то махзани маълумот, мундариҷаи чунин ҷадвалҳои истинод вобаста ба имкониятҳои ҳар як DBMS фарқ мекунанд. Ва, масалан, барои MySQL, аз ҳамон як маълумотнома шумо метавонед параметрҳои ҷадвалро, ки ба ин DBMS хос аст, гиред:
select table_name
, storage_engine -- Используемый "движок" ("MyISAM", "InnoDB" etc)
, row_format -- Формат строки ("Fixed", "Dynamic" etc)
, ...
from information_schema.tables
where schema = 'HR'
Oracle information_schema-ро намедонад, аммо дорад
select table_name
, pct_free -- Минимум свободного места в блоке данных (%)
, pct_used -- Минимум используемого места в блоке данных (%)
, last_analyzed -- Дата последнего сбора статистики
, ...
from all_tables
where owner = 'HR'
ClickHouse истисно нест:
select name
, engine -- Используемый "движок" ("MergeTree", "Dictionary" etc)
, ...
from system.tables
where database = 'HR'
Чизи ба ин монандро дар Кассандра анҷом додан мумкин аст (ки дорои оилаҳои сутунҳо ба ҷои ҷадвалҳо ва фазои калидҳо ба ҷои схемаҳо):
select columnfamily_name
, compaction_strategy_class -- Стратегия сборки мусора
, gc_grace_seconds -- Время жизни мусора
, ...
from system.schema_columnfamilies
where keyspace_name = 'HR'
Барои аксари дигар пойгоҳи додаҳо, шумо инчунин метавонед саволҳои шабеҳро пешниҳод кунед (ҳатто Mongo дорои
Албатта, бо ин рох на танхо дар бораи чадвалхо, балки умуман дар бораи ягон объект маълумот гирифтан мумкин аст. Баъзан одамони меҳрубон чунин кодро барои пойгоҳи додаҳои гуногун мубодила мекунанд, масалан, дар силсилаи мақолаҳои хабра "Функсияҳо барои ҳуҷҷатгузории пойгоҳи додаҳои PostgreSQL" (
Дар натиҷа, ин усули паймоиш ва ҷустуҷӯи объектҳо хеле чандиртар аст, вақти зиёдро сарфа мекунад ва ба шумо имкон медиҳад, ки маълумотро дар шакле, ки ҳоло зарур аст, гиред (чунон ки, масалан, дар мақола тасвир шудааст)
Амалиёт бо объектҳо
Пас аз он ки мо объектҳои заруриро ёфтем ва омӯзем, вақти он расидааст, ки бо онҳо ягон кори муфид анҷом диҳем. Табиист, ки инчунин бидуни гирифтани ангуштони худ аз клавиатура.
Ба касе пӯшида нест, ки танҳо нест кардани ҷадвал тақрибан дар ҳама базаҳои маълумот якхела хоҳад буд:
drop table hr.persons
Аммо бо ташкили ҷадвал он ҷолибтар мешавад. Қариб ҳама DBMS (аз ҷумла бисёр NoSQL) метавонанд дар ин ё он шакл "ҷадвал эҷод кунанд" ва қисми асосии он ҳатто каме фарқ мекунад (ном, рӯйхати сутунҳо, намудҳои маълумот), аммо тафсилоти дигар метавонанд ба таври назаррас фарқ кунанд ва аз он вобаста бошанд. дастгоҳи дохилӣ ва имкониятҳои DBMS мушаххас. Намунаи дӯстдоштаи ман ин аст, ки дар ҳуҷҷатҳои Oracle танҳо BNF-ҳои "бараҳна" барои синтаксиси "сохтани ҷадвал" мавҷуданд.
Инчунин, бисёре аз DBMS-ҳо намудҳои махсуси объектҳои худро доранд, ки дар дигар МДМ мавҷуд нестанд. Гузашта аз ин, мо метавонем амалиётҳоро на танҳо дар объектҳои пойгоҳи додаҳо, балки дар худи DBMS иҷро кунем, масалан, равандро «кушед», як қисми хотираро озод кунед, пайгирӣро фаъол созед, ба режими «танҳо барои хондан» гузаред ва ғайра.
Акнун биёед каме тасвир кунем
Яке аз вазифаҳои маъмултарин ин сохтани диаграмма бо объектҳои пойгоҳи додаҳо ва дидани объектҳо ва робитаҳои байни онҳо дар тасвири зебо мебошад. Қариб ҳама гуна IDE графикӣ, утилитаҳои алоҳидаи "хати фармон", асбобҳои махсуси графикӣ ва моделсозон метавонанд ин корро кунанд. Онҳо барои шумо чизеро "то ҳадди имкон метавонанд" ҷалб кунанд ва шумо метавонед ба ин раванд танҳо бо ёрии чанд параметр дар файли конфигуратсия ё қуттиҳои қайд дар интерфейс каме таъсир расонед.
Аммо ин масъаларо хеле соддатар, чандиртар ва шево ва албатта бо ёрии код хал кардан мумкин аст. Барои сохтани диаграммаҳои ҳама гуна мураккабӣ, мо якчанд забонҳои махсуси аломатгузорӣ дорем (DOT, GraphML ва ғайра) ва барои онҳо як пароканиши пурраи барномаҳо (GraphViz, PlantUML, Mermaid), ки метавонанд ин гуна дастурҳоро хонанд ва онҳоро дар форматҳои гуногун тасаввур кунанд. . Хуб, мо аллакай медонем, ки чӣ тавр дар бораи объектҳо ва робитаҳои байни онҳо маълумот гирифтан мумкин аст.
Ин як мисоли хурди он аст, ки ин метавонад бо истифода аз PlantUML ва
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'
Ва агар шумо каме кӯшиш кунед, пас дар асоси
Дархости SQL каме мураккабтар аст
-- Шапка
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'
Агар шумо бодиққат назар кунед, дар зери сарпӯш бисёр асбобҳои визуализатсия низ дархостҳои шабеҳро истифода мебаранд. Дуруст аст, ки ин дархостҳо одатан амиқанд
Метрикҳо ва мониторинг
Биёед ба мавзӯи анъанавии мураккаб - мониторинги иҷрои пойгоҳи додаҳо гузарем. Ман як ҳикояи ҳақиқии хурдеро ба ёд меорам, ки "яке аз дӯстонам" ба ман гуфта буд. Дар лоиҳаи дигар як DBA-и пурқудрат зиндагӣ мекард ва каме аз таҳиягарон ӯро шахсан мешинохтанд ё боре ӯро шахсан дидаанд (бо вуҷуди он, ки тибқи овозаҳо, ӯ дар ягон бинои дигар кор мекард). Дар соати "X", вақте ки системаи подукционии як фурӯшандаи калон бори дигар "бад ҳис" кард, вай хомӯшона скриншотҳои графикҳоро аз Менеҷери Enterprise Oracle фиристод, ки дар онҳо ҷойҳои муҳимро бо аломати сурх барои "фаҳмо будан" бодиққат қайд кард ( ин, нарм карда гуем, чандон ёрй нарасонд). Ва дар асоси ин «фотокарта» ман бояд табобат кунам. Дар айни замон, ҳеҷ кас ба мудири корхонаи қиматбаҳо (ба ҳар ду маънои калима) дастрасӣ надошт, зеро система мураккаб ва гарон аст, ногаҳон «таҳиягарон ба чизе пешпо мехӯранд ва ҳама чизро мешикананд». Аз ин рӯ, таҳиягарон "ба таври таҷрибавӣ" макон ва сабаби тормозҳоро пайдо карданд ва ямоқи онро бароварданд. Агар дар ояндаи наздик мактуби тахдидкунандаи ДБА нарасид, пас хама нафаси сабук кашида, ба кори имрузаи худ бармегарданд (то мактуби нав).
Аммо раванди мониторинг метавонад шавқовартар ва дӯстона ва муҳимтар аз ҳама, барои ҳама дастрас ва шаффоф ба назар расад. Ҳадди ақал қисми асосии он, ҳамчун илова ба системаҳои асосии мониторинг (ки албатта муфид ва дар бисёр ҳолатҳо ивазнашавандаанд). Ҳама гуна DBMS ройгон ва комилан ройгон аст, то маълумотро дар бораи ҳолати кунунӣ ва иҷрои он мубодила кунад. Дар ҳамон Oracle DB "хундор" тақрибан ҳама гуна маълумотро дар бораи иҷроиш аз намуди система, аз равандҳо ва сеансҳо то ҳолати кэши буферӣ гирифтан мумкин аст (масалан,
Ҳамин тариқ, бо як намуди коллекторҳои метрикӣ (Telegraf, Metricbeat, Collectd), ки метавонад дархостҳои фармоишии sql-ро иҷро кунад, нигоҳдории ин метрикҳо (InfluxDB, Elasticsearch, Timescaledb) ва визуализатор (Grafana, Kibana), шумо метавонед хеле осон ба даст оред. ва системаи мониторинги чандир, ки бо дигар ченакҳои системавӣ зич муттаҳид карда мешавад (масалан, аз сервери барномаҳо, аз ОС ва ғ. гирифта мешавад). Масалан, ин дар pgwatch2 анҷом дода мешавад, ки омезиши InfluxDB + Grafana ва маҷмӯи дархостҳоро барои намоишҳои система истифода мебарад, ки ба онҳо низ дастрас шудан мумкин аст.
Ҳамагӣ
Ва ин танҳо як рӯйхати тахминии он чизест, ки бо пойгоҳи додаи мо бо истифода аз рамзи муқаррарии SQL чӣ кор кардан мумкин аст. Ман боварӣ дорам, ки шумо метавонед бисёр истифодаҳоро пайдо кунед, дар шарҳҳо нависед. Ва мо дар бораи он сӯҳбат хоҳем кард, ки чӣ гуна (ва муҳимтар аз ҳама, чаро) ин ҳамаро автоматӣ кунем ва дафъаи оянда онро ба лӯлаи CI/CD дохил кунем.
Манбаъ: will.com