Вступление

Первое, что нам нужно сделать, это понять, что такое обработка графов и как она связана с SQL Server. Во второй части этой серии мы поговорим о Entity Framework Core и о том, как мы можем использовать его с построением графиков SQL Server. Если вы не знаете или не заботитесь об EF Core, не волнуйтесь, мы упоминаем об этом здесь в последний раз!

Однако здесь мы полностью сосредоточимся на базе данных.

Возможно, вы думаете о столбчатых и круговых диаграммах? А теперь, может быть, просто пирожки ... В любом случае, ты ошибаешься, а может быть, просто очень голоден. В SQL Server 2017 (что, конечно же, означает также и в Azure SQL по умолчанию) Microsoft представила создание графиков в ядре базы данных, но что это такое? Из документации Microsoft:

База данных графа - это набор узлов (или вершин) и ребер (или отношений).

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

В этой функции нет ничего из того, что SQL Server не мог делать раньше, но она дает некоторые важные преимущества:

  1. Обход графа делает запросы намного проще и удобочитаемыми. Раньше вам нужно было кропотливо соединять таблицы вместе.
  2. Для взаимоотношений не требуются первичные и внешние ключи - все это ваше дело.
  3. Графические запросы могут работать лучше, потому что ядро ​​базы данных может применять определенные оптимизации.

Столы

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

Создание таблиц

Во-первых, нам нужно сообщить SQL Server, что таблицы являются узлами или ребрами, и это так же просто, как пометить в конце «AS NODE» или «AS EDGE». Итак, вместо этого:

У нас есть:

Таблица отношений (или края) похожа:

Более того, в граничной таблице даже не обязательно должны быть столбцы, определенные пользователем:

Отношения и ключи

Второе отличие состоит в том, что у нас нет явных отношений между узлами и ребрами; нет внешних ключей! Вы можете связать любые два узла вместе с любым ребром, которое вам нравится. Итак, если у вас есть таблицы узлов для людей и местоположений и граничные таблицы для лайков и владеет, теперь это тривиально. сказать «людям нравятся местоположения», «людям нравятся люди», «людям принадлежат местоположения» и даже «людям принадлежит people »(хотя я настоятельно рекомендую вам держаться подальше от последнего!)

Итак, как SQL Server знает, как связывать строки вместе? Для этого у нас есть несколько псевдоколонок

Псевдо-что-теперь?

Несмотря на то, что мой редактор хотел автоматически исправить psuedocolumn на pseudocelli (который, по-видимому, является порой или глазом какого-то примитивного насекомого… определенно не для трипофобов) это настоящая вещь. Это дополнительные столбцы (немного похожие на вычисляемые столбцы), которые создаются для вас и которые вы не можете редактировать. Например, взяв нашу таблицу FooNode из ранее, давайте проведем по ней SELECT *:

Обратите внимание, что у нас появился новый столбец $ node_id, префикс знака доллара - это то, что идентифицирует его как psuedocolumn. Вы можете забыть о кажущемся случайным наборе символов, следующих за именем столбца. Вы можете выбрать этот столбец вручную с помощью:

Что касается граничных таблиц, есть еще пара псевдостолбцов. Помимо $ node_id у нас также есть $ from_id и $ to_id:

Они должны дать вам представление о том, как SQL Server строит граф и отношения между узлами.

Создание отношений

Это просто вопрос вставки $ node_id двух узлов в граничную таблицу. Например:

В реальной ситуации у вас не было бы значений $ node_id, указанных таким образом, вы почти наверняка сделали бы что-то вроде этого:

Вот и все! Выберите любые узлы, которые вам нравятся, и свяжите их вместе.

Запрос графика

Настоящая сила построения графиков в SQL Server заключается в получении данных из системы. Представьте, что вы делаете это классическим реляционным способом SQL с внешними ключами и объединениями. Я уверен, что вы все испытывали ту же боль, что и я, пытаясь запомнить названия столбцов («Это« ID »или« ProductID »?»)

Что ж, теперь у нас есть предложение MATCH. Учитывая наши таблицы выше, мы можем запросить его следующим образом:

Вот и все. Поначалу это может показаться немного устрашающим, но если вы присмотритесь, все, что вы делаете, - это указываете три вещи. Узел, отношение и еще один узел.

Вы также можете пойти на один шаг дальше и пройти по графику за второй переход:

А теперь представьте, как это будет выглядеть как серия JOIN, о… ужас!

Пример работы

Установка

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

Теперь по краям наши отношения просто друзья и рейтинги.

А поскольку пустые таблицы без данных бесполезны, давайте посеем их туда.

Теперь, когда мы дружны, мы должны убедиться, что наши фальшивые люди тоже дружелюбны. Для этого мы собираемся добавить некоторые отношения, вставив строки в наши граничные таблицы. В нашем случае Алиса дружит со всеми, кого мы свяжем здесь со всеми остальными, используя значения $ node_id из таблиц узлов, это фактически наши ключи.

Поскольку все любят Tyne Bar, все посетили и поставили ему оценку 5 из 5.

Большинство людей разумны, поэтому им не особенно нравится Готэм-Таун. Ну, кроме Боба, который, давайте признаем, немного животное.

Да, и Шарлин сильно пьет, и ей тоже нравится Тилли.

Хорошо, а что теперь делать со всеми этими прекрасными данными? Все вышеперечисленное - просто скучные данные, которые мы могли бы создать с помощью первичных ключей и внешних ключей, реальная сила построения графиков SQL Server заключается в запросах. Зададим несколько интересных вопросов нашей базе данных.

Запросы

Во-первых, мы начнем с чего-то простого, получим средний рейтинг для всех локаций и отсортируем от лучшего к худшему.

Это дает нам хороший список мест, которые мы могли бы посетить.

Хорошо, что-нибудь посложнее, как насчет того, чтобы получить список всех мест, которым друзья Алисы присвоили 5 звезд?

Обратите внимание на двойной прыжок по графику от людей к людям к местам. Другой момент заключается в том, что нам нужно создать псевдоним для таблицы People, поскольку мы используем ее дважды. Это дает нам два места

Важно отметить, что отношения являются направленными. Поэтому в этом контексте думайте о дружеских отношениях как о том, как работает Twitter, а не о Facebook: вы можете подписаться на кого-то, но они не обязательно подпишутся на вас. Поэтому, если мы наивно запустим этот запрос, чтобы получить всех людей, которые оценили Tilleys, он вернет пустой набор результатов.

Итак, как бы нам изменить дружбу, чтобы она стала более стилем Facebook? Есть несколько способов.

  1. Добавьте взаимные отношения, чтобы Алиса дружила с Бобом, а Боб дружил с Алисой.
  2. Запрашивая, убедитесь, что вы всегда проверяете оба направления.

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

Или другой вариант:

Другие вещи, о которых стоит подумать

Но это далеко не все пушистые кролики, но есть и недостатки.

Ключи и индексы

Мы можем (и должны) по-прежнему создавать первичные ключи и индексы для таблиц NODE и EDGE, и вы также можете включить псевдоколонки. Помните, что это всего лишь столы, и нет причин, по которым люди не могут так обращаться с ними.

Странные отношения

В нашем примере выше можно создать отношения, в которых место может дружить с человеком. Это действительно не имеет смысла, если мы не говорим о разумных зданиях, и без сверхсовременного ИИ или домов с привидениями мы действительно не хотим, чтобы это было разрешено. Так как бы вы это остановили? Насколько я могу судить, для этого нет хорошего способа, поэтому у нас остается два варианта:

  1. Создайте триггеры INSERT в граничных таблицах для проверки ваших таблиц from и to. Я вообще не большой поклонник этого, обычно есть способ получше.
  2. Просто позвольте установить отношения. Если вы не собираетесь писать запросы для получения этих значений, то есть аргумент, что они на самом деле не имеют значения.

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

Далее?

Как вы понимаете, Microsoft не сидит сложа руки и работает над улучшением этой функции. В SQL Server 2019 есть несколько ключевых изменений, но главным почти наверняка является возможность добавлять граничные ограничения. Эта функция устранит указанную выше проблему и предотвратит создание таких странных отношений в запросах.

Заключение

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

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

Во-вторых, это изначально возникло из-за вопроса, опубликованного в Stack Overflow, под названием Запрос таблиц графиков SQL Server 2017 из Entity Framework. Моя первая реакция на это была Черт возьми, держись подальше от объединения этих двух вещей, но, подумав об этом немного глубже, я подумал, могу ли я сделать запрос на перенос в исходный код Entity Framework Core. code для поддержки этой функции. С тех пор я отправил запрос на перенос, но пройдет некоторое время, прежде чем он будет рассмотрен командой EF, поскольку в настоящее время они планируют выпуск v2.2, а затем v3. Я не знаю, будет ли мой код объединен, но я хотел рассказать историю о том, как я прошел путь с открытым исходным кодом, и, надеюсь, поощрить других попробовать его тоже. В конце концов, разве это не одна из лучших сторон открытого исходного кода?