"د کوډ په توګه ډیټابیس" تجربه

"د کوډ په توګه ډیټابیس" تجربه

SQL، څه ساده کیدی شي؟ موږ هر یو کولی شو ساده غوښتنه ولیکئ - موږ ټایپ کوو غوره، بیا اړین کالمونه لیست کړئ لهد میز نوم، ځینې شرایط په کې هلته او دا ټول دي - ګټور معلومات زموږ په جیب کې دي، او (تقریبا) پرته لدې چې DBMS په هغه وخت کې د هود لاندې وي (یا شاید هیڅ DBMS نه دی). د پایلې په توګه، د نږدې هرې ډاټا سرچینې سره کار کول (متعلق او داسې نه) د عادي کوډ له نظره په پام کې نیول کیدی شي (د ټولو سره چې دا معنی لري - د نسخې کنټرول، د کوډ بیاکتنه، جامد تحلیل، اتوماتیک، او دا ټول دي). او دا نه یوازې پخپله ډاټا، سکیمونو او مهاجرتونو باندې تطبیق کیږي، مګر په عمومي توګه د ذخیره کولو ټول ژوند ته. پدې مقاله کې به موږ د ورځني کارونو او د "کوډ په توګه ډیټابیس" د لینز لاندې د مختلف ډیټابیسونو سره د کار کولو ستونزو په اړه وغږیږو.

او راځئ چې له سمې څخه پیل وکړو اورم. د "SQL vs ORM" ډول لومړۍ جګړې بیرته په نښه شوي پری پیټرین روس.

د اعتراض-اړیکو نقشه کول

د 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 نفرت".

د خنډونو په بل اړخ کې ، د خالص "لاسي جوړ" SQL پیروان د اضافي پرتونو او خلاصونونو پرته د دوی د DBMS څخه ټول جوس د راټولولو وړتیا یادونه کوي. د پایلې په توګه، "ډیټا متمرکز" پروژې ښکاري، چیرې چې ځانګړي روزل شوي خلک په ډیټابیس کې ښکیل دي (دوی هم "بنسټیسټان" دي، دوی "بنسټیسټان" هم دي، دوی "بیسډینر" هم دي، او داسې نور.) یوازې د چمتو شوي نظرونو او زیرمه شوي طرزالعملونو "راوبښلو" ته اړتیا لري، پرته له دې چې توضیحاتو ته لاړ شي.

څه که موږ د دواړو نړۍ غوره درلودل؟ دا څنګه د ژوند تصدیق کونکي نوم سره په زړه پورې وسیلې کې ترسره کیږي Yesql. زه به زما په وړیا ژباړه کې د عمومي مفکورې څخه یو څو کرښې درکړم، او تاسو کولی شئ په ډیر تفصیل سره ورسره آشنا شئ دلته.

کلوجور د DSLs رامینځته کولو لپاره ښه ژبه ده ، مګر SQL پخپله یو ښه DSL دی ، او موږ بل ته اړتیا نلرو. د S- څرګندونه خورا ښه دي، مګر دوی دلته هیڅ نوي نه اضافه کوي. د پایلې په توګه، موږ د قوسونو لپاره بریکٹونه ترلاسه کوو. موافق نه یاست؟ بیا هغه شیبې ته انتظار وکړئ کله چې د ډیټابیس خلاصول لیک پیل شي او تاسو د فنکشن سره مبارزه پیل کړئ (raw-sql)

نو زه باید څه وکړم؟ راځئ چې SQL د منظم SQL په توګه پریږدو - د هرې غوښتنې یوه فایل:

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

... او بیا دا فایل ولولئ، دا په منظم کلوجور فعالیت بدل کړئ:

(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 په واسطه، د ځان په واسطه کلوجر" اصولو ته په تعقیب سره، تاسو ترلاسه کوئ:

  • هیڅ ترکیبي حیرانتیا نشته. ستاسو ډیټابیس (د نورو په څیر) د SQL معیار سره 100٪ مطابقت نلري - مګر دا د Yesql لپاره مهم ندي. تاسو به هیڅکله د SQL مساوي ترکیب سره د دندو په لټه کې وخت ضایع نه کړئ. تاسو به هیڅکله د فنکشن ته بیرته راشئ (raw-sql "some('funky'::SYNTAX)")).
  • د غوره مدیر ملاتړ. ستاسو مدیر لا دمخه د غوره SQL ملاتړ لري. د SQL په توګه د SQL خوندي کولو سره تاسو کولی شئ په ساده ډول دا وکاروئ.
  • د ټیم مطابقت. ستاسو DBAs کولی شي هغه SQL ولولي او ولیکئ چې تاسو یې په خپل کلوجور پروژه کې کاروئ.
  • د فعالیت آسانه تنظیم کول. د یوې ستونزې لرونکي پوښتنې لپاره پلان جوړولو ته اړتیا لرئ؟ دا کومه ستونزه نده کله چې ستاسو پوښتنه منظم SQL وي.
  • د پوښتنو بیا کارول. ورته SQL فایلونه نورو پروژو ته کش کړئ او پریږدئ ځکه چې دا یوازې ساده زوړ SQL دی - یوازې یې شریک کړئ.

زما په اند، نظر خورا ښه دی او په ورته وخت کې خورا ساده دی، له دې امله چې پروژې ډیری لاسته راوړنې ترلاسه کړې پیروان په مختلفو ژبو. او موږ به بیا هڅه وکړو چې د ORM څخه هاخوا د هرڅه څخه د SQL کوډ جلا کولو ورته فلسفه پلي کړو.

د IDE او DB مدیران

راځئ چې د یو ساده ورځني کار سره پیل وکړو. ډیری وختونه موږ باید په ډیټابیس کې د ځینې شیانو لټون وکړو، د بیلګې په توګه، په سکیما کې یو جدول ومومئ او د هغې جوړښت مطالعه کړئ (کوم کالمونه، کیلي، شاخصونه، خنډونه، او نور کارول کیږي). او د هر ډول ګرافیکي IDE یا یو کوچني DB مدیر څخه ، له هرڅه دمخه ، موږ واقعیا د دې وړتیاو تمه کوو. د دې لپاره چې دا ګړندی وي او تاسو اړتیا نلرئ نیم ساعت انتظار وکړئ تر هغه چې د اړینو معلوماتو سره یوه کړکۍ رسم شي (په ځانګړي توګه د لیرې ډیټابیس سره د ورو اړیکې سره) ، او په ورته وخت کې ترلاسه شوي معلومات تازه او اړونده دي ، او نه زیرمه شوي کثافات. سربیره پردې ، څومره چې ډیټابیس خورا پیچلی او لوی وي او د دوی شمیر ډیر وي ، نو دا کار کول خورا ستونزمن وي.

مګر معمولا زه موږک لرې غورځوم او یوازې کوډ لیکم. راځئ چې ووایو تاسو اړتیا لرئ ومومئ چې کوم میزونه (او کوم ملکیتونه) په "HR" سکیما کې شتون لري. په ډیری DBMSs کې، مطلوب پایله د معلوماتو_ سکیما څخه د دې ساده پوښتنې سره ترلاسه کیدی شي:

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'

اوریکل د معلوماتو_ سکیما نه پوهیږي، مګر دا لري اوریکل میټاډاټا، او کومه لویه ستونزه نه رامینځته کیږي:

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'

د ډیری نورو ډیټابیسونو لپاره ، تاسو کولی شئ ورته پوښتنو سره هم راشئ (حتی مونګو لري د ځانګړي سیسټم راټولول، کوم چې په سیسټم کې د ټولو راټولولو په اړه معلومات لري).

البته، پدې توګه تاسو کولی شئ نه یوازې د میزونو په اړه معلومات ترلاسه کړئ، مګر په عمومي توګه د هر شی په اړه. وخت په وخت، مهربان خلک د مختلفو ډیټابیسونو لپاره دا ډول کوډ شریکوي، لکه د مثال په توګه، د هابرا مقالو لړۍ کې "د PostgreSQL ډیټابیسونو مستند کولو لپاره دندې" (ایب, بین, جم). البته، د پوښتنو دا ټول غر زما په سر کې ساتل او په دوامداره توګه یې ټایپ کول د خوښۍ وړ دي، نو زما په زړه پورې IDE/ایډیټر کې زه د ډیری کارول شویو پوښتنو لپاره د مخکې څخه چمتو شوي ټوټې لرم، او ټول هغه څه چې پاتې دي د ټایپ کولو لپاره دي. په کينډۍ کې د څيزونو نومونه

د پایلې په توګه، د شیانو د نیولو او لټون کولو دا طریقه خورا انعطاف وړ ده، ډیر وخت خوندي کوي، او تاسو ته اجازه درکوي دقیق معلومات په هغه شکل کې ترلاسه کړئ چې اوس ورته اړین دي (لکه د بیلګې په توګه، په پوسټ کې تشریح شوي. "په هر شکل کې د ډیټابیس څخه د معلوماتو صادرول: IDEs په IntelliJ پلیټ فارم کې څه کولی شي").

د شیانو سره عملیات

وروسته له دې چې موږ اړین توکي وموندل او مطالعه کړل، دا وخت دی چې د دوی سره یو څه ګټور کار وکړو. په طبیعي توګه، پرته له دې چې ستاسو ګوتې له کیبورډ څخه لرې کړئ.

دا هیڅ راز پټ نه دی چې په ساده ډول د میز حذف کول به نږدې ټولو ډیټابیسونو کې ورته ښکاري:

drop table hr.persons

مګر د میز په جوړولو سره دا ډیر په زړه پوري کیږي. نږدې هر DBMS (د ډیری NoSQL په شمول) کولی شي په یوه یا بل شکل کې "جدول رامینځته کړي" او د هغې اصلي برخه به حتی یو څه توپیر ولري (نوم، د کالمونو لیست، د ډیټا ډولونه)، مګر نور توضیحات په ډراماتیک ډول توپیر کولی شي او په دې پورې اړه لري. د یو ځانګړي DBMS داخلي وسیله او وړتیاوې. زما غوره بیلګه دا ده چې د اوریکل اسنادو کې د "میز جوړولو" ترکیب لپاره یوازې "ننګره" BNFs شتون لري 31 مخونه نیول. نور DBMSs ډیر معمولي وړتیاوې لري، مګر هر یو یې د میزونو جوړولو لپاره ډیری په زړه پورې او ځانګړي ځانګړتیاوې لري (پوسته, مای, کاکروچ, کیسندرا). دا امکان نلري چې د بل IDE څخه کوم ګرافیکي "جادوګر" (په ځانګړي توګه یو نړیوال) به وکولی شي دا ټول وړتیاوې په بشپړ ډول پوښي ، او حتی که دا کولی شي ، دا به د زړه د ضعیف لپاره تماشا نه وي. په ورته وخت کې، په سمه توګه او پر وخت لیکل شوی بیان میز جوړ کړئ تاسو ته به اجازه درکړي په اسانۍ سره دا ټول وکاروئ ، ذخیره کړئ او ستاسو ډیټا ته لاسرسی د باور وړ ، غوره او د امکان تر حده راحته کړئ.

همدارنګه، ډیری DBMSs خپل ځانګړي ډولونه لري چې په نورو DBMSs کې شتون نلري. سربیره پردې ، موږ کولی شو عملیات نه یوازې د ډیټابیس شیانو کې ترسره کړو ، بلکه پخپله DBMS کې هم ترسره کړو ، د مثال په توګه ، یوه پروسه "وژل" ، د حافظې ځینې ساحې خلاصې کړئ ، د تعقیب وړ کړئ ، "یوازې لوستل" حالت ته واړوئ او نور ډیر څه.

اوس راځئ چې لږ رسم کړو

یو له خورا عامو کارونو څخه دا دی چې د ډیټابیس شیانو سره ډیاګرام جوړ کړئ او د دوی ترمینځ شیان او اړیکې په ښکلي عکس کې وګورئ. نږدې هر ډول ګرافیکي IDE، جلا "کمانډ لاین" اسانتیاوې، ځانګړي ګرافیکي وسیلې او ماډلر کولی شي دا کار وکړي. دوی به ستاسو لپاره یو څه راوباسي "لکه څنګه چې دوی کولی شي غوره وي" او تاسو کولی شئ دا پروسه یوازې د ترتیب کولو فایل یا په انٹرفیس کې د چیک باکسونو کې د څو پیرامیټونو په مرسته یو څه اغیزه وکړئ.

مګر دا ستونزه خورا ساده ، ډیر انعطاف منونکي او ښکلي حل کیدی شي ، او البته د کوډ په مرسته. د هر ډول پیچلتیا ډیاګرامونو رامینځته کولو لپاره ، موږ ډیری ځانګړي مارک اپ ژبې لرو (DOT, GraphML etc) ، او د دوی لپاره د غوښتنلیکونو بشپړ خپریدل (GraphViz, PlantUML, Mermaid) چې کولی شي دا ډول لارښوونې ولولي او په مختلف شکلونو کې یې لید کړي. . ښه، موږ دمخه پوهیږو چې څنګه د شیانو او د دوی تر مینځ د اړیکو په اړه معلومات ترلاسه کړو.

دلته یو کوچنی مثال دی چې دا څنګه ښکاري، د PlantUML او کارولو سره د PostgreSQL لپاره ډیمو ډیټابیس (په ښي خوا کې د SQL پوښتنه ده چې د 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'

او که تاسو لږ هڅه وکړئ، نو پر بنسټ د PlantUML لپاره ER ټیمپلیټ تاسو کولی شئ د ریښتیني ER ډیاګرام سره ورته یو څه ترلاسه کړئ:

د 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" کې، کله چې د لوی پرچون پلورونکي د پوډکشن سیسټم یو ځل بیا "خراب احساس" پیل کړ، هغه په ​​​​خاموشۍ سره د اوریکل شرکت مدیر څخه د ګرافونو سکرین شاټونه واستول، په کوم کې چې هغه د "فهم" لپاره د سور مارکر سره مهم ځایونه په احتیاط سره روښانه کړل ( دا، په نرمۍ سره، ډیره مرسته نده کړې). او د دې "عکس کارت" پراساس ما درملنه کوله. په ورته وخت کې، هیڅوک قیمتي (د کلمې په دواړو حواسو کې) د شرکت مدیر ته لاسرسی نه درلود، ځکه چې سیسټم پیچلی او ګران دی، ناڅاپه "پراختیا کونکي په یو څه اخته کیږي او هرڅه ماتوي." له همدې امله، پراختیا کونکو "تجربه" د بریکونو موقعیت او لامل وموند او یو پیچ یې خپور کړ. که چیرې د DBA لخوا ګواښونکي لیک په نږدې راتلونکي کې بیرته را ونه رسی ، نو هرڅوک به د راحت ساه واخلي او خپلو اوسنیو دندو ته راستون شي (تر نوي لیک پورې).

مګر د څارنې پروسه کولی شي ډیر ساتیري او دوستانه وګوري، او تر ټولو مهم، د هرچا لپاره د لاسرسي وړ او شفاف وي. لږترلږه د هغې اساسي برخه، د اصلي څارنې سیسټمونو اضافي په توګه (کوم چې یقینا ګټور دي او په ډیری قضیو کې نه بدلیدونکي). هر DBMS د خپل اوسني حالت او فعالیت په اړه د معلوماتو شریکولو لپاره وړیا او په بشپړ ډول وړیا دی. په ورته "خوني" اوریکل DB کې ، د فعالیت په اړه نږدې هر ډول معلومات د سیسټم لیدونو څخه ترلاسه کیدی شي ، د پروسو او غونډو څخه نیولې د بفر کیچ حالت پورې (د مثال په توګه ، د DBA سکریپټ، برخه "څارنه"). Postgresql د دې لپاره د سیسټم لیدونو ټوله ډله هم لري د ډیټابیس څارنه، په ځانګړي توګه هغه چې د هر DBA ورځني ژوند کې لازمي دي ، لکه pg_stat_activity, pg_stat_database, pg_stat_bgwriter. MySQL حتی د دې لپاره جلا سکیما لري. فعالیت_سکیما. A په مونګو کې جوړ شوی پروفایلر د سیسټم راټولولو کې د فعالیت ډاټا راټولوي system.profile.

پدې توګه ، د یو ډول میټریک راټولونکي (ټیلیګراف ، میټریک بیټ ، راټول شوي) سره وسله وال چې کولی شي دودیز sql پوښتنې ترسره کړي ، د دې میټریکونو ذخیره (InfluxDB, Elasticsearch, Timescaledb) او یو لیدونکی (Grafana, Kibana) ، تاسو کولی شئ خورا اسانه ترلاسه کړئ. او د څارنې یو انعطاف منونکی سیسټم چې د نورو سیسټمونو پراخه میټریکونو سره به نږدې مدغم شي (د مثال په توګه ترلاسه شوي ، د غوښتنلیک سرور څخه ، د OS څخه او داسې نور). لکه څنګه چې، د مثال په توګه، دا په pgwatch2 کې ترسره کیږي، کوم چې د InfluxDB + Grafana ترکیب کاروي او د سیسټم لیدونو لپاره د پوښتنو یوه سیټ کاروي، کوم چې هم لاسرسی کیدی شي. دودیز پوښتنې اضافه کړئ.

ټول

او دا یوازې د هغه څه نږدې لیست دی چې زموږ د ډیټابیس سره د منظم SQL کوډ په کارولو سره ترسره کیدی شي. زه ډاډه یم چې تاسو کولی شئ ډیری نورې کارونې ومومئ، په نظرونو کې ولیکئ. او موږ به د دې په اړه وغږیږو چې څنګه (او خورا مهم ولې) دا ټول اتومات کړئ او بل ځل یې ستاسو په CI/CD پایپ لاین کې شامل کړئ.

سرچینه: www.habr.com

Add a comment