SQL vs NoSQL: как насчет других проблем, чем ACID и масштабируемости?

В последнее время я прочитал немало статей, описывающих SQL и NoSQL с обеих сторон разрыва, таких как http://use-the-index-luke.com/blog/2013-04/whats-left-of-nosql. Эти статьи очень часто затрагивают предметы, такие как ACID и масштабируемость. Тем не менее, ряд вопросов, которые я обычно имею с SQL, как правило, редко упоминаются в этих статьях, и мне было интересно, почему и что это связано с тем, что я не совсем понимаю SQL. Если кто-нибудь сможет просветить меня, по крайней мере частично, по одному или нескольким из следующих пунктов, я бы очень признателен.

Мои проблемы с SQL:

  • SQL по своей сути небезопасен: SQL - это язык, который был сделан для вставки и не имеет каких-либо методов предотвращения вставки кода вместо данных. Единственный способ предотвратить вставку - полностью изолировать SQL от приложения, используя его. Почему это еще не было разрешено в самом SQL?
  • Кажется, что SQL был сделан для наименьшего размера памяти для данных, содержащихся в нем. Хотя это все еще имеет большой смысл для огромных объемов данных, оно больше не подходит для небольших баз данных или делает это?
  • SQL заставляет все подогнать двухмерную реляционную модель, а конкретные таблицы отношений - для других измерений. Для меня это представляет собой две проблемы:
    • согласованность данных полностью зависит от таблиц отношений
    • данные очень трудно понять людям в случаях сбоев.
  • SQL не поддерживает историю, поскольку по умолчанию она выполняет деструктивные обновления: есть, конечно, всевозможные способы создания истории, но для этого требуются специальные письменные материалы с дополнительными таблицами и использование штампов времени или запись новый рекорд для каждого изменения, что приводит к экспоненциально растущим размерам таблиц.
  • SQL, похоже, предпочитает потерю данных для потери согласованности: если возникает ошибка или потеря согласованности, единственным способом восстановления ситуации в постоянном состоянии является использование резервной копии, что означает, что последние изменения будут уничтожены. Это отчасти из-за отсутствия истории (см. 4), но также из-за отсутствия читаемости для человека нет реального способа заставить человека исправить ошибки.
  • Особенно в веб-среде использование SQL обычно означает, что модели создаются часто более одного раза. В обычном (простом) веб-приложении PHP дважды: один раз в PHP, один раз в SQL. В веб-приложении полного стека три раза: один раз в клиентском приложении, один раз в промежуточном программном обеспечении и один раз в базе данных SQL (если ORM не используется). Из-за разных языков программирования и различий типов между ними это означает, что между этими моделями существует множество возможных конфликтов. Я знаю, что ORM, такие как ActiveRecord и Django, решают хотя бы часть этих проблем, но объем дополнительной работы вам еще нужно сделать, потому что таблица SQL содержит VARCHAR (25) и ни один из используемых языков (JavaScript, Ruby, PHP, Perl, Python и т.д.) Знают, что такая конструкция огромна.
  • Изменения структуры данных, по-видимому, рассматриваются как проблема согласованности: если что-то меняется в структуре данных, изменения таблицы применяются к каждой существующей записи в этой таблице, даже если запись не имела этого поля изначально и независимо от того, для этой записи имеет смысл иметь это поле. Набор этих изменений приводит к автоматическим переходам, которые добавляют еще один уровень возможных проблем, особенно в отношении согласованности.
  • Смешивание логики хранения и логики приложения: SQL, похоже, хочет сожрать части логики приложения в качестве хранимых процедур (CouchDB также делает это через представления). Хотя я понимаю, что для некоторых типов операций вам нужна серверная сторона и очень строго контролируемые процедуры, я не понимаю, почему они хранятся в базе данных и как таковая часть механизма хранения, а не являются частью приложения ( промежуточный слой).

Я знаю (но не очень хорошо знаю) такие вещи, как PostgreSQL Hstore, но я не вижу полностью, как это решает то, о чем говорилось выше. Спасибо за любые идеи!

Ответы

Ответ 1

  • Является ли SQL по своей сути небезопасным?

    Я думаю, вы имеете в виду SQL Injections, который является одной из самых опасных уязвимостей безопасности вообще.

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

    В любом случае SQL имеет системы безопасности звука, которые позволяют ограничить доступ к таблицам, представлениям, а иногда и выбранным строкам на основе некоторых правил ( "безопасность на уровне строк" ).

  • "наименьший размер памяти возможно"

    Извините, у меня нет этого вопроса.

  • О нормализации.

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

    • Как легко получить доступ к данным из многих таблиц.
    • Как поддерживать согласованность во многих таблицах.
    • Как справиться с намеренными "несоответствиями", ака. истории (изменения основных данных)

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

    Доступ к данным из многих таблиц должен выполняться с помощью объединений и аналогичных операций SQL. SQL делает больше, чем хранение и извлечение данных с использованием способа 1:1, он предоставляет инструменты (объединения, подзапросы, операции набора,...) для преобразования нормализованных данных в форму, наиболее подходящую для конкретной задачи. Это делается намеренно во время выполнения, потому что задачи не обязательно должны быть заранее известны. С другой стороны, характер данных данных считается статическим, так что сохранение его нормализованной моды является допустимым. Это очень важная ключевая концепция реляционной модели и SQL: характер данных не изменяется, так что он должен быть постоянным. Как вы используете эти данные, они широко варьируются и часто меняются с течением времени, поэтому это необходимо сделать динамичным. Это, конечно, очень обычная задача, так что имеет смысл иметь прочный инструмент, чтобы сделать его легким. Мы называем этот инструмент SQL;) Правило DRY может быть выполнено с помощью представлений или CTEs, но оба могут повредить потому что реализация не очень оптимизирована для этого (что я открыто критикую!).

    Сохранение данных, согласованных во многих таблицах, в основном выполняется с помощью ограничений.

    Обработка предполагаемых "несоответствий" (истории) была наконец покрыта SQL:2011: это позволит запросить "AS" и предоставить также инструменты для поддержания временной консистенции ( например, действительность одной строки может не совпадать с действительностью другой строки). Вероятно, довольно плохо, что потребовалось 40 лет или около того, чтобы придумать решение для этого. И я даже не знаю, когда это будет общедоступно!

    Я думаю, что эта часть в значительной степени верна для каждой системы: "данные очень трудны для людей, чтобы иметь смысл в случаях сбоев" (мой акцент). Однако, я думаю, вы можете иметь в виду, что трудно исследовать проблемы, потому что требуемые данные могут быть распределены по нескольким таблицам. Ответ SQL для этого: VIEWs, которые в основном просто сохранены. Однако в зависимости от диапазона базы данных VIEW могут возникать проблемы с производительностью. Это, однако, ограничение некоторых диапазонов базы данных, а не ограничение SQL или реляционной модели.

  • Сохранение истории

    Я уже упоминал выше (SQL: 2011).

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

    Инструментами для борьбы с ним являются триггеры или ORM. Если вы хотите быть уверенным, что никто не выполняет "деструктивное обновление", вы можете просто отменить права UPDATE на этой таблице (а также DELETE на стороне сохранения).

  • "предпочитают потерю данных для потери согласованности:"

    Я нахожу эту интересную точку зрения. Однако SQL-ответ на этот вопрос заключается в том, что вы очень стараетесь не ошибиться в системе в первую очередь. В основном, используя правильную схему, ограничения + ACID. Таким образом, ваше утверждение как-то правильно: вместо того, чтобы принимать противоречивые данные, отвергается (это нечто иное, чем потерянное!). Таким образом, вы должны обработать ошибку в то время, когда кто-то вводит отклоненные данные, а не некоторое время, когда вы пытаетесь устранить несоответствия, потому что вы приняли плохие данные в первую очередь. Итак, да, эта философия для реляционной модели и SQL!

    Отсутствие человеческой читаемости, очевидно, зависит от вашего фона. Тем не менее, правильная способность с использованием SQL довольно хороша, я бы сказал. Здесь я также хотел бы привести цитату из оригинальной статьи IBM о SEQUEL (в то время это было настоящее имя):

    SEQUEL предназначен как подъязык базы данных как для профессионального программиста, так и для более редкого пользователя базы данных.

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

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

  • Несоответствие импеданса объектов/реляций

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

  • Изменения структуры данных

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

    Это также довольно хорошо обсужденный аргумент: schema vs. "schema less". Выберите свой вкус. "Schema less" довольно часто означает "не предоставляет инструменты управления схемой", тем не менее вам приходится справляться с тем, что мы иногда хотим добавить дополнительные свойства к существующей сущности. RDBMS предоставляют инструменты для этого: новые столбцы могут быть обнуляемыми или иметь значения по умолчанию. Более резкие изменения, такие как перемещение одного атрибута в дополнительную таблицу (например, 1: n), можно выполнить с помощью CREATE AS SELECT. Возможно, вы даже представите представление совместимости, которое по-прежнему передает данные так, как должно быть (как будто перемещенный атрибут все равно будет храниться в таблице). После того, как вы изменили схему, ваше приложение может полагаться на его ограничения (например, наличие столбцов или допустимость ограничений). Это довольно много вещей, которые база данных может сделать для вас в чрезвычайно надежной манере. Вам больше не нужно заботиться о своем приложении.

    Аргумент, о котором вы не говорили, заключается в том, что эти изменения схемы часто связаны с простоем. Это окончательно верно для прошлого, а в некоторой степени и сегодня. Например. MySQL представляет онлайн ALTER TABLE только в 5.6 недавно. Однако это довольно частое ограничение реализации, а не проблема, связанная с реляционной моделью или SQL. Даже некоторые более сложные изменения (например, перемещение атрибута в другую таблицу) можно сделать онлайн, когда все сделано правильно и тщательно спланировано (я сделал это с одной из дорогостоящей базы данных, которая предоставляет все необходимые для этого инструменты). Как правило, это сохранение кода миграции из вашего приложения и копирование в базе данных с ним. После миграции у вас не должно быть артефактов миграции в БД или в коде приложения. Конечно, бывают случаи, когда время простоя неизбежно (я думаю;).

  • "Смешение логики хранения и логики приложения"

    SQL фактически делает совершенно противоположное: SQL полностью абстрагирует слой хранения.

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

    Второй аргумент - это, конечно, чрезмерное использование ORM снова и политики, которые запрещают использование реального SQL в приложении.

Ответ 2

  • SQL по своей сути небезопасен. Нет, это не так. Используйте параметризованные утверждения.
  • SQL, похоже, сделан для наименьшего размера памяти. Это лишь вторичное следствие сокращения дублирования посредством нормализации. Преимущества нормализации - это небольшие обновления и упрощенная проверка ограничений.
  • SQL заставляет все вписываться в двухмерную реляционную модель. Это несколько верно для DML (запрос), но не для DDL (определение данных), что гораздо важнее. Современный SQL разбивает 2D-композицию в любом случае с помощью таких технологий, как postgres json.
  • SQL не поддерживает историю: это полностью фиктивный. Тривиально поддерживать историю через триггеры, но это абсолютно не должно быть дефолтом. Время во времени данных невероятно интенсивно, но, если вы это сделаете, будет проще и меньше в SQL vs noSQL из-за нормализации и возможности запуска RI во времени, если вам нужна формальная проверка исторических ограничений.
  • SQL, похоже, предпочитает потерю данных для потери согласованности. Это не следует. Существует много способов восстановления согласованности за пределами восстановления из резервных копий.
  • В веб-приложении полного стека три раза. Это правда. Но вы хотите сократить жир в неправильном месте. SQL - это очень формальное определение данных. Подумайте о том, чтобы удалить ORM и сократить сторону клиента.
  • Изменения структуры данных, по-видимому, рассматриваются как проблема согласованности: Это просто неверно. вы можете оставить новый рекорд по умолчанию null, который в большинстве реализаций sql не приведет к перезаписыванию записи (ALTER TABLE foo ADD f TEXT; is O (1)). Также обратите внимание, что изменения структуры postgres являются транзакционными и могут быть отброшены назад.
  • Смешение логики хранения и логики приложения. Это довольно глупый аргумент. Это аналогично высказыванию бинарных файлов C не следует компилировать с помощью структур данных. Нет такой вещи, как "логика хранения, бизнес-логика или логика приложения". Там просто логика. Логика связи более жесткая к структурам данных значительно повышает производительность и упрощает управление функциональными зависимостями. Я никогда не пойму, почему программистам лучше "заставить" сериализовать базу данных через протокол, перенести ее в приложение на другой процесс (или даже на другой сервер) и записать его обратно в базу данных с помощью десериализации вместо того, чтобы позволить базе данных сделайте это.