Database as Сode. Копаем глубже


    В IT-проектах код пишут все. Инженеры с помощью нескольких строк управляют Kubernetes кластерами, разгоняют облака Terraform'ом и ворочают тонны конфигураций на Ansible, Chef и Puppet. QA пишут понятные бизнесу тестовые сценарии на Spock и Cucumber. Аналитики свободно, часто лучше разработчиков, разговаривают на SQL. Проектная документация в форматах Markdown, AsciiDoc или LaTEX "компилируются" в нужный формат на билд-сервере. Ну а сами разработчики, эти укротители кода, владеют сразу россыпью языков на каждый жизненный случай — клиентский, серверный, скриптовый, функциональный и пр.


    Код уже давно перестал быть загадочной тарабарщиной и теперь в том или ином виде доступен и понятен многим, даже премьер-министрам. И весь этот код участвует в стандартном жизненном цикле — находится под управлением VCS, подвергается code review, автоматизированному тестированию, CI, CD. Используются общие инструменты и подходы, метрики производительности и качества. А все вместе это носит гордое название — "Everything as code".


    Однако мир БД традиционно стоит особняком вдалеке от этой феерии прогресса и технологий. Процесс разработки и сопровождения БД не меняется годами и продолжает вселять ужас и страх в разработчиков, администраторов и пользователей по всему миру. Но возможно ли представить БД в виде обычного кода? Приблизиться к основному процессу разработки, использовать общие инструменты и подходы? Об этом под катом.


    Типичный проект


    Большинству из нас ежедневно, хотим мы этого или нет, приходится сталкиваться с самыми разными БД. Проектировать, разрабатывать, администрировать, решать проблемы с производительностью, конкурентным доступом и вот это все. При этом требования к сбору, обработке и хранению данных постоянно ужесточаются — для одних нужна 100% консистентность, для других нет. Одни хранятся годами, другие несколько секунд. Потеря одних приведет к миллионным убыткам, тогда как потеря других не будет заметна для бизнеса.


    В связи с этим давно появился и успешно используется подход Polyglot Persistence, в результате чего встретить в наши дни на каком-нибудь проекте одну единственную СУБД будет большой удачей. Вместо этого для каждой конкретной задачи подбирается наиболее подходящая база, без попыток как-то выкрутиться и решить все свои проблемы на старой доброй реляционке. А, например, микросервисная архитектура позволяет изолировать работу с конкретной СУБД в рамках одного сервиса и выжать из нее максимум пользы, без вреда для чистоты архитектуры всего проекта. В итоге "Реляционка" (куда ж без неё) + "Key-value DB" + "Wide Column DB" + "Document-oriented DB" + "Search engine DB" + "Graph DB" + "Какая-то еще DB" = "SUCCESS!". Помимо этого, увеличивается количество экземпляров (инстансов) этих БД — шардинг, репликации, распределенные СУБД. Плюс все это надо "растянуть" и поддерживать в разных средах — разработческой, тестовой, продовой и пр.


    Чтобы не быть голословным, приведу несколько выдержек из свежего соцопроса от компании-гиганта по решениям в области управления и разработки БД Quest Software — Проблемы DBA: Тренды в администрировании БД (чтобы скачать, придется пройти несложную регистрацию, но оно того стоит):


    • Вопрос №2: "Сколько инстансов реляционных БД запущено в вашей компании?" — по результатам 24% респондентов используют от 100 до 500 инстансов, а 19% более 500.
    • Вопрос №4: "Сколько различных СУБД (SQL и NoSQL) используется в вашей компании?" — 56% используют от 2-х до 3-х различных СУБД, 40% более 5-и, и только у 4% опрошенных одна-единственная СУБД.
    • Вопрос №18: "Что происходит с количеством инстансов БД в ваших проектах?" — 2/3 респондентов отмечают ежегодное их увеличение.
    • Вопрос №30 (в качестве итога): "С какими главными проблемами столкнутся DBA в ближайшие 3 года?"
      1. 51% — "Увеличение количества инстансов СУБД"
      2. 40% — "Возможность администрировать новые нереляционные БД"
      3. 32% — "Сокращение IT-бюджета" (который, ожидаемо, распухает из-за первых двух проблем)

    А мы готовы к этому?


    Не секрет, что для эффективной работы с той или иной СУБД необходимы специализированные инструменты, такие, как IDE и DB-менеджеры, средства мониторинга, моделирования, миграции схем и многое другое. Однако большая часть таких инструментов и сред были придуманы и разработаны еще в те славные времена, когда любому проекту с головой хватало одной-единственной реляционной СУБД, а таких модных слов, как "Agile", "DevOps" и "CI/CD", еще не придумали. И с тех пор мало что изменилось, т.к. область разработки и сопровождения БД всегда являлась достаточно закрытой и консервативной, а у большинства разработчиков ассоциируются с чем-то древним, сложным и непонятным. Сегодня же, когда практически в любом проектном хозяйстве трудится сразу несколько самых разношерстных СУБД и десятки/сотни их инстансов, обычные повседневные проблемы разработчиков и DBA становятся еще более острыми.


    Традиционно самым популярным и незаменимым инструментом для работы с БД являются всевозможные IDE. Обычно это комплексное решение, которое объединяет под своим интерфейсом, в основном графическим, самые разные функции для разработки и администрирования в единую рабочую среду, делает нашу работу с БД более продуктивной и комфортной — остается только клацнуть мышью на нужном пункте меню. И действительно, мало кто из нас обходится без таких крутых штук, как EMS SQL Manager, Toad, dbForge и многих других.


    Одной из главных проблем таких "коробочек" является то, что под прессом новых фич и новых СУБД (которые не прекращают появляться на рынке) они получаются довольно сложными и продолжают усложняться с каждым разом. Причем как в использовании (зачастую людям приходится осваивать не особенности работы конкретной СУБД, а хитрости и фичи самой IDE), так и в их реализации (поэтому такие системы обычно закрытые и очень платные). Даже многими (включая меня) любимый DBeaver, флагман среди open sourse DB IDE, предоставляет поддержку NoSQL-решений (а какой проект сейчас обходится без них) только в своей Enterprise версии. В добавок ко всему этому сохраняется неиллюзорный риск того, что поддержку какой-либо очень нужной и интересной функциональности СУБД можно не дождаться в скором времени, пока разработчики IDE не посчитают нужным ее впилить (а могут вообще не посчитать и не впилить).


    В ответ на сложившуюся ситуацию сами пользователи зачастую не дожидаются пока появится нужная фича или поддержка новой СУБД, а решают поступающие проблемы самостоятельно и наиболее подходящим для себя и своего проекта способом. GitHub просто кишит такими решениями разной степени сложности. В основном это наборы sql-скриптов на все случаи жизни (dataegret/pg-utils, NikolayS/postgres_dba, gwenshap/Oracle-DBA-Scripts, ktaranov/sqlserver-kit, lestatkim/opensql). Или консольные утилиты, такие, как top-подобные pg_activity и pgcenter. А также всевозможные web-based тулзы, начиная от вполне самостоятельных клиентов и средств мониторинга (pg_web, pg_hero) и заканчивая, например, просто html-обертками над системными таблицами (pg_web_stats, pg_stats_viewer). В результате чего складывается целый класс решений вида "programmers-for-programmers", "DBA-for-DBA", с помощью которых простые, и не очень, пользователи СУБД делятся своим опытом друг с другом непосредственно.


    Everything as code


    Похожая картина когда-то давным-давно наблюдались в области администрирования серверов и управления конфигурациями ПО. Тогда с постоянным появлением новых требований и технологий инфраструктура проектов стала заметно усложняться, резко увеличивалось количество серверов и софта, на нем работающего. А также появилась необходимость более частой, а затем и непрерывной поставки ПО с новыми бизнес-фичами заказчику. Существующие средства для конфигурирования и управления всем этим хозяйством плохо справлялись, в результате чего появился подход "Infrastructure as Code" и такие инструменты, как Ansible, Chef, Salt, Puppet и др., где конфигурирование инфраструктуры осуществляется на специальном DSL. Что даёт больше гибкости и свободы творчества. А код на таком DSL участвует в стандартном жизненном цикле наряду с основным кодом приложения (на Java, C#, Ruby или любом другом языке программирования), а именно — хранится в системе контроля версий (со всеми вытекающими — брэнчи, форки, code review), собирается в билды на сервере сборок, запускаются автоматические тесты и пр.


    В дальнейшем влияние такого подхода стало заметно и в других областях:



    Все больше людей уже не боятся писать код, это становится нормой. Это дает возможность более гибкой конфигурации, а также позволяет использовать общие инструменты (контроль версий, метрики, визуализация, отчеты, тестирование и пр.) в общем флоу. Во многих специализированных инструментах графический интерфейс заменяется или дополняется более гибким программным интерфейсом, различными DSL и конфигурационными файлами.


    Более подробную информацию на эту тему можно найти в докладе Александра Тарасова (aatarasoff) "Everything as a Code".


    Database as code


    А что на этот счет в бескрайнем мире баз данных? Набрав в Google простое словосочетание "Database as code", я не нашел ничего интересного, кроме одного-единственного (но зато какого!) поста на DZone — "Database as Code: a Novel Concept".


    Мы много говорим о database-first подходе. Мы много говорим о том, что данные — это самый ценный актив предприятия. Но как насчет концепции, представленной Dan North на третьем слайде его презентации? Что если относиться к базе данных как к коду?

    Звучит заманчиво, а на слайдах #5 и #6 (к сожалению, видео я не нашел) описываются 2 подхода к управлению схемой БД "через код" — через инкрементальные миграции (Liquibase, Flyway) и идемпотентные DDL-скрипты (Redgate). Таким образом, схема — это тоже код, она находится под контролем VCS, собирается на билд-сервере, выполняются автоматические тесты и все такое.


    Что нам необходимо, чтобы изменить наше мышление в области работы с базами данных? Мы должны прекратить относиться к нашей БД как к магическому артефакту или как к уникальному сценарию и взглянуть на нее под тем же углом, что мы смотрим на обычный код нашего приложения.

    Снова мощно сказано, у меня аж слезы на глазах наворачиваются. К сожалению, и в докладе, и в самом посте, "как код" рассматриваются только изменения схемы БД (миграция схем БД):


    Мы относимся к исходному коду нашего приложения как к сокровищу. И это абсолютно верно, код — это сердце любого приложения. Но не должны ли изменения базы данных также находиться под управлением системы контроля версий, быть автоматизированными, быть готовыми к релизу по первому требованию и подчиняться "DevOps-законам", как и основной код?

    Но минуточку...


    БД — это не только схема!


    Большинство современных СУБД предоставляют свой язык запросов, с помощью которого мы можем не только получать и изменять хранящиеся в ней данные (т.н. DML) и оперировать их схемой (т.н. DDL), а вообще получить (не побоюсь этого слова) любую метаинформацию о текущей БД и ее состоянии (из системных таблиц и представлений) и выполнять практически любые операции над ней (запустить БД, остановить, перевести в read only, собрать статистику, управлять памятью и пр). И такой код тоже вполне себе подходит под концепцию, описанную в предыдущем параграфе.


    А когда речь заходит о БД и языке запросов, то первым в голову приходит, конечно же, старый и добрый SQL. Но можем ли мы рассчитывать на него (а заодно и на реляционные БД, с которыми у большинства он плотно ассоциируется) сейчас и в ближайшем будущем, учитывая огромный рост спроса на NoSQL-решения?


    "Ведь SQL уже всё? ..."


    Вы можете справедливо меня спросить — о каком вообще SQL я тут разговариваю в эпоху NoSQL и schemaless databases, когда "пыльные реляционки доживают свой век исключительно в кровавом легаси Ынтерпрайзе". Ранний Хабр (как лакмусовая бумажка трендов в мире технологий) тоже когда-то был наполнен негативом по отношению к SQL и реляционкам и предвещал их скорейшую гибель (в скобках указаны количество голосов, а через слеш — количество комментариев):



    Однако примерно с 12-года настроение на Хабре заметно меняется:



    При этом анти-sql'ные и антиреляционные настроения продолжают иметь место, но реакция сообщества на них уже совершенно другая:



    Подтверждение этих настроений можно найти в недавних докладах Константина Осипова (kostja) "NewSQL: SQL никуда не уходит" и Андрея Николаенко "Нереляционный SQL". Возьму на себя ответственность привести краткое резюме из обоих выступлений:


    • "SQL в NoSQL" — SQL (как это не странно) довольно комфортно чувствует себя и в NoSQL-среде. Практически во всех NoSQL базах есть возможность использовать какой-либо sql-подобный query language, как, например, CQL в Cassandra и ScyllaDB, AQL в Aerospike и N1QL в Couchbase, а в некоторых и полноценный (или максимально приближенный к нему) ANSI SQL – как в Tarantool, ClickHouse и CrateDB.
    • "SQL в облаках" — Облачные гиганты предоставляют поддержку самых разных SQL-хранилищ: Amazon RDS, Amazon Aurora, Oracle Cloud, Google Cloud SQL, Microsoft SQL Azure, Alibaba Cloud ApsaraDB, Yandex Managed Databases.
    • "SQL в BigData" — SQL давно и плотно влился в инфраструктуру Hadoop. В далеком 2009 году появился Hive со своим HiveQL, а далее, год за годом, стали появляться решения, уже напрямую поддерживающие SQL — Impala (2011), Spark (2013), Kudu (2014), Presto (2015), Phoenix (2017).
    • "SQL в Поточниках" — SQL стал практически стандартом для потоковых обработчиков данных: Flink, Samza, Storm, Apex, а с недавних пор еще и Kafka.
    • "SQL в NewSQL" — Многие современные СУБД активно развиваются в сторону NewSQL, где совмещают в себе преимущества как NoSQL, так и классических реляционных решений, включая широкую поддержку SQL (CockroachDB, FoundationDB, MemSQL).

    Нужно больше аргументов с картинками!
    Дальше приведу еще немного аргументов, но если и так все понятно, то можно смело переходить к следующему параграфу.

    История баз данных в "No-нотациях":


    Также в последнее время появляется много новых и модных СУБД, которые являются «надстройками» над известными и проверенными реляционными СУБД. Например Postgres-based (Timescale и ToroDB), MySQL-based (RadonDB) и даже на базе sqllite (которая всегда позиционировалась как простая и надежная embedded-база) появился rqlite – «легкое распределенное реляционное хранилище». Либо реализуют интерфейс какой-либо популярной базы (например, MySQL для InfiniDB и TiDB). Такой подход хорош тем, что при новой модели данных мы остаемся на той же привычной платформе, которую знаем как конфигурировать и администрировать.

    Ну а для совсем уж "безсхемных" ребят тоже есть попытки создать общий универсальный язык "а-ля SQL", как, например, Eclipse JNoSQL, а точнее — его подпроект JNoSQL Aphrodite.

    Google, который и является одним из родоначальников NoSQL-движения, также делает все больше акцентов на SQL. Сначала это был Spanner, а теперь активно развивается BigQuery:


    SQL-интерфейсами обзаводятся не только хранилища и обработчики данных. Например, с помощью osquery (от самого Facebook) и fsql на языке SQL можно получить много всякой полезной информацию из любой ОС или выполнять различные операции с файловыми системами.


    В общем, SQL вполне комфортно себя чувствует в современных условиях, в том числе далеко за пределами реляционок. Практически с любым источником данных можно "поговорить" на SQL или SQL-like языке, получить нужную информацию о данных или метаданных хранилища и выполнять какие-либо операции (например, что-нибудь создать, удалить, запустить, остановить и пр.)


    Здесь и далее (для удобства и с вашего разрешения) под "SQL" я буду подразумевать не только "тот самый" стандартный реляционный SQL, но и все его подвиды (в т.ч. далеко не реляционные), да и вообще любой встроенный в БД QL, с помощью которого можно сделать что-нибудь полезное.


    К чему все это?


    А к тому, что в далеком 92-м году появился замечательный ANSI-стандарт, согласно которому любая реляционная СУБД обязана уметь описывать свою внутреннюю структуру в специальной схеме — Information schema. Т.о. с помощью стандартного языка запросов к служебным таблицам/представлениям можно получить метаданные любой БД — как в ней содержатся схемы, таблицы, индексы, колонки и пр. Но на самом деле одной схемой данных это не ограничивается, и таким же образом (пусть уже и за пределами стандарта) можно получить информацию о процессах, сессиях, планах выполнения запросов, дисковой подсистеме, утилизации памяти и еще много чего другого.


    Несмотря на то, что этот стандарт появился почти четверть века назад и только для реляционных БД, почти все современные NoSQL и NewSQL базы тоже реализовывают что-то похожее. Например, в Cassandra есть сразу несколько системных схем (а точнее keyspace'ов – system, system_auth, system_schema, system_traces), доступ к которым можно получить с помощью уже упоминавшегося CQL. В ClickHouse есть специальная схема «system». Разработчики из CockroachDB вообще замахнулись на реализацию стандартной information_schema. И даже документный Mongo радует нас системными коллекциями.


    При этом наблюдается постоянный рост количества и расширение таких системных представлений. Например, в Postgresql (как БД с одним из самых активных сообществ) помимо реализации самой information_schema, собственной схемы pg_catalog и pg_stat-представлений имеет несколько официальных расширений в виде преставлений pg_stat_statements и pg_buffercache. А также дополнительные сторонние представления, такие как pg_active_session_history, pg_store_plans и pg_stat_kcache.

    Практически любому узлу соответствует какая-либо системная таблица, которая отображает его структуру и/или состояние. То есть о своем внутреннем устройстве и состоянии БД может рассказать сама посредством своего языка запросов. Помимо этого многие СУБД предоставляет возможность с помощью своего языка запросов не только получить полезные метаданные, но и выполнять служебные операции — что-нибудь остановить, запустить, очистить, собрать статистику и пр. Так в некоторых СУБД команду "ALTER" можно применить не только к таблицам или колонкам, но и к другим объектам, например, к сессии ("alter session set sql_trace = true"), датафайлам ("alter tablespace add datafile") или системе целиком ("alter system kill session").


    Знание этих таблиц и запросов поможет как в разработке и администрировании, так и в освоении очередной новой СУБД. Понятно, что в одних базах такие возможности весьма развиты, и "кодом" можно сделать практически все, а в других гораздо скромнее, но определенно имеет место тенденция того, что все больше разработчиков СУБД будут развивать такие возможности в своих продуктах, а мы сможем более эффективно их эксплуатировать.


    Вместо выводов и резюме


    К сожалению, SQL уже давно и прочно воспринимается многими как язык "низкого уровня", некий "байт-код" для БД. Который не принято, а в некоторых обществах даже глубоко неприлично "писать руками" и вообще каким-либо образом контактировать с ним. Мы уже давно привыкли, что многочисленные DB-тулзы и фреймворки сами генерируют и выполняют за нас "хитрые и сложные" SQL-запросы к системе, и за этим процессом остается только наблюдать. Но давайте выйдем из зоны комфорта теплых ламповых графических интерфейсов и кодогенераторов и посмотрим на наши СУБД с точки зрения обычного кода. Тем более, что все необходимое для этого у нас есть.


    Теперь по делу. Пользователи любой СУБД имеют возможность описать практически все аспекты работы со своей БД в виде кода, на простом, понятном и привычном многим языке. Это может быть не обязательно ANSI SQL, а любой SQL-like диалект, либо вообще свой собственный встроенный QL или API, в зависимости от используемой БД. Чем это полезно?


    • Не привязываясь к какому-либо инструменту, можно получить любую информацию о БД в нужном виде, либо выполнить любую операцию над БД;
    • Т.к. это все-таки обычный код, то и относиться к нему нужно как к любому другому "настоящему" коду. А именно, он должен быть понятен, структурирован и отформатирован по принятому стандарту, а также участвовать во всех этапах стандартного жизненного цикла кода — быть под контролем VCS, подвергаться Code review, участвовать в CI/CD pipeline'ах и пр. (а не "валяться" где-нибудь в папке под названием "SQL-tricks"). Что повысит его качество и ценность в команде.

    Интересно ваше мнение на этот счет, пишите в комментариях — будем обсуждать.


    В следующем посте я планирую на конкретных примерах проиллюстрировать описанные выше идеи, а также расскажу о том, как мы в КРОК пробуем применить их в экспериментальном графическом DB-manager'е с открытым исходным кодом, который разрабатывается в рамках одного из исследовательских проектов.
    КРОК
    196,00
    №1 по ИТ-услугам в России
    Поделиться публикацией

    Похожие публикации

    Комментарии 16

      +1
      Хм… Либо я чего-то не понял, но в MS Visual Studio SSDT весь проект базы данных для MS SQL Server как раз укладывается в концепцию «Database as code».
        +1
        Да, выглядит здорово, жаль что только для MS SQL Server
          0
          Для большого количества СУБД есть другие инструменты. Например, IDE DataGrip от JetBrains. Я им не пользовался (только когда-то давно тестировал), т.к. наши потребности SSDT покрывает полностью. Но по описанию — все тоже самое.
            0
            Да, вопрос больше в отношении и организации, а хороших инструментов хватает
          +1
          Но глядя на то, что в Entity Framework Core поддержка Db-First крайне ограниченная (можно сделать первоначальный dbcontext c существующей базы, а дальше только миграциями из проекта рулить базой), то вполне вероятно, что майкрософт хочет аккуратно поставить крест на концепции Db-First, продвигая Code First.
          Впрочем, тут сложно сказать в чём дело. Некоторые вещи, которые коммьюнити просит у майкрософт не будут релизованы в core — уж больно они специфически виндовые, а core вроде как пытается охватить шире платформы.
          Также и проект БД — он только под MS Sql Server.
            0

            Если нужен чистый DbFirst — то всегда можно удалить контекст со всеми моделями и создать заново.


            Но я не вижу никаких проблем в том, чтобы после внесения изменений в БД дублировать их в моделях EF.

          0
          + за статью!
          А когда у вас появится свой Firebase с блэкджеком и шплюшками?
            0
            Мы сейчас делаем один концепт на эту тему, надеюсь в ближайшее время смогу рассказать о том, что получилось
              +1
              Ждёмс!
            +1
            Возможно я что-то сильно не уловил. Но имеется в виду что-то вроде Evolutionary Database Design? https://www.martinfowler.com/articles/evodb.html
              0
              Промахнулся с ответом, ответил ниже
              0

              Да, все верно. Но в Evolutionary Database Design (и в соответствующей книге) основой акцент делается на схему БД, на ее структуру и как-будто больше ничего нет. Я же предлагаю взглянуть чуть шире, т.к. одной схемой БД дело далеко не ограничивается. Есть всякие административные операции, можно собирать метрики о работе и прочую информацию и все это точно так же можно выразить кодом.

                +1

                С одной стороньі я сильно вдохновлен идеей "Everything as code".


                А с другой стороньі, єтот текст (и примерьі в нем) относится к другому подходу. Одному из древнейших. Everything as text. Кстати, все Version control system имеют ту же проблему.


                Большая часть статьи о том, что на sql можно делать гораздо больше, чем используют отдельно взятьіе проектьі. Однако почему я (любой другой читатель) должен внести изменения в свой текущий проект — не понятно.


                ОРМ имеют шлейф проблем. Однако велосипедьі с шаблонизацией (тем более конкатенацией) SQL кода имеют на порядки больше проблем.

                  0
                  Снова промахнулся…
                  Ответ ниже.
                  0
                  А с другой стороньі, єтот текст (и примерьі в нем) относится к другому подходу.

                  Возможно, но целью был именно «Everything as code». Код «живой», его можно провалидировать, собрать/скомпилить, выполнить тесты и т.д.

                  Однако почему я (любой другой читатель) должен внести изменения в свой текущий проект — не понятно.

                  Об этом как раз и будет во 2-м посте, он почти готов.

                  ОРМ имеют шлейф проблем.

                  Я намеренно не упоминал в тексте это слово ) Не, я не против ОРМ и не против «гуёвых» IDE'шек с красивыми кнопками, я за баланс, чтобы одно полностью не заменяло другое (и наоборот).
                    +1

                    Тогда буду ждать второй статьи.

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое