Как работают реляционные базы данных (часть 1)

Использование NoSQL

NoSQL хранилища данных отвечают за те ключевые требования хранения данных, которые не могут быть
удовлетворены реляционными БД.

Кеширование

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

Хранилища ключ-значение

Некоторые NoSQL БД сохраняют пары ключ-значение для быстрого поиска, к примеру, в случае доступа
вопрос/ответ. Реляционные БД более ориентированы на сохранение сложных структур данных и различных
взаимосвязей между типами данных. Эта технология излишне усложняет, когда разработчик хочет реализовать
способ быстрого сохранения и доступа к Q&A данным.

Хранение документов

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

Быстрый доступ к большим наборам данных

Реляционные БД теряют производительность при поиске в больших объемах данных. Исторически, разработчики
строят системы, в которых пишутся SQL запросы для нахождения небольшого количества записей, которые
удаляют для увеличения общей эффективности. Чем больше результирующий набор, тем более дорогим становится
запрос. Большие объемы данных или запросы, которые включают обработку больших объемов данных,
называются «data warehousing».

NoSQL хранилища становятся более популярными и протестированы во многих ситуациях. Эти ситуации
включали большие объемы данных, а также большой темп роста данных во многих системах.

Менее жесткие требования согласованности

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

Как прикажете всё это выучить?

таком количестве баз данных

  1. MongoDB. Вероятно, самая популярная NoSQL база данных на рынке. Если компания не использует в качестве основного хранилища данных реляционную базу данных, то, вероятно, она использует MongoDB. Это гибкое хранилище документов с хорошим набором инструментария. В начале своей «карьеры» у MongoDB была не лучшая репутация, потому что данные в ней в некоторых случаях терялись, но с тех пор её стабильность и надежность намного повысились. Взгляните на этот посвященный MongoDB курс, если хотите узнать больше.
  2. DynamoDB. Если вы используете веб-сервисы Amazon (AWS), вам лучше узнать больше о DynamoDB. Это исключительно надежная, масштабируемая база данных с низкой задержкой, богатым набором возможностей и интеграцией с множеством других сервисов AWS. А самое приятное то, что её не нужно развертывать самостоятельно. Настроить масштабируемый кластер DynamoDB, способный обрабатывать тысячи запросов, можно всего за несколько щелчков мышью. Если это вас заинтересовало, можете взглянуть на вот этот курс.
  3. Neo4j. Самая распространенная графовая база данных. Это масштабируемое и стабильное решение, подходящее для желающих воспользоваться графовой моделью данных. Если хотите узнать больше – начните с этого курса.
  4. Redis. В то время как остальные описанные тут базы данных используются для хранения основных данных приложения, Redis применяется в основном для реализации кэша и хранения вспомогательных данных. Во многих случаях, используется одна из вышеупомянутых баз данных в тандеме с Redis. Чтобы узнать больше, загляните в этот курс.

Как понять что настала пора проводить рефакторинг?

— Don RobertsМартин Фаулер

  • встречается дублирование
  • есть большие методы
  • существуют методы с большим количеством параметров
  • встречается оператор switch
  • Многоцелевые столбцы (или столбцы используемые не по назначению). Допустим у нас есть таблица содержащая информацию по заказам. В таблице есть необязательное для заполнения поле InvoiceId типа int. Представим что процесс продаж в компании построен таким образом, что это поле никогда не заполняется. Начиная с нового года менеджерам стало необходимо проставлять у заказов оценку клиента (от 1 до 10 по результатам обзвона). Такого поля в таблице нет и менеджеры начинают вбивать эти данные в поле InvoiceId (например потому, что IT-шники сказали им что на добавление нового поля уйдет целый месяц). Это приведет к проблемам когда поле InvoiceId станет использоваться по назначению.
  • Многоцелевые таблицы. Примером может послужить таблица Customer в которой хранится информация о физических и юридических лицах. В подобном случае неизбежно появляются столбы с NULL значениями.
  • Избыточные данные. Например, наличие поля Адрес клиента в таблице заказов может привести к случаю когда у нескольких заказов одного и того же клиента будут разные адреса.
  • Таблицы с большим количеством столбцов. Наличие большого количества столбцов может означать что в таблице хранятся атрибуты более чем одной сущности. В таком случае вероятно нужно применить рефакторинг «Разбиение таблицы».
  • Многозначные столбцы. Многозначными называются столбцы, в которых в различных позициях представлено несколько разных фрагментов информации. Например в таблице заказов есть поле OrderNumber содержащее данные вида XXX20150908000125. Где XXX — код товара, 20150908 — дата заказа, 000125 — порядковый номер заказа. На практике часто обнаруживается необходимость разбить поле на части, чтобы можно было проще обрабатывать эти поля в виде отдельных элементов.

1 Сравнение схем целевой БД и БД-источника

Инструмент

Redgate SQL Compare. Еще есть http://compalex.net/, но он работает только с php. Есть и другие инструменты сравнения схем БД.

Методология

Кроме БД prod – она целевая БД – делается БД dev – она БД-источник.

Каким-либо образом делаются изменения в БД-источнике. Причем эта БД-источник получается не тестовая в общепринятом смысле, потому что с ней нельзя делать все, что угодно – подразумевается, что все изменения (по крайней мере, изменения схемы БД) должны перенестись на целевую БД. Далее эти изменения могут скриптоваться, но эти скрипты впоследствии никак не используются – потому что, если их использовать и накатывать каким-либо образом, то вся суть подхода исчезает, сравнение схем становится бессмысленным. Эти скрипты могут лишь играть роль истории изменений. Но которая может отличаться от реальности, поскольку можно что-то визуально в Management Studio (или другом GUI для БД) поменять и забыть это заскриптовать. Или заскриптовать неправильно. Потом, в момент деплоя на целевую БД, делается (с помощью инструмента) diff-скрипт, который накатывается, приводя целевую БД в состояние равной схемы с источником.

Плюсы

  • Для тех, кто боится писать sql. Изменения в БД-источнике можно делать визуальными средствами (с другой стороны, я не считаю это хорошей практикой).
  • Скрипты необходимо писать только для преобразования данных (опять же, я считаю, что скрипты для программиста должны быть отправной точкой, и уходить от них не стоит).

Минусы

Невозможно все, что связано с несколькими контурами (п2).
Если я делаю изменения на своей выделенной тестовой БД-песочнице – я должен перенести эти изменения на БД-источник для prod’а. Если это делать по такой же схеме, то это дает дыру – перенос тех случайных или личных изменений, которые я внес в свою БД (я ведь могу делать в своей песочнице все-все-все, правда?). Скриптуются ведь только нужные изменения, но переносятся все. Кроме того, то я затру изменения, которые переносит другой программист.
Если во втором контуре есть хоть какие-то отличия, нужно для него делать еще одну БД-источник. То есть, если в тестовом контуре есть какие-либо настройки или данные, отличающиеся от prod’а, то либо для него нужна вторая БД-источник, либо как-то еще решать эту проблему.
Отсутствие контроля над скриптами переноса изменений – будут накатаны скрипты, которые сгенерит инструмент. Иногда это может быть плохо, надо учитывать специфику. Например, некоторые изменения требуют пересоздания таблицы

Что делать нужно либо крайне осторожно, либо вообще не делать (если таблица часто используемая, очень большая).
Если же брать этот diff-скрипт, его смотреть и править, то тогда снова вся суть сравнения схем исчезает – можно ведь сразу писать скрипты.
Заскриптованная история изменений объектов может отличаться от реальной. Потому что инструмент сравнивает именно схему баз, а не скрипты – можно (случайно, конечно) что-то поменять и не занести это в скрипты

Или занести в скрипты не совсем правильно.
Все равно нужны дополнительные усилия и инструменты для поддержки:
— миграционных скриптов (преобразования данных),
— версионирования справочников и персистентных данных.
Инструмент не перетягивает настройки БД и настройки SQL Server’а.
Если кто-то другой накатил что-то на БД-источник, при deploy’е оно тоже перетянется.
Зависимость целевой БД от другой БД – в том смысле, что prod должен идти в комплекте со своим источником.
Бесплатных хороших инструментов нет, а redgate SQL Compare дорогой. Причем нужна лицензия для инструмента на всех хостах, с которых будет осуществляться миграция на любую целевую БД.

Подход не решает задачи

  • 1b — подразумевается, что для этого надо использовать SQL Data Compare; 1c; 1d; 1e.
  • Для 2 – дополнительные и весьма весомые усилия. Проще отказаться от нескольких контуров, чем их поддерживать.
  • 3a – инструмент перетягивает изменения схемы либо всех объектов, либо выбранных. То есть нужно при deploy’е просмотреть список всех объектов и отщелкнуть ненужные. Принципиально это решает задачу, но… Так делать никто не будет. Снова правило «намного лучше дисциплинарные ограничения убирать инструментарным расширением». Не хватает что-то типа файла .gitignore.
  • 6 – нужны дополнительные усилия, история изменений может расходиться с реальной.

Происхождение

История названия

Изначально слово NoSQL являлось акронимом из двух слов английского языка: No («Не») и SQL (сокращение от англ. Structured Query Language — «структурированный язык запросов»), что даёт термину смысл «отрицающий SQL». Возможно, что первые, кто стал употреблять этот термин, хотели сказать «No RDBMS» («не реляционная СУБД») или «no relational» («не реляционный»), но NoSQL звучало лучше и в итоге прижилось (в качестве альтернативы предлагалось также NonRel). Позднее для NoSQL было придумано объяснение «Not Only SQL» («не только SQL»). NoSQL стал общим термином для различных баз данных и хранилищ, но он не обозначает какую-либо одну конкретную технологию или продукт.

Развитие идеи

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

В начале 2000-х годов построил свою высокомасштабируемую поисковую систему и приложения: GMail, Google Maps, Google Earth и т. п., решая проблемы масштабируемости и параллельной обработки больших объёмов данных. В результате была создана распределённая файловая система и распределённая система координации, хранилище семейств колонок (англ. column family store), среда выполнения, основанная на алгоритме MapReduce. Публикация компанией Google описаний этих технологий привела к всплеску интереса среди разработчиков открытого программного обеспечения, в результате чего был создан Hadoop и запущены связанные с ним проекты, призванные создать подобные Google технологии. Через год, в 2007 году, примеру Google последовал Amazon.com, опубликовав статьи о высокодоступной базе данных Amazon DynamoDB.

Поддержка гигантов индустрии менее чем за пять лет привела к широкому распространению технологий NoSQL (и подобных) для управления «большими данными», а к делу присоединились другие большие и маленькие компании, такие как: IBM, , Netflix, eBay, Hulu, Yahoo!, со своими проприетарными и открытыми решениями.

O(1) vs O(n2)

В настоящее время многие разработчики не заботятся о временной сложности алгоритмов … и они правы!

Но когда вы имеете дело с большим количеством данных (я не говорю о тысячах) или если вы боретесь за миллисекунды, становится критически важным понять эту концепцию. И как вы понимаете, базы данных должны иметь дело с обеими ситуациями! Я не заставлю вас потратить больше времени, чем необходимо чтобы ухватить суть. Это поможет нам позже понять концепцию оптимизации на основе затрат (cost based optimization).

Концепция

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

Например, когда я говорю «этот алгоритм имеет сложность O (some_function() )», это означает, что для обработки определенного объема данных алгоритму требуется some_function(a_certain_amount_of_data) операций.

При этом важно не количество данных**, а то, ** как увеличивается количество операций при увеличении объема данных. Сложность по времени не дает точное количество операций, но хороший способ для оценки времени выполнения

На этом графике вы можете увидеть зависимость числа операций от объема входных данных для различных типов временных сложностей алгоритмов. Я использовал логарифмическую шкалу, чтобы отобразить их. Другими словами, количество данных быстро увеличивается с 1 до 1 млрд. Мы можем увидеть, что:

  • O(1) или постоянная сложность остаются постоянными (иначе это не будет называться постоянной сложностью).
  • O(log(n)) остается низкой даже с миллиардами данных.
  • Наихудшая сложность — O(n2), где количество операций быстро растет.
  • Две другие сложности так же быстро увеличиваются.

Примеры

При небольшом количестве данных разница между O(1) и O(n2) незначительна. Например, предположим, что у вас есть алгоритм, который должен обрабатывать 2000 элементов.

  • Алгоритм O (1) обойдется вам в 1 операцию
  • Алгоритм O (log (n)) обойдется вам в 7 операций
  • Алгоритм O (n) обойдется вам в 2 000 операций
  • Алгоритм O (n * log (n)) обойдется вам в 14 000 операций
  • Алгоритм O (n2) обойдется вам в 4 000 000 операций

Как я уже сказал, по-прежнему важно знать эту концепцию при работе с огромным количеством данных. Если на этот раз алгоритм должен обработать 1 000 000 элементов (что не так уж много для базы данных):

  • Алгоритм O (1) обойдется вам в 1 операцию
  • Алгоритм O (log (n)) обойдется вам в 14 операций
  • Алгоритм O (n) обойдется вам в 1 000 000 операций
  • Алгоритм O (n * log (n)) обойдется вам в 14 000 000 операций
  • Алгоритм O (n2) обойдется вам в 1 000 000 000 000 операций

Я не делал расчетов, но я бы сказал, что с помощью алгоритма O (n2) у вас есть время выпить кофе (даже два!). Если вы добавите еще 0 к объему данных, у вас будет время, чтобы вздремнуть.

Идем глубже

Для справки:

  • Поиск в хорошей хеш-таблице находит элемент за O (1).
  • Поиск в хорошо сбалансированном дереве дает результат за O (log (n)).
  • Поиск в массиве дает результат за O (n).
  • Лучшие алгоритмы сортировки имеют сложность O (n * log (n)).
  • Плохой алгоритм сортировки имеет сложность O (n2).

Примечание: в следующих частях мы увидим эти алгоритмы и структуры данных.

Есть несколько типов временной сложности алгоритма:

  • сценарий среднего случая
  • лучший вариант развития событий
  • и худший сценарий

Временная сложность часто является наихудшим сценарием.

Я говорил только о временной сложности алгоритма, но сложность также применима для:

  • потребления памяти алгоритмом
  • потребления дискового ввода / вывода алгоритмом

Конечно, есть сложности хуже, чем n2, например:

  • n4: это ужасно! Некоторые из упомянутых алгоритмов имеют такую сложность.
  • 3n: это еще хуже! Один из алгоритмов, которые мы увидим в середине этой статьи, имеет эту сложность (и он действительно используется во многих базах данных).
  • факториал n: вы никогда не получите свои результаты даже с небольшим количеством данных.
  • nn: если вы столкнетесь с этой сложностью, вы должны спросить себя, действительно ли это ваша сфера деятельности …

Кластеры атакуют!

В начале нового тысячелетия в технологическом мире лопнул пузырь доткомов (), надувавшийся в 1990-х годах. Это вызвало у многих людей вопросы об экономических перспективах Интернета, но в 2000-х годах некоторые из главных свойств сети веб приобрели очень большой масштаб.

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

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

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

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

Когда произошел сдвиг в сторону кластеров, возникла новая проблема – реляционные базы данных не предназначены для работы на кластерах. Кластерные реляционные базы данных, такие как Oracle RAC или Microsoft SQL Server, основаны на концепции общей дисковой подсистемы. Они используют кластерную файловую систему, выполняющую запись данных в легко доступную дисковую подсистему, но это значит, что дисковая подсистема по-прежнему является единственным источником уязвимости кластера. Реляционные базы данных также могут работать на разных серверах с разными наборами данных, эффективно выполняя фрагментацию базы данных (sharding). Хотя это позволяет разделить рабочую нагрузку, вся процедура фрагментации должна контролироваться приложением, которое должно следить за тем, какой сервер базы данных и за какой порцией данных обращается.

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

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

Это несоответствие между реляционными базами данных и кластерами вынудило некоторые организации рассмотреть альтернативные способы хранения данных.

В частности, большое влияние оказали две компании — Google и Amazon. Они вышли на передний фронт работы с горизонтально масштабированными кластерами; более того, они хранили огромные объемы данных. Это стимулировало остальные компании.

Обе компании были успешными и быстро растущими высокотехнологичными предприятиями, обладающими средствами и возможностями. Им не приходило в голову, что они уничтожают свои реляционные базы данных. Когда прошло первое десятилетие нового века, обе компании опубликовали короткие, но очень важные документы о своих усилиях: BigTable от компании Google и Dynarno от компании Amazon.

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

Несмотря на то что большинство проектов программного обеспечения не требуют такого масштабного применения, все больше и больше организаций начинают изучать возможности хранения и обработки более крупных объемов данных — и наталкиваются на те же проблемы. Таким образом, чем больше информации об опыте компаний Google и Amazon мы получаем, тем больше людей начинают предпринимать попытки создавать аналогичные базы данных, непосредственно предназначенные для кластеров.

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

Методы хранения данных

Есть базы данных, которые вообще никак данные не хранят, у них все содержится в памяти. Соответственно, любая перезагрузка процесса влечет за собой потерю данных.
Другие базы данных используют такие методы как snapshot, запись данных в лог и in-place updates.

  • Snapshot – слепок базы данных на текущий момент. Минусом этого способа является необходимость наличия дополнительной памяти. В зависимости от активности, которая происходит на сервере, может понадобиться до двукратного запаса памяти.
  • Запись данных в лог – когда базе данных приходит команда на запись, происходит запись в лог и продолжается работа. Данные, которые попали в лог, не подлежат изменению.
  • In-place updates – база данных имеет свою копию, которая обновляется при каких-либо изменениях в базе данных. Такая модель не безопасна, так как при возможном отключении питания во время обновления копии данные потеряются.
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector