Реляционный SQL по сравнению с NoSQL MONGODB

Tags: SQL, NoSQL, MongoDB, Oracle, DBA, DDL, DML

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

Аббревиатура CRUD означает Create (создать), Read (прочитать), Update(обновить) и Delete (удалить). Это операции, используемые для добавления, поиска и выборки, управления и удаления данных, хранимых в системах управления базами данных. Для выполнения операций обмена данными реляционные базы данных используют крайне мощный, стандартный язык структурированных запросов - Structured Query Language (SQL).

Их конкуренты, NoSQL-системы, используют более простые языки и API-интерфейсы для хранения данных и доступа к ним. Большинство NoSQL-продуктов имеют уникальные языки и механизмы, которые обеспечивают CRUD-возможности. В данной статье при сравнении реляционных и NoSQL-систем, мы сопоставим операции SQL CRUD с методом доступа MongoDB. В наше обсуждение будет входить работа с данными, а также построение расширенных запросов, которые включают в себя соединения или их отсутствие. В следующей статье этой серии мы рассмотрим манипулирование данными и их удаление.

Реляционная SQL

Реляционный язык структурированных запросов или SQL - это язык, специально созданный для работы с данными, хранящимися в системах управления реляционными базами данных. В основе этого языка лежит алгебра - область математики, в которой символы используются для представления цифр или членов конкретных множеств. Символы представляют величины или общие функции членов множества. Множество объединяется с двоичными операциями, которые задаются для множества. Э.Ф. КОДД, отец систем управления реляционными базами данных, впервые описал реляционную алгебру в 1970 году.

Язык SQL можно дальше разложить на:

  • Язык определения данных - Data Definition Language (DDL)
    Используется для построения схем и связанных объектов хранения в системах управления базами данных
  • Язык манипулирования данными - Data Manipulation Language (DML)
    Операторы, которые позволяют приложениям взаимодействовать с информацией базы данных – SELECT, INSERT, UPDATE, DELETE. Также известны как операции CRUD.
  • Язык управления данными - Data Control Language (DCL)
    Операторы, используемые для управления безопасностью внутри базы данных. Определяют, кто и к чему имеет доступ.

На протяжении лет SQL является стандартным языком, используемым для работы с реляционными базами данных. Он был адаптирован в качестве стандартного языка различными организациями, включая Американский национальный институт стандартизации (ANSI) и Международную организацию по стандартизации, которая входит в Международную электротехническую комиссию (ISO-IEC).

Цель стандартизации - иметь возможность переносить язык из одной системы в другую. Он стал стандартным языком, используемым для работы со всеми системами управления реляционными базами данных (RDBMS). Поскольку все значительные RDBMS поддерживают язык SQL, разработчики и DBA могут легко использовать свои навыки при работе с различными реляционными базами данных. Нам следует использовать выражение "переносимый язык" несколько в более широком смысле, поскольку все разработчики баз данных предлагают улучшения языка, специфические для их продукции. Такие улучшения в большинстве случаев не могут быть перенесены между продуктами различных разработчиков.

Методы MongoDB

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

Перед тем, как начать наше сравнение формулировок запросов MongoDB и SQL, дадим несколько определений и дополнительных сравнений.

Реляционная (Oracle)

NoSQL (MongoDB)

Database (база данных)

Database (база данных)

Table (таблица)

Collection (Сборник)

Row (строка)

Document (документ)

Column (колонка)

Field (поле)

Index (индекс)

Index (индекс)

Primary Key (первичный ключ)

_ID field

Join (соединение)

Reference or Embedded Document (указатель или встроенный документ)

Check Constraint (проверочное ограничение)

Validation Rules (правила проверки)

 

Операция

Реляционная (Oracle)

Метод NoSQL (MongoDB)

 Данные запроса

 SELECT

db.collection.FIND() - where collection is the name of the collection being searched

 

 Вставить данные

 

 INSERT

 

db.collection.insertOne () – inserts single document

db.collection.insertMany() – inserts multiple documents

db.collection.insert() – inserts one or more documents

 

 Обновить данные

 

 UPDATE

 

db.collection.updateOne() – updates single document

db.collection.updateMany() – updates multiple documents

db.collection.replaceOne() – replaces a single document

db.collection.update() – updates one or more documents

 

Удалить данные

 

DELETE

 

db.collection.deleteOne() – deletes single document

db.collection.deleteMany() –deletes multiple documents

db.collection.remove() – deletes one or more documents

 

Термин

Определение

Projection (Проекция)

Оператор, который ограничивает реляционные колонки или поля MongoDB, возвращенные по запросу.

Selection (Выбор)

Оператор, который ограничивает реляционные ряды или документы MongoDB, возвращенные по запросу.

Cursor (курсор)

Управляющая структура, которая позволяет приложению просматривать результаты, возвращенные по данному запросу.

 

Давайте взглянем на примитивный запрос:

Реляционная система

SELECT empno, ename

Projection (Проекция)

FROM hr. employees

Schema Object (объект схемы)

WHERE salary > 35000

Selection (Выбор)

 

MongoDB

db.employees.find(

Schema Object (объект схемы)

{ salary: {$gt: 35000 } }

Selection (Выбор)

{ empno: 1, ename: 1 }

Projection (Проекция)

 

Как Oracle так и MongoDB используют операции запросов, которые позволяют использовать простой и сложный выбор данных:

Оператор

Oracle

MongoDB

Равно

=

$eq

Больше, чем

$gt

Больше или равный

>=

$gte

Меньше, чем

$lt

Меньше или равный

<=

$lte

Не равный

!=

$ne

Совпадает со значениями в массиве

IN

$in

Не совпадает со значениями в массиве

NOT IN

$nin

Условие совпадения с одним из операторов

OR

$or

Условие совпадения с обоими операторами

AND

$and

Не совпадает с запросным выражением

NOT

$not

Не совпадает с обоими запросными выражениями

NOT

$nor

Поиск шаблона строки

LIKE

$regex

Отсутствие значения

NULL

NULL*

Совпадение документа с конкретным полем

N/A

$exists

Совпадение документа с конкретным типом

N/A

$type

 

Я намеренно не описал все возможные операторы, поскольку обе базы данных имеют десятки возможных операторов. Oracle является безоговорочным победителем, когда дело касается размаха и глубины доступных операторов. В этой статье была поставлена цель провести общее сравнение механизмов доступа к данным в NoSQL-системе и реляционной системе, а не глубокий анализ синтаксиса SQL и NoSQL. В последней статье из серии по сравнению реляционной и NoSQL-системы я предоставлю более детальное сравнение.

Вот пример сортировки возвращенных результатов:

Реляционная система

SELECT empno, ename, address

Projection (Проекция)

FROM hr. employees

Schema Object (объект схемы)

WHERE salary > 35000

Selection (Выбор)

ORDER BY empno

Результаты сортировки (используется ключевое слово DESC для убывания)

 

MongoDB

db.employees.find(

Schema Object (объект схемы)

{ salary: {$gt: 35000 } }

Selection (Выбор)

{ empno: 1, ename: 1 } )

Projection (Проекция)

.sort ( { empno: 1 } )

Результаты сортировки (используется ключевое слово -1 для убывания)

 

Реляционные соединения

Оператор соединения в языке SQL совмещает колонки из двух или более реляционных таблиц. Критерии, которые являются одинаковыми для обеих таблиц используются для установления связей между объектами. Для примера, давайте взглянем на таблицы "Сотрудники" и "Отдел".

Наша таблица "Сотрудники" содержит информацию о персонале, работающем в нашей условной организации. В таблице хранится идентификаторы номера сотрудника, имени, должности и отдела. Колонка DEPTNO в строке сотрудника содержит номер отдела, к которому закреплен сотрудник. Но могут быть и другие признаки, дающие дополнительное описание отдела, которое мы хотим хранить в нашей базе данных. Таблица "Отделы" содержит номер отдела, а также название отдела и его расположение. 

 

Таблица "Сотрудники"

EMPNO

Идентификационный номер сотрудника

ENAME

Имя сотрудника

JOBNO

Номер должности сотрудника

MGRNO

Номер руководителя сотрудника

DEPTNO

Отдел, в котором работает сотрудник

...

Дополнительная информация о сотруднике

Таблица "Отделы"

DEPTNO

Номер отдела

DEPTNAME

Название отдела

DEPTLOC

Расположение отдела

Дополнительная информация об отделе

 

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

  • Inner Join – Объединение двух таблиц с помощью явно заданного оператора соединения. Возвращает данные на основании совпадения значений, содержащихся в колонках, указанных в операторе соединения.
  • Left Outer Join – Объединение двух таблиц с помощью явно заданного оператора соединения, но также возвращает несовпадающие строки из первой таблицы.
  • Right Outer Join – Объединение двух таблиц с помощью явно заданного оператора соединения, но также возвращает несовпадающие строки из второй таблицы.

Описанный ниже SQL-оператор делает выборку имен наших сотрудников и отделов, в которых они работают. Мы объединяем две таблицы вместе, используя колонку DEPTNO, которая является критерием, одинаковым для обеих таблиц. Информация из обеих таблиц будет возвращена в наше приложение, когда колонка DEPTNO из таблицы "Сотрудники" совпадет со значением из колонки DEPTNO в таблице "Отделы".

SELECT employee.ename, department.deptname
FROM employee 
INNER JOIN department
ON employee.deptno = department.deptno

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

На графике снизу изображена наша условная таблица "Сотрудники". В неупорядоченной модели, когда нам необходимо изменить расположение (колонка DEPTLOC) отдела 10 с “Pittsburgh” на “New York,” нам необходимо найти и обновить каждую строку, которая имеет DEPTNO=10. Приложение будет вынуждено изменить все строки с таблице сотрудников, которые содержат то значение DEPTNO (в нашем случае FOOT и ALLEN).

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

Встроенные документы MongoDB, ссылки на справочную документацию и DBRefs
MongoDB, как и большинство продуктов NoSQL, не поддерживает операции соединения. Однако, MongoDB предоставляет некоторые альтернативы. Приведу для примера две наиболее распространенные из них:

Встроенные документы
Данные не упорядочены. В нашем примере информация об отделе сотрудника будет храниться в качестве встроенного документа в нашем документе "Сотрудники". Если необходимо поменять какую-либо информацию о наших отделах, необходимо будет соответственно просмотреть и обновить все документы сотрудников.

{ empno: 7388,
 ename: ‘Foot’,
 jobno: 87,
 mgrno: 6599,
 hiredate: new Date(‘Dec 12, 2015’),
 department: { 
 deptno: 10, 
 deptname: ‘sales’,
 depltloc: ‘Pittsburgh’
 }
 
 }

Ссылки на справочную документацию
Пользователи сохранят _ID field документа "Отделы" в документе "Сотрудники". Приложение выполнит второй запрос, используя _ID field отдела для получения необходимых данных из сборника документов. Для обеспечения достоверности полей _ID fields в документах "Сотрудники" приложение должно будет программным образом поддерживать их значения.

 { empno: 7388,
 ename: ‘Foot’,
 jobno: 87,
 mgrno: 6599,
 hiredate: new Date(‘Dec 12, 2015’),
 department_id_locator: <object ID of Department 10 Document>
 }

DBRefs
DBRefs - это ссылки с одного документа на другой с использованием _id field первого документа, имени сборника и, как опция, имени базы данных. Благодаря включению этих имен, DBRefs позволяет документам, хранящимся во множественных сборниках, более легко связываться с документами из какого-то одного сборника. Для обработки DBRefs наше приложение должно выполнить дополнительные запросы для получения выборки из ссылочных документов. Некоторые движки MongoDB имеют вспомогательные методы, которые автоматически формируют запросы для DBRef. 

$LOOKUP (Ступень агрегирования)
MongoDB 3.2 имеет оператор $lookup, который теперь может быть включен в качестве ступени в процесс агрегации. $lookup совершает операцию "left outer join" по отношению к неразделяемым сборникам в одной и той же базе данных для фильтрации документов из "объединенного" сборника и последующей их обработки. Ступень $lookup ищет полное соответствие между полями в исходных документах и полями документов из "объединенного" сборника.

Обзор последующих статей
В следующей статье из этой серии мы обсудим процессы манипулирования данными и их удаления. Мы закончим серию о системах доступа к базам данных, сделав обзор сильных и слабых сторон как реляционных, так и NoSQL-систем. Затем мы продолжим нашу серию по сравнению реляционных и NoSQL-систем, обсудив поддержку транзакций и механизмы блокировки.

Спасибо за чтение!

No Comments

Add a Comment