SQLããã以äžã«ç°¡åãªãã®ã¯ãªãã§ãããã? ç§ãã¡ã¯ããããç°¡åãªãªã¯ãšã¹ããæžãããšãã§ããŸã - ç§ãã¡ã¯å
¥åããŸã selectãå¿
èŠãªåããªã¹ãããŠããã ãããããŒãã«åãããã€ãã®æ¡ä»¶ ã³ã©ãã¬ãŒ ããã ãã§ã - æçšãªããŒã¿ã¯ãã±ããã®äžã«ããããã®æç¹ã§ã©ã® 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 è¡šçŸã¯çŽ æŽãããã§ãããããã§ã¯äœãæ°ãããã®ã¯è¿œå ãããŸããã ãã®çµæãæ¬åŒ§ã®ããã®æ¬åŒ§ãåŸãããŸãã äžè³æïŒ æ¬¡ã«ãããŒã¿ããŒã¹äžã®æœè±¡åãæŒãå§ããé¢æ°ãšã®æŠããå§ãŸãç¬éãåŸ ã¡ãŸãã (çã®SQL)
ããã§ãã©ãããã°ããã§ããããïŒ SQL ãéåžžã® SQL ã®ãŸãŸã«ããŠãããŸã (ãªã¯ãšã¹ãããšã« XNUMX ã€ã®ãã¡ã€ã«)ã
-- 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 åäœãã®ååã«åŸãããšã§ã次ã®ããšãåŸãããŸãã
- æ§æçã«é©ããããªããšã¯ãããŸããã ããªãã®ããŒã¿ããŒã¹ã¯ (ä»ã®ããŒã¿ããŒã¹ãšåæ§ã«) SQL æšæºã« 100% æºæ ããŠããããã§ã¯ãããŸãããããã㯠Yesql ã«ãšã£ãŠã¯åé¡ã§ã¯ãããŸããã SQL ãšåçã®æ§æãæã€é¢æ°ãæ¢ããŠæéãç¡é§ã«ããããšã¯ãããŸããã é¢æ°ã«æ»ãå¿ èŠã¯ãããŸãã (raw-sql "some('funky'::SYNTAX)")).
- æé«ã®ãšãã£ã¿ãŒã®ãµããŒãã ãšãã£ã¿ã«ã¯ãã§ã«åªãã SQL ãµããŒããåãã£ãŠããŸãã SQL ã SQL ãšããŠä¿åãããšãç°¡åã«äœ¿çšã§ããŸãã
- ããŒã ã®äºææ§ã DBA ã¯ãClojure ãããžã§ã¯ãã§äœ¿çšãã SQL ãèªã¿æžãã§ããŸãã
- ããã©ãŒãã³ã¹ã®ãã¥ãŒãã³ã°ã容æã«ãªããŸãã åé¡ã®ããã¯ãšãªã®èšç»ãç«ãŠãå¿ èŠããããŸãã? ã¯ãšãªãéåžžã® SQL ã§ããå Žåãããã¯åé¡ã«ãªããŸããã
- ã¯ãšãªã®åå©çšã ããã¯åãªãå€ã SQL ãªã®ã§ãåã SQL ãã¡ã€ã«ãä»ã®ãããžã§ã¯ãã«ãã©ãã° ã¢ã³ã ããããããŠãå ±æããã ãã§ãã
ç§ã®æèŠã§ã¯ããã®ã¢ã€ãã¢ã¯éåžžã«ã¯ãŒã«ã§ãããšåæã«éåžžã«ã·ã³ãã«ã§ããããã®ãããã§ãã®ãããžã§ã¯ãã¯å€ãã®æ¯æãåŸãŸããã
IDE ããã³ DB ãããŒãžã£ãŒ
ãŸãã¯ç°¡åãªæ¥åžžæ¥åããå§ããŸãããã å€ãã®å ŽåãããŒã¿ããŒã¹å ã®ãªããžã§ã¯ããæ€çŽ¢ããå¿ èŠããããŸããããšãã°ãã¹ããŒãå ã®ããŒãã«ãèŠã€ããŠããã®æ§é (ã©ã®ãããªåãããŒãã€ã³ããã¯ã¹ãå¶çŽã䜿çšãããŠããã) ã調ã¹ãå¿ èŠããããŸãã ãããŠãã°ã©ãã£ã«ã« IDE ãå°ã㪠DB ãããŒãžã£ãŒã«ã¯ããŸã第äžã«ããŸãã«ãããã®æ©èœãæåŸ ãããŸãã é«éã§ãå¿ èŠãªæ å ±ãå«ããŠã£ã³ããŠã衚瀺ããããŸã§ XNUMX åãåŸ ã€å¿ èŠããªã (ç¹ã«ãªã¢ãŒã ããŒã¿ããŒã¹ãžã®æ¥ç¶ãé ãå Žå)ãåæã«åãåã£ãæ å ±ãæ°é®®ã§é¢é£æ§ãããããããã£ãã·ã¥ããããžã£ã³ã¯ã§ã¯ãããŸããã ããã«ãããŒã¿ããŒã¹ãè€éã§å€§èŠæš¡ã«ãªãããã®æ°ãå¢ããã»ã©ããããè¡ãããšã¯é£ãããªããŸãã
ããããéåžžã¯ããŠã¹ãæšãŠãŠã³ãŒããæžãã ãã§ãã ã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'
Cassandra ã§ãåæ§ã®ããšãã§ããŸã (ããŒãã«ã®ä»£ããã«åãã¡ããªãŒããããã¹ããŒãã®ä»£ããã«ããŒã¹ããŒã¹ããããŸã)ã
select columnfamily_name
, compaction_strategy_class -- СÑÑаÑÐµÐ³ÐžÑ ÑбПÑкО ÐŒÑÑПÑа
, gc_grace_seconds -- ÐÑÐµÐŒÑ Ð¶ÐžÐ·ÐœÐž ÐŒÑÑПÑа
, ...
from system.schema_columnfamilies
where keyspace_name = 'HR'
ä»ã®ã»ãšãã©ã®ããŒã¿ããŒã¹ã§ããåæ§ã®ã¯ãšãªãäœæã§ããŸã (Mongo ã§ããã
ãã¡ããããã®æ¹æ³ã§ã¯ãããŒãã«ã«é¢ããæ
å ±ã ãã§ãªãããªããžã§ã¯ãå
šè¬ã«é¢ããæ
å ±ãååŸã§ããŸãã ããšãã°ãhabra ã®äžé£ã®èšäºãPostgreSQL ããŒã¿ããŒã¹ãææžåããããã®é¢æ°ã(
ãã®çµæããªããžã§ã¯ããããã²ãŒãããŠæ€çŽ¢ãããã®æ¹æ³ã¯ããæè»ã«ãªããæéã倧å¹
ã«ç¯çŽããå¿
èŠãªåœ¢åŒã§æ
å ±ãæ£ç¢ºã«ååŸã§ããããã«ãªããŸã (ããšãã°ã次ã®æçš¿ã§èª¬æãããŠããŸã)ã
ãªããžã§ã¯ãæäœ
å¿ èŠãªãªããžã§ã¯ããèŠã€ããŠèª¿ã¹ããããããã䜿ã£ãŠäœã圹ã«ç«ã€ããšãããŠã¿ãŸãããã ãã¡ãããããŒããŒãããæãé¢ãå¿ èŠããããŸããã
ããŒãã«ãåé€ããã ãã§ã¯ãã»ãšãã©ãã¹ãŠã®ããŒã¿ããŒã¹ã§åãããã«èŠããããšã¯åšç¥ã®äºå®ã§ãã
drop table hr.persons
ããããããŒãã«ãäœæãããšãããã«é¢çœããªããŸãã ã»ãšãã©ãã¹ãŠã® DBMS (å€ãã® NoSQL ãå«ã) ã¯ãäœããã®åœ¢åŒã§ãããŒãã«ãäœæãââã§ãããã®äž»èŠéšå (ååãåã®ãªã¹ããããŒã¿å) ã¯ãããã«ç°ãªããŸããããã®ä»ã®è©³çŽ°ã¯å€§å¹
ã«ç°ãªãå¯èœæ§ããããããŒã¿ããŒã¹ã«äŸåããŸããå
éšããã€ã¹ãšç¹å®ã® DBMS ã®æ©èœã ç§ã®ãæ°ã«å
¥ãã®äŸã¯ãOracle ã®ããã¥ã¡ã³ãã«ã¯ãããŒãã«äœæãæ§æã®ã裞ã®ãBNF ããååšããªãããšã§ãã
ãŸããå€ãã® DBMS ã«ã¯ãä»ã® DBMS ã§ã¯äœ¿çšã§ããªãç¬èªã®ç¹å®ã®ã¿ã€ãã®ãªããžã§ã¯ãããããŸãã ããã«ãããŒã¿ããŒã¹ ãªããžã§ã¯ãã ãã§ãªããDBMS èªäœã«å¯ŸããŠãæäœãå®è¡ã§ããŸããããšãã°ãããã»ã¹ãã匷å¶çµäºãããäžéšã®ã¡ã¢ãªé åã解æŸãããã¬ãŒã¹ãæå¹ã«ãããèªã¿åãå°çšãã¢ãŒãã«åãæ¿ãããªã©ã§ãã
ã§ã¯ãå°ãæããŠã¿ãŸããã
æãäžè¬çãªã¿ã¹ã¯ã® XNUMX ã€ã¯ãããŒã¿ããŒã¹ ãªããžã§ã¯ããå«ãå³ãæ§ç¯ãããªããžã§ã¯ããšãªããžã§ã¯ãéã®æ¥ç¶ãçŸããå³ã§ç¢ºèªããããšã§ãã ã»ãŒãã¹ãŠã®ã°ã©ãã£ã«ã« 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ãæéã倧æå°å£²åºã®è²©å£²ã·ã¹ãã ãåã³ã調åãæªããªããå§ãããšãã圌ã¯é»ã£ãŠ Oracle Enterprise Manager ããã°ã©ãã®ã¹ã¯ãªãŒã³ã·ã§ãããéä¿¡ãããåããããããã®ããã«éèŠãªå Žæãèµ€ãããŒã«ãŒã§æ éã«åŒ·èª¿è¡šç€ºããŸãã (æ§ããã«èšã£ãŠããããã¯ããŸã圹ã«ç«ã¡ãŸããã§ãã)ã ãããŠããã®ããã©ãã«ãŒãããããšã«æ²»çãããããšã«ãªããŸããã åæã«ã貎é㪠(äž¡æ¹ã®æå³ã§) Enterprise Manager ã«ã¢ã¯ã»ã¹ã§ãã人ã¯èª°ãããŸããã§ããã ã·ã¹ãã ãè€éã§é«äŸ¡ãªãããçªç¶ãéçºè ãäœãã«ã€ãŸãããŠãã¹ãŠãå£ããŠããŸããã®ã§ãã ãããã£ãŠãéçºè ã¯ãçµéšçã«ããã¬ãŒãã®å Žæãšåå ãç¹å®ãããããããªãªãŒã¹ããŸããã DBA ããã®è è¿«çãªæçŽãè¿ãå°æ¥åã³å±ããªãã£ããã誰ããå®å µã®ããæ¯ãã€ããçŸåšã®ä»äºã«æ»ãã§ããã (æ°ããæçŽãå±ããŸã§)ã
ããããç£èŠããã»ã¹ã¯ãã楜ãããã¬ã³ããªãŒã«èŠããå¯èœæ§ããããæãéèŠãªããšã¯ã誰ã«ãšã£ãŠãã¢ã¯ã»ã¹å¯èœã§éææ§ãããããšã§ãã å°ãªããšããã®åºæ¬çãªéšåã¯ãäž»èŠãªç£èŠã·ã¹ãã (確ãã«äŸ¿å©ã§ãå€ãã®å Žå代æ¿äžå¯èœãªãã®) ãžã®è¿œå ãšããŠã®ãã®ã§ãã DBMS ã¯ãçŸåšã®ç¶æ
ãšããã©ãŒãã³ã¹ã«é¢ããæ
å ±ãå®å
šã«ç¡æã§å
±æã§ããŸãã åããè¡ãŸã¿ããã® Oracle DB ã§ã¯ãããã»ã¹ãã»ãã·ã§ã³ãããããã¡ ãã£ãã·ã¥ã®ç¶æ
ã«è³ããŸã§ãããã©ãŒãã³ã¹ã«é¢ããã»ãšãã©ãã¹ãŠã®æ
å ±ãã·ã¹ãã ãã¥ãŒããååŸã§ããŸã (ããšãã°ã
ãããã£ãŠãã«ã¹ã¿ã SQL ã¯ãšãªãå®è¡ã§ããããçš®ã®ã¡ããªã¯ã¹ ã³ã¬ã¯ã¿ãŒ (TelegrafãMetricbeatãCollectd)ããããã®ã¡ããªã¯ã¹ã®ã¹ãã¬ãŒãž (InfluxDBãElasticsearchãTimescaledb)ãããã³ããžã¥ã¢ã©ã€ã¶ (GrafanaãKibana) ãåããŠãããããããªãç°¡åã«ãããŠãä»ã®ã·ã¹ãã å
šäœã®ã¡ããªã¯ã¹ (ããšãã°ãã¢ããªã±ãŒã·ã§ã³ ãµãŒããŒãOS ãªã©ããååŸ) ãšç·å¯ã«çµ±åãããæè»ãªç£èŠã·ã¹ãã ã ããšãã°ããã㯠pgwatch2 ã§è¡ãããInfluxDB + Grafana ã®çµã¿åãããšãã·ã¹ãã ãã¥ãŒãžã®äžé£ã®ã¯ãšãªã䜿çšããŸãããããã®ãã¥ãŒã«ãã¢ã¯ã»ã¹ã§ããŸãã
åèšã§
ããã¯ãéåžžã® SQL ã³ãŒãã䜿çšããŠããŒã¿ããŒã¹ã§å®è¡ã§ããããšã®ããããã®ãªã¹ãã«ãããŸããã ä»ã«ãããããã®äœ¿ãæ¹ãèŠã€ãããšæããŸãã®ã§ãã³ã¡ã³ãã«æžããŠãã ããã 次åã¯ãããããã¹ãŠãèªååã㊠CI/CD ãã€ãã©ã€ã³ã«çµã¿èŸŒãæ¹æ³ (ãããŠæãéèŠãªçç±) ã«ã€ããŠèª¬æããŸãã
åºæïŒ habr.com