Колоночные базы данных

Меня, если честно, всегда смущал тот факт что Oracle пихают во все задачи, куда только можно, бытует мнение что «БД это Оракл». Я лично не думаю что это прям такая «серебряная пуля». MySQL занимает те же позиции немного на другом фронте. Да, Oracle в частности, MySQL, и реляционные БД в общем, это отличный инструмент, но для случая когда у нас реально востребована эта реляционность.

Но ведь Оракл используют независимо от того нужна ли нам реляционность, просто по привычке, и потому что «все так делают». Я за все свое время редко встречал нормализованные структуры, и даже больше, часто встречал таблицы БД с колонками вида col_1, col_2, col_N и пр. нарушениями всех форм, когда также разрезали таблицы на отдельные, в том числе отдельные инстансы БД. Встречал также когда в Oracle складывали черт знает что, когда использовали как хранилище лога операций, десятки гигабайт логов, ну и т.д. И никакого серьезного положительного эффекта от реляционных возможностей во всех этих случаях не было.

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

Под реляционностью в данном случае я подразумеваю не только то что данных хранятся в виде таблице (с заранее четко оговоренным списком атрибутов). Я имею ввиду все что вертится вокруг этого: нормальные формы, внешние ключи, связи и ограничения, acid, собственно реляционная алгебра и все прочее предназначенное для облегчения хранения и соблюдения целостности структурированных данных.

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

Поэтому хотел бы обратить внимание на другой тип баз, на колоночные БД.

Основная идея колоночных БД

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

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

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

Перечислю что у нас обычно присуще колоночными базами данных (хочу подчеркнуть что обычно, но не все это обязательно каждой конкретно):

Позднее связывание

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

Например для запроса select col_1 from table where col_2 = 10 традиционная БД будет читать все строки, проверяя каждую на условие во второй колонке, и для совпавших вернет значение первой ячейки этих строк. При этому если у нас в таблице десяток колонок то будет прочитано куча лишних данных (в данном примере что-то около 80% мусора). Чтобы такого перерасхода вычислительных ресурсов не было нужно добавить индекс, который сразу ограничит набор нужных строк. Этот индекс и есть та самая дополнительная колонка, через которую пройдет позднее связывание в традиционной БД. В случае колоночной БД будет читаться лишь 2я колонка, и при совпадении условия к ней будет привязано значение из первой колонки. Очень похоже на то что у нас вся таблица состоит лишь из индексов по колонкам.

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

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

Разная структура данных

Связанные данные хранят в одной таблице (не забываем что при этом можно использовать огромное количество колонок), а связи между таблицами здесь не приживаются, по многим причинам. Но! здесь можно не боятся хранить сложные структуры в ячейках, в том числе вложенные списки, подтаблицы, структуры XML, JSON и пр.

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

Одним из применений этого подходя является ответвление БД имеющих всего одну колонку, помимо ключа, в которой и хранится все что нужно. Внешне все это выглядит как огромный HashTable. Такие БД еще называют key-value storage или document oriented database.

Сжатие данных

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

Большие объемы данных

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

Доступ

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

Но получается что средства доступа по универсальности и скорости разработки/использования выглядят обычно хуже возможностей предоставляемых Oracle и компании.

Сравнение с RDBMS

RDBMS:

  • соблюдается целостность данных (foreign keys, транзакционность)
  • четко структурированные данные
  • запросы по всей структуре БД, используя стандартизованный язык
  • результат запроса это небольшой (относительно БД) кусок данных
  • быстрое извлечение нужной структуры (в том числе быстрая реализация запроса)

Колоночные БД:

  • хранят большие объемы данных, упрощеный шардинг, репликация и пр.
  • данные гораздо менее структурированы
  • данные обрабатываются большим блоком (параллельно, massive parallel processing), или вообще сразу вся база
  • оптимальным будет индивидуальный подход к обработке, тесная интеграция с данными
  • худшая (ручная) поддержка целостности данных

Где стоит использовать

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

Здесь достаточно просто хранить большие блоки данных, документов (в документ-ориентированных БД) и/или сложных структур. Также довольно распространено хранилище данных вида «Ключ-Значение» (aka Properties Pattern, Хэш-таблица) с большими группами которых идет различная работа. Отлично подходит для задач, которые я привел в записи «Хранилище для обработки данных». Ну и также это хранилище логов и прочее в этом духе. Особенно хорошо если данные лишь дописываются, а не изменяются существующие.

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

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

Где не стоит использовать

Не стоит использовать когда нам нужна именно классическая реляционная структура, и когда у нас данные (и связи) постоянно меняются. Под «меняются» я подразумеваю изменение и удаление существующих данных, смену связей между ними. Хотя если данные лишь дополняются, то уже стоит подумать.

Так же не подойдет если у нас много колонок, и мы оперируем в основном всей строкой, нет особого смысла менять тип БД. Хотя в большинстве случаев, как я уже упоминал, значения в нескольких колонкам, которые нам нужно обрабатывать одновременно, даже удобней объединить в общую структуру, к примеру в список имя/значений, или превратив в xml, yaml или json, по вкусу.

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

Ну и конечно не подойдет когда нам нужны классические SQL запросы. Что-то «в стиле SQL» они часто имеют, но это уже на самом деле другой подход и по другому выполняется.

Реализации

HBase — представляет собой часть Apache Hadoop, можно сказать классическая реализация Гуглового Bigtable, рассчитана в первую очередь на большие объемы данных, и на хранение этих данных в большом кластере. Типы данных ничем не ограниченны. Я именно именно на hbase ориентировался когда приводил приводил основные тонкости/отличия, но не ограничивался им.

Из возможностей: сразу учтено что каждая колонка может иметь несколько ячеек (получается что помимо того что в строке несколько строк, в колонке тоже несколько ячеек, этакое минидерево, для хранения списочных и связанных данных), может хранить любые бинарные данные, может хранить одновременно несколько версии (версионность из коробки), поддерживает фильтры Блума, rest интерфейс доступа (помимо java api) и пр.

Но, как минимум в данный момент, не имеет индексов, кроме как по ключу. Если честно, как и сам Hadoop эта база еще развивается, поэтому БД в данный момент достаточно сырая.

Прочие

CouchDB
реализация на Erlang. Не совсем колоночная, это документная БД (document oriented DB), но по сути внутри одна большая колонка, и все приемы соответствующие. БД, конечно, не привязана к определенной платформе (т.е. к Эрлангу). Запросы пишутся на Javascript (!) в виде mapreduce операций, доступ через REST. Благодаря отказоустойчивости самого Erlang'а — очень интересное решение
Hipertable
реализация bigtable на С, изначально как основная альтернатива Hadoop HBase, именно так себя позиционировали. Причем хранение так же было организовано поверх Hadoop HDFS. Как там сейчас обстоит дело не знаю.
The Cassandra Project
реализация от Facebook, тоже базируется на идеях Google BigTable и поэтому похожа на HBase.
Project Voldermort
распределенный key-value storage, на java.
Kdb+
коммерческая БД и язык обработки, заточенные под time-series data. Это всевозможные логи, биллинг, биржы и пр. Язык обработки имеет очень сильную базу для обработки массивов (БД в данном случае является отдельным огромным многомерным массивом) и особенно распределенных во времени. В результате многие узкоспециализированные задачи (всяческие кубы, временные данные) выполняются в разы быстрее. Как минус — БД и все вокруг нее являются излишне закрытыми от людей извне
LucidDB
Open Source реляционная СУБД с основой на колоночной структуре. Расчитывается в первую очеред на аналитику, bi и пр.
Sybase IQ
Еще одна реляционная колоночная СУБД, для нужд аналитики. В этот раз коммерческая
Amazon SimpleDB, Google BigTable, Yahoo Everest
закрытые внутренние реализации от монстров интернета.

Ссылки

  • http:// Александр

    Правильно ли я понял, что Berkley DB тоже можно отнести к колоночным БД?

  • http:// Андрей

    Игорь, до вас дошел мой предыдущий комментарий про колоночные базы и Oracle? А то при добавлении был какой-то сбой, а я там много написал 🙂

  • http://artamonov.ru splix

    2 Андрей: похоже не дошел 🙁 ни в спаме, ни в модерируемых нигде нет

  • http://artamonov.ru splix

    2 Александр: есть большое подозрение что Berkley DB можно отнести к колоночным. Я честно говоря близко не знаком поэтому не упоминал и не буду категорически утверждать

  • http:// Андрей

    Попробую повторить.

    Итак. У меня два замечания.

    1. Колоночная база может быть реляционной. Пример — Sybase IQ. Насколько мне известно, реляционная теория не накладывает ограничений на способ хранения на диске, а говорит только о том как связаны структуры на логическом уровне.

    Так что у вас статья не про то что есть реляционные и колоночные базы, а про реляционные и нереляционные.

    Вообще это спор старый и однозначного ответа до сих пор нет — значит все не так просто.

    2. Ставить рядом MySql и Oracle — это как ставить рядом мотоцикл и грузовик. Да, у них есть колеса, двигатель и предназначены они для перевозки людей и грузов. Но на грузовике неудобно маневрировать в пробках, а на мотоцикле сложно перевести 10 тонн груза.

  • http:// Андрей

    Игорь, почему то коммент не добавляется, когда я заполняю поле сайт.

    Александр, Berkeley DB не колоночная база, она работает с массивами. Но она нереляционная.

  • http:// Андрей

    Игорь, а в остальном полезная и позовнвательная статья. Спасибо 🙂

  • http://artamonov.ru splix

    2 Андрей: если утерянный комментарий был по поводу того что в Оракле есть колоночные структуры, то я не буду спорить, они там обязательно должны быть, я уверен. Но я не нашел явного упоминания об этом 🙁 Но я понимаю что есть OLAP и прочий data warehousing с которыми у него все прекрасно (у вас ведь не спроста адрес вида ___bi.ru?), слышал про Oracle Exadata и пр., там есть куда приложить силы и технологии.

    К Ораклу притензия на самом деле лишь одна: его считают (и он себя позиционирует) серебряной пулей и молотком для всех гвоздей 🙁 это к добру не приводит.

    PS: буду рад хорошему и непредвзятому комментарию по поводу этих технологий в Оракле. Прошу прощения за глюк который привел к пропаже вашего первоначального комментарий.

  • http://artamonov.ru splix

    2 Андрей: кстати точно, про Sybase IQ совсем забыл. И еще LucidDB припоминаю. Все это реляционные и колоночные БД. Надо наверное дописать в статью. Я кстати упомянул что критерий разделения выбрал несколько нелогично, и долго думал по этому �оводу, знаю что одно другому не должно противоречить, но по другому разделять было бы еще менее правильно 🙂

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

  • http:// Андрей

    Игорь,

    Конечно, продажи RDBMS Oracle составляют большую часть доходов от продажи СУБД. Но про серебряную пулю не совсем верно. У компании Oracle в арсенале есть и другие СУБД. Навскидку:

    TimesTen

    Berkeley DB (упоминавшийся)

    InnoDB (кстати движок MySQL)

    Express и его потомок OLAP

    Essbase

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

  • http:// kmmbvnr

    Oracle — это не просто база данных. Это стабильность, удобные интрументы и уверенность в том что на больших объемах оно не загнется.

    У нас в Oracle в колоночном стиле лежит более полуторамиллиарда строк. И все рулит и бибикает. А когда что-нить упирается в производительность, частично переходим на реляционное хранение.

    Удобство и стабильность работы остальных малораспространенных решений зачастую вызывает столько сомнений, что в продакшн их пихать просто страшно.

  • http:// enternet

    kmmbvnr, я тебя конечно очень уважаю... «Платон мне друг, но истина дороже».

    Ты, похоже, не очень долго работаешь с ораклом:

    1) Оракл — это крайне нестабильная СУБД. Первое правило ораклового админа — не ставить свежих обновлений ни в коем случае. Потому что политика оракла — это полное отсутствие внутреннего тестирования. Тестирование проводится только на пользователях. Как результат — админы (в серьезных заведениях, в банках, например) по максимуму откладывают обновления, и ты, разработчик, чтобы получить работающую функцию, сломанную в одном из минорных релизов, ждешь месяцами, пока админы все форумы поддержки перечитают, убедятся, что нужный релиз им ничего другого не сломает. В общем, более низкокачественной СУБД чем оракл, я не встречал. За 9 лет работы с ним мнение о его крутизне упало до нуля.

    2) Оракл применяют не потому, что он удобен. Наоборот, он крайне неудобен и дорог во всём: от программирования, до поддержки. Его применяют потому, что оракл дает партнерам до 60% скидки. Т.е. разрабатывать и внедрять решения на базе оракла банально выгоднее, чем например на базе MSSQL. Вот и весь секрет.

  • http:// kmmbvnr

    Вы бредите. Переводите спор «Стабильная Реляционка (+ колоночное решение там где надо)» vs Чисто НаКолеоночные БД. На столкновение Oracle vs MSSQL.

    ...он крайне неудобен и дорог во всём...

    Только вот решения на нем, повсеместно встречаются и работают. Как и на MSSQL кстати.

    ------------

    Не увидел ничего в защиту мнения, что в малоиспользуемых нетрадиционных, вчера сделанных субд все _гораздо_ лучше.

  • http://artamonov.ru splix

    2 kmmbvn

    Баги есть везде, и что глючней на самом деле неизвестно, все субъективно, критериев оценки нет. По мне так нельзя утвержать и то что Оракл надежен, и то что он глючен. В любой другой базе тоже будут ошибки.

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

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

  • http:// Никита Кокшаров

    Кстати, MonetDB тоже относится к классу такого рода БД. Разработчики даже не поленились провести тест производительности в сравнении PostgreSQL и MySQL

  • http://artamonov.ru splix

    Я почему то считал что MonetDB это XML БД, я ошибался? Ну хотя принципе это все равно не мешает ей быть колоночной

  • Pingback: asash's blog » Подходы к масштабированию баз данных

  • http:// Андрей

    Игорь, а если бы потребовалось завести в базу этакую русско-английскую семантическую карту, то колоночная база была бы кстати?

    Пояснение задачи:

    а) в строках учитываются русские слова, а в колонках те же самые слова, но по английски.

    б) в числе слов могут быть словосочетания (два слова через пробел, где первое — общее, второе — частное);

    в) в ячейках пересечений (те что закрашены черным в таблицах групповых турниров) идут графические файлы изображений.

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

    Предположительно решаемые задачи:

    1. Пользователь хочет перевести «дом». База найдя строку «дом» проходится по ней, находит ячейку с графикой. Далее, образно выражаясь, разворачивается перпендикулярно вверх и выходит на название колонки — «house».

    2. Пользователь хочет узнать, есть ли смысловая связь у слова «дом» с «структура» и если есть, то какая. Он обращается к базе. Та проходится по строке, и видит «home» в колонке «structure home». Дополнительно убедившись, что «structure» по отдельности переводится как «строение» (см. процедуру 1), база отвечает: да, связь есть и это «дом» входит в общее понятие «структура».

    Реально?

  • http:// splix

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