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дин жактоочулары кошумча катмарларсыз жана абстракцияларсыз СББнын бардык ширесин сыгып алуу мүмкүнчүлүгүн белгилешет. Натыйжада «дата-борбордук» долбоорлор пайда болуп, анда маалымат базасына атайын даярдалган адамдар тартылат (алар дагы «базистер», алар дагы «базистер», алар дагы «базачылар» ж.б.), иштеп чыгуучулар Болгону майда-чүйдөсүнө чейин кирбестен, даяр көрүнүштөрдү жана сакталган процедураларды "тартуу" керек.
Эгер биз эки дүйнөнүн эң жакшысына ээ болсокчы? Бул жашоону тастыктаган аты менен сонун куралда кантип жасалат
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 өзүнөн өзү" принцибин кармануу менен, сиз төмөнкүлөрдү аласыз:
- Синтаксистик сюрприз жок. Сиздин маалымат базаңыз (башкалары сыяктуу) SQL стандартына 100% туура келбейт - бирок Yesql үчүн бул маанилүү эмес. SQL эквиваленттүү синтаксиси бар функцияларды издөөгө эч качан убакыт коротпойсуз. Сиз эч качан функцияга кайтууга туура келбейт (raw-sql "some('funky'::SYNTAX)")).
- Эң мыкты редактор колдоо. Сиздин редакторуңуз мурунтан эле мыкты SQL колдоосуна ээ. SQLди SQL катары сактоо менен сиз аны жөн гана колдоно аласыз.
- Команда шайкештиги. Сиздин DBA'ларыңыз Clojure долбооруңузда колдонгон SQLди окуп жана жаза алышат.
- Оңой аткарууну жөндөө. Көйгөйлүү суроо үчүн план түзүү керекпи? Сиздин сурооңуз кадимки SQL болгондо, бул көйгөй эмес.
- Сурамдарды кайра колдонуу. Ошол эле SQL файлдарын башка долбоорлорго сүйрөп барып таштаңыз, анткени бул жөн эле эски SQL - жөн гана бөлүшүңүз.
Менин оюмча, идея абдан сонун жана ошол эле учурда абдан жөнөкөй, анын аркасында долбоор көптөгөн ээ болду
IDE жана DB менеджерлери
Жөнөкөй күнүмдүк тапшырмадан баштайлы. Көбүнчө маалымат базасынан кээ бир объекттерди издөөгө туура келет, мисалы, схемадан таблицаны таап, анын структурасын изилдөөгө туура келет (кандай мамычалар, ачкычтар, индекстер, чектөөлөр ж.б. колдонулат). Жана кандайдыр бир графикалык IDEден же кичинекей DB-менеджерден, биринчи кезекте, биз дал ушул жөндөмдөрдү күтөбүз. Бул тез жана керектүү маалыматы бар терезе тартылганга чейин жарым саат күтпөстөн (айрыкча алыскы маалымат базасына жай туташууда) жана ошол эле учурда алынган маалымат жаңы жана актуалдуу болушу үчүн, жана кэштелген таштанды эмес. Анын үстүнө, маалымат базасы канчалык татаал жана чоң болсо жана алардын саны канчалык көп болсо, муну жасоо ошончолук кыйын болот.
Бирок, адатта, мен чычканды ыргытып, жөн гана код жазам. "HR" схемасында кайсы таблицалар (жана кайсы касиеттери менен) камтылганын билишиңиз керек дейли. Көпчүлүк DBMS, каалаган натыйжага information_schema бул жөнөкөй суроо менен жетишүүгө болот:
select table_name
, ...
from information_schema.tables
where schema = 'HR'
Берилиштер базасынан маалымат базасына чейин, мындай маалымдама таблицалардын мазмуну ар бир СББнын мүмкүнчүлүктөрүнө жараша өзгөрүп турат. Жана, мисалы, 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 гана бар.
Ошондой эле, көптөгөн МББдер башка СББларда жок объекттердин өзүнүн спецификалык түрлөрүнө ээ. Мындан тышкары, биз маалыматтар базасынын объектилерине гана эмес, ошондой эле МББнын өзүндө да операцияларды жасай алабыз, мисалы, процессти "өлтүрө алабыз", эстутумдун бир бөлүгүн бошотуп, трассаны иштете алабыз, "окуу үчүн гана" режимине которула алабыз жана башка көптөгөн нерселер.
Эми бир аз тарталы
Эң кеңири таралган милдеттердин бири - маалымат базасынын объектилери менен диаграмма куруу жана алардын ортосундагы объекттерди жана байланыштарды кооз сүрөттө көрүү. Дээрлик бардык графикалык IDE, жеке "буйрук сабы" утилиталары, адистештирилген графикалык инструменттер жана модельерлер муну жасай алышат. Алар сиз үчүн "мүмкүн болушунча" бир нерсени тартышат, бирок сиз бул процесске конфигурация файлындагы бир нече параметрлердин же интерфейстеги белги кутучаларынын жардамы менен гана таасир эте аласыз.
Бирок бул маселени бир топ жөнөкөй, ийкемдүү жана көрктүү чечсе болот, албетте, коддун жардамы менен. Ар кандай татаалдыктагы диаграммаларды түзүү үчүн бизде бир нече атайын белгилөө тилдери бар (DOT, GraphML ж. . Ооба, биз объекттер жана алардын ортосундагы байланыштар жөнүндө кантип маалымат алууну билебиз.
Бул 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 мүмкүнчүлүгүнө ээ болгон эмес, анткени система татаал жана кымбат, күтүлбөгөн жерден "иштеп чыгуучулар бир нерсеге чалынып, баарын бузушат". Ошондуктан, иштеп чыгуучулар "эмпирикалык" тормоздун ордун жана себебин таап, жамаачы чыгарышты. Эгерде ДБАнын коркунучтуу каты жакынкы аралыкта кайра келбесе, анда ар бир адам жеңил дем алып, учурдагы милдеттерине (жаңы Катка чейин) кайтып келмек.
Бирок мониторинг процесси кызыктуураак жана достук, эң негизгиси бардыгы үчүн жеткиликтүү жана ачык көрүнүшү мүмкүн. Негизги мониторинг системаларына кошумча катары, жок эле дегенде, анын негизги бөлүгү (алар, албетте, пайдалуу жана көп учурларда алмаштырылгыс). Ар кандай МББ анын учурдагы абалы жана иштеши жөнүндө маалымат менен бөлүшүү үчүн эркин жана таптакыр бекер. Ошол эле "кандуу" Oracle DBде, процесстер менен сеанстардан баштап буфердик кэштин абалына чейин системалык көрүнүштөрдөн дээрлик бардык маалыматтарды алууга болот (мисалы,
Ошентип, ыңгайлаштырылган sql сурамдарын аткара турган кандайдыр бир метрика жыйноочу (Telegraf, Metricbeat, Collectd), бул метрикалардын сактагычы (InfluxDB, Elasticsearch, Timescaledb) жана визуализатор (Grafana, Kibana) менен куралдансаңыз, сиз оңой эле ала аласыз. жана башка жалпы системалык көрсөткүчтөр менен тыгыз интеграцияланган ийкемдүү мониторинг системасы (мисалы, колдонмо серверинен, ОСтен ж.б. алынган). Мисалы, бул pgwatch2де жасалат, анда InfluxDB + Grafana айкалышы жана системанын көрүнүштөрү үчүн сурамдардын жыйындысы колдонулат, аларга да кирүүгө болот
жалпы
Бул кадимки SQL кодун колдонуу менен биздин маалымат базасы менен эмне кылса болорун болжолдуу тизмеси гана. Дагы көп колдонууну таба аласыз деп ишенем, комментарийге жазыңыз. Мунун баарын кантип автоматташтыруу (жана эң негизгиси эмне үчүн) жана кийинки жолу CI/CD түтүкчөсүнө кошуу керектиги жөнүндө сүйлөшөбүз.
Source: www.habr.com