Реляционная модель данных почти полвека с нами. Неудивительно, что за это время она успела немного надоесть. Старый спор сетевой и реляционной модели готов был вот-вот разгореться с новой силой, но тут случилось неожиданное.

История

Напомню в чем было основное преимущество реляционной модели над сетевой. Если не вдаваться в длинные размышления, преимущество заключалось в том, что по замыслам создателей реляционной модели, вам не надо будет программировать, чтобы получить данные из базы. Как видите, идея существовала задолго до того, как low-code и zero-code стали популярными. Мы даем вам SQL, говорили создатели. А это почти обычный человеческий язык. Там понятные английские слова. Ну есть некоторые правила, но их ведь несложно будет усвоить. И тогда все преимущества использования баз данных станут доступны всем и каждому.

На деле всем и каждому усвоить правила оказалось сложно. Для большинства вот это вот "почти" в словосочетании "почти обычный человеческий язык" оказалось непреодолимым препятствием. Но реляционная модель все равно победила. По причине того, что язык SQL все-таки здорово экономил силы программистам. Пусть zero-code и не вышел, зато low-code получился очень неплохой.

Шло время, к этому low-code в SQL все привыкли, и отчасти перестали его различать. При этом стали вспоминать позабытые было достоинства сетевой модели. Появилась концепция NoSQL. Поначалу Nо означало... No. В смысле, "ну все, хватит". Потом все-таки поняли, что погорячились и совсем без SQL не получится. Поэтому стали всем объяснять, что No это на самом деле Not only. Как бы там ни было, сетевая модель стала постепенно возвращать утраченные ею позиции.

Поворот

Но тут случилось технологическое чудо в виде больших языковых моделей и GPT. И оказалось, что в том самом словосочетании "почти обычный человеческий язык" теперь можно смело убирать "почти". Любой человек, без какой-либо подготовки может сформулировать запрос к базе данных на привычном ему языке и немедленно получить результат.

Как так получилось. Сильно упрощая, можно сказать, что результат, выдаваемый языковой моделью, зависит о того, сколько ранее натрындели по вашему вопросу в Интернете и что из этого попало в обучающую выборку. На тему любого мыслимого запроса в SQL натрындели много и почти все это попало в обучающую выборку. В принципе, то же самое относится и к наиболее распространенным языкам программирования. Но есть существенное отличие. Если попросить языковую модель написать программу, то почти всегда результат нужно будет немножко "допилить", иначе не запустится. Если же попросить написать SQL запрос, то почти всегда этот запрос можно будет отправлять на выполнение как есть.

В будущем этот феномен наверняка будет исследован. А пока мы просто имеем это, как факт.

Примеры

Чтобы не быть голословным приведу несколько примеров.

Пояснения к примерам

Это все реальные примеры вопросов, которые задавали пользователи сервиса доступа к данным на естественном языке. Получаемые результаты транслировались в язык запросов 1С:Предприятие и выполнялись в этой среде. Каждый вопрос дополняется спереди описанием таблиц. Эту добавку я убрал для большей читабельности. Конечные пользователи ее все равно не видят. Содержание добавки очевидным образом выводится из текста запроса SQL. Здесь я привожу тексты SQL запросов, но не оттранслированный в 1С:Предприятие результат. Как мне кажется, так будет понятнее всем.

Я понимаю, что чем-то совсем простым, типа "покажи остатки такого-то товара на складе" никого не удивить. Поэтому возьмем что-нибудь поинтереснее. Например, такой вопрос:

Что лучше всего продается в этом году

ответ языковой модели

SELECT Товар.наименование, SUM(Продажи.сумма) AS выручка
FROM Продажи
JOIN Товар ON Продажи.товар_id = Товар.id
WHERE YEAR(Продажи.дата) = YEAR(CURRENT_DATE())
GROUP BY Товар.наименование
ORDER BY выручка DESC
LIMIT 10

Сразу надо отметить, что этот запрос рабочий. Т.е. его можно как есть отправлять на выполнение. Что еще более примечательно, мы получаем рабочий ответ на достаточно расплывчатый вопрос. Языковая модель не "ломается" и не "бастует". Она просто берет и выдает вполне себе разумный вариант.

Языковая модель может "прожевать" и нечто более заковыристое

Список уникальных покупателей артикула Ч-8889 в 2023 году из тех у кого было менее 3 покупок любых товаров в 2022 году

С помощью такого вопроса некто пытался доказать принципиальную неработоспособность языковой модели. В самом деле, в этом вопросе есть определенная "засада". Видимо, оппонент сам решал такого рода задачу и "наступил на грабли". Он составил запрос, отвечающий первой части условия, а для второй части использовал условие на вхождение в список. Типа, выбираем уникальных покупателей артикула Ч-8889, а потом смотрим присутствует ли каждый из этих покупателей в списке тех, кто сделал менее 3 покупок в 2022 году. Если вы еще не догадались в чем тут дело, я вам подскажу, что в этом списке не будет тех, кто сделал 0 покупок и результат будет неправильным.

Языковая модель без проблем справляется с этой задачей. Ее ответ

SELECT Контрагенты.id, Контрагенты.наименование
FROM Продажи
JOIN Контрагенты ON Продажи.контрагент_id = Контрагенты.id
WHERE Продажи.товар_id = (SELECT id FROM Товар WHERE артикул = 'Ч-8889')
AND YEAR(Продажи.дата) = 2023
AND Контрагенты.id NOT IN ( SELECT Продажи.контрагент_id FROM Продажи WHERE YEAR(Продажи.дата) = 2022 GROUP BY Продажи.контрагент_id HAVING COUNT(*) >= 3)

Он снова синтаксически корректный. Но, кроме того, он еще и правильный. Языковая модель смогла "догадаться" что здесь следует использовать NOT IN вместо IN.

Вообще нейросеть вполне может делать относительно сложные вещи. Например, вот на такой вопрос

Срез последних продаж по клиентам

будет выдан совершенно правильный ответ

SELECT Продажи.контрагент_id, Контрагенты.наименование, Продажи.товар_id, Товар.наименование, Продажи.количество, Продажи.сумма, Продажи.суммаприбыли, Продажи.рентабельность, Продажи.дата
FROM Продажи
JOIN Контрагенты ON Продажи.контрагент_id = Контрагенты.id
JOIN Товар ON Продажи.товар_id = Товар.id
WHERE Продажи.дата = (SELECT MAX(дата) FROM Продажи WHERE контрагент_id = Продажи.контрагент_id)

И "вишенка на торте". Все это прекрасно работает и в обратную строну. Я имею ввиду, что можно попросить построить SQL запрос по текстовому описанию, а можно попросить построить текстовое описание по SQL запросу. Текстовое описание для запроса, приведенного выше, будет таким:

Этот SQL запрос выбирает данные о продажах, включая идентификатор контрагента, наименование контрагента, идентификатор товара, наименование товара, количество проданного товара, сумму продаж, сумму прибыли, рентабельность и дату продажи. Для этого запроса используются три таблицы: Продажи, Контрагенты и Товар. Для связи этих таблиц используются операторы JOIN. Запрос выбирает только те записи, где дата продажи равна максимальной дате продажи для данного контрагента.

Таким образом, человек вовсе не владеющий SQL может сформировать работающий запрос к базе данных. И он же может получить текстовое описание запроса и убедиться, что его поняли правильно.

Заключение

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

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

В конце статьи хочу порекомендовать вам бесплатный вебинар на котором эксперты OTUS покажут как настроить доступ между базами через расширение postgres_fdw и логическую репликацию.

Комментарии (14)