О том, что объёмы данных, сложность их структуры, сложность связей между ними растут совершенно невероятными темпами, пишут на каждом заборе уже много лет. Вопрос же о том, что делать со всей этой свалкой обычно повисает в воздухе. Или, точнее, упирается в понятие «модель данных». Хотя формально моделей данных великое множество (сетевая модель Ч. Бахмана, реляционная модель Э. Кодда, ER-модель П. Чена, различные объектные модели, что-то специализированное под темпоральные и пространственные данные, многомерные кубы и т.д.), все они, за исключением первых двух, предназначены для представления данных конечному пользователю и/или их аналитической обработки прикладными утилитами, а на уровне доступа к данным они опираются на одну из базовых (обычно РМД).

Что такое модель данных, толком не знает никто. Существует множество определений, однако единая общепризнанная формулировка отсутствует. Сам автор термина «модель данных», Эдгар Кодд (он же автор РМД), определяет его как комбинацию трёх компонентов:
  1. Коллекции типов объектов данных, образующих базовые строительные блоки для любой БД данной модели.
  2. Коллекции общих правил целостности, ограничивающих набор экземпляров этих типов объектов.
  3. Коллекции операций, применимых к таким экземплярам.

Современные определения мало отличается от вышеприведённого. Если объединить все характеризующие понятие признаки в общую формулировку, определение выглядит приблизительно так: «Модель данных — это логическое определение объектов, операторов и правил, в совокупности составляющее для пользователя абстрактную машину доступа к данным».

Такое определение, по сути, не говорит вообще ни о чём. Никому. Между тем, Кристофер Дейт как-то сказал замечательную фразу: «Модель данных есть теория, или средство моделирования, в то время как модель базы данных (схема базы данных) есть результат моделирования. Соотношение между этими понятиями аналогично соотношению между языком программирования и конкретной программой на этом языке». Как видим, Дейт, сам того не желая, дал совершенно блестящее определение модели данных, очень компактное и понятное даже ребёнку: модель — это язык!

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

Сетевая модель


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

Пожалуй, основными претензиями к сетевой модели является то, что логика процедуры выборки данных (якобы) зависит от их физической организации, а также, что там (якобы) ослаблен контроль целостности данных из-за допустимости установки произвольных связей между элементами. Эти претензии справедливы лишь в том случае, если под сетевой моделью понимать её эталонный вариант, описанный в отчёте рабочей группы по языкам баз данных (COnference on DAta SYstem Languages) CODASYL. Между тем, подход CODASYL далеко не единственный: можно спроектировать множество других реализаций сетевой модели, в том числе свободных от большинства приписываемых ей недостатков.

Забавно, но определение сетевой модели данных дал главный её конкурент, всё тот же Кодд. Ещё более забавно, что до сих пор при сравнении этих моделей противопоставляется абстрактная РМД конкретным спецификациям CODASYL (сам Кодд называл это «сравнением яблок с апельсинами»!), что есть фактически жульничество и принижение реальных возможностей сетевой модели, которая может составить куда более серьёзную конкуренцию РМД, чем сейчас. К сожалению, эта «клевета» Кодда на сетевую модель попала чуть ли не во все учебники и напрямую связана с отождествлением сетевой модели с подходом CODASYL. Если для РМД «получение физического доступа к кортежу не является вопросом модели данных», то для сетевой модели «изменение структуры БД требует больших усилий и времени, поскольку операции модификации и удаления данных требуют перестановки указателей» — очевидное передёргивание. Или ещё одно: «Указатели не обязательно должны быть представлены на физическом уровне хранения как указатели, однако пользователи обязаны относиться к ним, как к реальным указателям — такова сетевая модель». Не «сетевая модель», а лишь представление о ней Кодда!

Реляционная модель


Поскольку сейчас почти все СУБД именно реляционные, естественно предположить, что у РМД есть ряд важных преимуществ (прежде всего, высокая степень независимости данных). Тем более что многим клиентам удобно представление данных в простых отношениях, с ясными структурами данных и привычным языком запросов SQL (Structured Query Language). Но и недостатков у РМД множество, и они достаточно очевидны: отсутствие прямых ссылок на поля кортежа, неприлично высокий уровень затрат на создание или модернизацию схемы БД, причём изменение схемы иногда невозможно без отказа от старых данных, т.к. структурная информация в них вообще отсутствует. Широко распространённая ситуация для реальных табличных данных, когда невозможно однозначно идентифицировать элемент по данным его атрибутов, в РМД просто запрещена. Операция соединения по одному или более атрибутам, главный механизм, используемый в реляционной модели, чтобы связать данные различных отношений, выполняется всегда к целому кортежу, но не к его части. Запросы по множеству таблиц выполняются очень долго: концептуально реляционная алгебра оперирует понятием «Декартова произведения», использовать которое слишком дорого, поэтому применяют разные техники оптимизации запросов. Нормальные формы, иерархичные по природе, тоже приводят к ограничению сложности поддерживаемых структур данных. Между тем, идея самого Кодда состояла в том, что «при выборе логических структур данных должно присутствовать лишь одно соображение — удобство большинства пользователей». Подобная жёсткость подхода к простоте представления данных (которые всё это время имели явную тенденцию к усложнению), дополненная появлением нормальных форм, уже привела к ситуации, что ни одна (!) реальная РСУБД в действительности РМД не поддерживает. В частности, обычным явлением стал отказ от нормализации таблиц.

Сам Кодд пропагандировал трёхзначную логику (истина, ложь и NULL), а в 1990 даже четырёхзначную, однако из-за высокой сложности (!) в «Третьем Манифесте» К. Дейта и Х. Дарвена запрещены как неопредёленные значения, так и многозначная логика! Цитирую:
Третий манифест
Х. Дарвин и К. Дэйт, Перевод: М.Р. Когаловский
РМ-запреты
4. Каждый атрибут каждого кортежа каждого отношения должен иметь значение, которое является значением из соответствующего домена.
Комментарии (там же):
Иными словами, больше никаких неопределенных значений и больше никакой многозначной логики!


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

Цель Кодда — «переместить прикладное программирование на уровень, где отношения трактуются как операнды, а не обрабатываются поэлементно». Замечательная цель: язык, позволяющий работать с множествами, бесспорно, удобен. РМД, однако, предполагает работу только с множествами: никаких покортежных операций, единичный кортеж есть просто частный случай множества, запрещается концепция курсора и т.д. А в таких «коротких штанишках» становится уже тесно даже SQL — ближайшему родственнику РМД, хотя в математике (и в SQL, с которым реляционщики вроде Дейта ведут борьбу не на жизнь, а на смерть) кортежи упорядочены, разрешаются их дубли. Мало того, сам Кодд первоначально определял кортежи именно так! Отказ от упорядочивания рассматривается Дейтом как «величайший вклад (!) Кодда в РМД». В ООБД, однако, «почему-то» вновь требуется поддержка индивидуальности объектов, т.е. «объекты должны иметь уникальный идентификатор, который не зависит от значений их атрибутов». Почему? Да потому, что «величайший вклад» есть полная фикция!

Предположим, мы имеем РБД, состоящую всего лишь из одного отношения. Заведём дополнительный столбец, значениями которого будут порядковые номера кортежей (с единицы). Именами столбцов также установим их порядковые номера (с нуля). Определим нулевой столбец как первичный ключ (или «суррогатный», или «системно-генерируемый», как «весьма настоятельно» рекомендуют авторы «Третьего Манифеста»). Теперь мы можем получать доступ к столбцам и кортежам по их номеру (как и в SQL), но в строгом соответствии с РМД. Что же изменилось? Мы всего лишь утратили возможность прямого доступа к полям и кортежам (т.к. РМ-предписания запрещают упорядочение атрибутов или кортежей), и автоматически перестали бояться дубликатов кортежей и неопределенных значений. А где же преимущества того, что наше отношение теперь идеально соответствует требованиям «Третьего Манифеста»? Их нет! Вне РМД мы можем точно так же ссылаться на кортежи этого отношения из других (или из него самого), можем вычислять физический адрес кортежа по значению суррогатного ключа (и контролировать его при желании по значению нулевого столбца), т.е. внешний ключ реально становится указателем. Таким образом, концепции, воплощённые в SQL, как минимум, не хуже РМД. Так почему же «безнадёжно следовать извращению РДМ, воплощенному в SQL», как писали Дейт с Дарвеном? С какой стати «чтобы выдержать испытание временем, следует недвусмысленно отвергнуть SQL»? Что-то здесь не так!

Мы полагаем, что отказ от упорядоченности есть неизбежное следствие «структурного аспекта»: данные РБД определены как набор отношений, т.е. первичный элемент есть группа. Совершенно неизбежным и страшным следствием отсутствия упорядоченности является также концепция ключа. Понятие идентификатора, «жульническим» образом изъятое из модели данных, принципиально не может быть убрано также из РСУБД: ведь даже для тривиального чтения значения ключа нужно получить доступ к кортежу каким-то иным способом. Как видим, избавиться от понятия идентификатора нельзя — можно лишь сделать вид, что его не существует при групповой обработке данных. К тому же, говорить о скорости доступа к данным при концепции поиска по ключу — насмешка над здравым смыслом. Впрочем, РМД никогда не интересовали вопросы реализации, получения физического доступа к кортежу: она предписывает ассоциативный доступ к данным (на основе значений), а как это реализуется в конкретной системе, для модели совершенно неважно.

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

Есть только один вид доступа к данным, пригодный для реально работоспособной СУБД, и называется он «прямой» (а концепция ключа, между прочим, его явно запрещает — в отличие от SQL). Третий Манифест: «РМ-предписания и запреты не могут быть предметом компромисса». Даже несчастный курсор «категорически запрещается», а уж более примитивной навигации просто не бывает в природе! РМД именно категорически запрещает их иметь, ибо концепция ключа сразу же превращает любые навигационные операции в рекурсивный SQL-запрос: раз кортежи идентификатора иметь не могут, нам придётся рыскать по значениям, хоть ключом их обзови. И обязательный первичный ключ на реляцию вынь, да положь. И одинаковых кортежей заводить не моги, худо будет. И никакие индексы, никакие костыли не спасут идеологически неполноценную конструкцию!

SQL


Отношение к SQL у разных пользователей весьма неоднозначное, иногда диаметрально противоположное. Лично мне ближе такая его характеристика: «SQL — один из самых убогих языков, кривое детище Дональда Чемберлена сотоварищи». Точнее, их последователей — те, по крайней мере, понимали, что никакой это не язык: «Целью разработки было создание простого непроцедурного языка, которым мог воспользоваться любой пользователь, даже не имеющий навыков программирования». То есть это язык запросов, причём конечного пользователя! Назвать его «языком программирования» тогда никому и в страшном сне не могло присниться! А теперь та же Вики нагло утверждает, что «SQL можно назвать языком программирования», стыдливо добавляя, что «он не является тьюринг-полным».

Ещё одна фраза из Вики: «SQL (structured query language — язык структурированных запросов) — декларативный язык программирования, применяемый для создания, модификации и управления данными в реляционной базе данных. Это единственный механизм связи между прикладным программным обеспечением и РБД».

Одуреть! В самой расшифровке языка говорится, что это язык ЗАПРОСОВ, а в «пояснении» — что это язык ПРОГРАММИРОВАНИЯ!

Стандарт SQL. Отдельная песня. Во-первых, он неприлично раздут в размерах при очень слабой функциональности языка (например, базовая часть стандарта SQL:2003 состоит из более чем 1300 страниц текста). Даже Великй и Могучий С потребует уж никак не больше десятка страниц! А здесь что? Один-единственный оператор SELECT? Что ещё? CREATE — INSERT — DELETE — UPDATE? GRANT — REVOKE? COMMIT — ROLLBACK — SAVEPOINT? Не смешите мои тапочки!

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

SQL не является истинно реляционным языком: он разрешает в таблицах строки-дубликаты, что в рамках реляционной модели данных (к слову, ещё более убогой, чем SQL) невозможно и недопустимо, поддерживает неопределённые значения (NULL) и многозначную логику, использует порядок столбцов и ссылки на колонки по номерам, разрешает колонки без имени и дублирующиеся имена столбцов. За это на него матерятся реляционщики-теоретики вроде Дейта с Дарвеном, что, в общем-то, понятно: ещё из школьного курса биологии известно, что «внутривидовая борьба — самая жестокая».

SQL изначально вообще не предлагал способов манипуляции даже иерархическими структурами, не говоря уже о графах общего вида. Даже рекурсивные запросы (которые дают экспоненциальное замедление производительности с увеличением глубины связей) появились в Microsoft SQL Server лишь в версии 2005. SQL не является привычным процедурным языком программирования (то есть не предоставляет средств для построения циклов, ветвлений и т. д.), поэтому производители СУБД вводят различные процедурные расширения — хранимые процедуры и процедурные языки-«надстройки». Практически в каждой СУБД применяется свой процедурный язык (Oracle — PL/SQL, Interbase и Firebird — PSQL, в DB2 — SQL PL, в MS SQL Server — Transact-SQL, в PostgreSQL — PL/pgSQL и т.д.). И нафига мы стандартизуем SQL с его фактически единственным оператором SELECT, который, к тому же, почти ничего не умеет делать?

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

NoSQL


В последнее время термин «NoSQL» стал очень модным и популярным, активно развиваются и продвигаются всевозможные программные решения под этой вывеской, говорятся всякие «умные слова», вроде «линейная масштабируемость», «кластеры», «отказоустойчивость», нереляционность", NoSQL хранилище прижилось в качестве основной базы данных для социальных сетей Instagram и Facebook, но никакой «NoSQL-революции» не произошло — реляционные базы данных стабильно удерживают доминирующие позиции. И дело даже не в мощнейшем «реляционном лобби», а в том, что продукт этот достаточно сырой, ему не хватает множества базовых вещей — универсальности, надежности, целостности и предсказуемости. А потому трактовка термина «NoSQL» всё больше смещается в сторону «Not Only SQL», хотя изначально в качестве альтернативы предлагали даже «NonRel», но быстро успокоились, и сейчас более 90% действующих СУБД и БД построены по реляционному принципу, в основе которого лежит табличная схема компоновки данных — особенно, если учесть, что подавляющее большинство остальных решений, хотя и называются NoSQL, фактически оперируют всё равно с таблицами. Данные и там, и там ИДЕОЛОГИЧЕСКИ табличны! В полном соответствии с первым же из «12 правил Кодда», которое гласит: «Вся информация в реляционной базе данных на логическом уровне должна быть явно представлена единственным способом: значениями в таблицах».

Великий Спор


Сегодня уже основательно подзабытый, «Великий Спор» между Коддом и Бахманом состоялся в 1974 году на семинаре ACM SIGMOD, где каждый из докладчиков стремился показать преимущества своего подхода. Тогда современники говорили, что спор закончился вничью, поскольку никто из присутствующих (включая самих спорщиков) так ничего и не понял. Теперь, задним числом, принято считать, что победу одержал Кодд, ибо реально работающие СУБД сейчас почти все реляционные. Но до сих пор, как отголосок этого спора, при разговоре о моделях данных противопоставляют поэлементную и групповую обработку данных. На самом деле такое противопоставление есть просто глупость.

Общеупотребительным (хотя не всегда явно определённым) термином во всех моделях является поле — наименьший, неделимый, атомарный элемент данных заданного типа. При этом термин «тип данных» может нести весьма разнообразную смысловую нагрузку: он может определять объём памяти, занимаемый элементом, набор допустимых значений, набор ассоциированных с этим типом операций, дескриптор устройства, связь с другими элементами и многое другое. Кроме атомарных, существуют также элементы данных, представляющие собой группы полей, называемые разными авторами «сегментами», «наборами» и другими терминами. Существует два типа групп однородных элементов: массив (множество элементов заданного размера) и строка (размер этой группы определяется по заранее установленному значению терминатора). Группы же разнородных элементов фактически отличаются друг от друга лишь названием: узел (графовая модель), кортеж (реляционная модель), класс (объектный подход), структура (языки программирования).

После согласования терминов легко видеть всю нелепость предмета Великого Спора: проблема вовсе не в сравнении конкретных описаний CODASYL и абстрактной РМД. И не в том, что сравнивается табличное и графовое представление данных — в конце концов, это всего лишь абстракция. И не в принципиальных различиях понятий ключ и указатель — это лишь прямое следствие главной ошибки: сравнение групп с атомарными элементами. В РМД первичный элемент есть таблица, т.е. группа. Но если мы определим отношение как «массив кортежей», а сам кортеж как «совокупность полей», тогда, действительно, станет возможным реальное сравнение полей и кортежей РМД с узлами и рёбрами сетевой модели.

Теперь повторим попытку сравнения этих двух моделей, имея в виду, что узел может содержать не только атомарный элемент, но и структуру, а термин tuple эквивалентен struct (т.е. член группы тоже может быть группой). После этого мы не только сможем корректно сравнивать модели данных, но и совершенно автоматически получим объектную модель данных вместо реляционной (хотя и ценой уничтожения реляционной алгебры). И такое сравнение окажется отнюдь не в пользу РМД: мы сразу же увидим набор неоправданно жёстких ограничений на сложность данных в отношениях. В самом деле: почему разрешено комплектовать в единое отношение лишь однородные элементы? Почему нельзя адресоваться непосредственно к внутренним элементам кортежа? Почему кортежу запрещено иметь свой собственный, не зависящий от данных идентификатор? С какой стати мы должны упираться рогом в эту несчастную концепцию «ключа»? За какие провинности нам запретили иметь в кортеже структуры сложнее одноуровневого дерева? И зачем нам это прокрустово ложе нормальных форм? Ради чего? Ради упрощения формального аппарата алгебры отношений и реляционного исчисления? А кому они, собственно, нужны? Разработчикам СУБД? Администраторам? Пользователям?

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

Поиск информации


При поиске информации графовая модель предоставляет более широкие возможности, поскольку позволяет создавать очень гибкие запросы, используя механизм преобразования типов и навигационные выражения. Например, возможно запросить всю информацию о текущем объекте базы данных, которая там вообще есть (что-то типа FIND.CURRENT.ALL), поскольку именно связи между элементами позволяют СУБД выявить (без какого-либо дополнительного поиска!) и сообщить пользователю эти сведения. Извлечь подобную информацию из аналогичной РБД практически невозможно. Кроме того, граф — это прекрасное подспорье для «чайника», который и знать не знает, как нужно спрашивать, чтобы получить то, что нужно именно ему, а вовсе не то, что поисковик думает по поводу его запроса. Наконец, запрос из разового становится итерационным — ответы сервера всё чаще содержат информацию, интересующую именно потребителя.
Иллюстрация: юзер запросил слово «кофе». Поисковик ему что-то там прислал (по своим соображениям), но одновременно привёл список сопутствующих ключевых слов: сорта, рецепты, производители, кофемолки, технология выращивания, история и культура потребления, кофе-брейк, и даже чай (как альтернатива кофе). Да любой клиент с радостью уточнит запрос!

Верификация


Везде, где присутствует человек, любые средства интерфейса и входного контроля могут лишь снизить вероятность внесения ошибок, но никогда не устранят их полностью. Из выпадающего меню обязательно будет выбран соседний пункт (промах мышкой), в результате чего «улица маршала Рыбалко» превратится в «улицу маршала Соколовского» (реальный случай из практики), а пресловутый Вася Иванов обязательно получит «женский пол» в радиокнопке. Но самое неприятное, что неверно записанное значение какого-либо поля приводит к лавинообразному росту паразитных записей, и, как следствие, к наведённым ошибкам при поиске и анализе информации. Забавный пример: сотрудники два дня искали одного старичка с фамилией ИBАНОВ (в нижнем регистре иbанов). И стоит проблема верификации весьма остро!

В РСУБД средства верификации отсутствуют как класс. Мало того — вот ещё одна цитата из Вики: «В криптографии и информационной безопасности целостность данных (в широком смысле) — это сохранение данных в том виде, в каком они были созданы». Видали? Это фактически запрещает правку данных вообще! Обнаружили ошибку? Не моги исправлять! А то целостность данных будет нарушена (в широком смысле).

И ещё одна проблема: база данных развивается, состав и объём данных изменяется, и потому ясное представление о конечной структуре БД (и, соответственно, дизайн, спроектированный с учетом её особенностей) невозможен в принципе. Информационные потребности пользователей также разные, и они изменяются со временем. Следовательно, БД должна периодически перестраивать свою структуру согласно изменению их потребностей или вследствие изменения самих данных. Это уже не просто верификация — это ещё и реструктуризация, изменение схемы БД во время её эксплуатации!

Заключение


Нам представляется правильным вместо «Великого Спора» объявить «Великое Перемирие» не противопоставлять, а объединить реляционный и сетевой подходы в рамках единой модели данных. Если такая задача осуществима, то и все остальные модели данных наверняка укладываются в общую схему, поскольку все они базируются либо на табличном, либо на графовом представлении данных. Так можно ли «скрестить ежа с ужом», свести воедино модели Кодда и Бахмана, сохранив достоинства и устранив недостатки каждой из них? Вопрос нужно ставить даже не так: это нужно сделать!

В графовом представлении БД должна выглядеть как распределённый, многомерный, циклический, смешанный граф с разнородными элементами произвольной структуры, каждый узел которого имеет, в общем случае, переменное количество связей с другими узлами (рёбер), в т.ч. нулевое, при этом рёбра также могут иметь свои собственные «персональные» данные. Необходимо уйти от подхода CODASYL, включив отношения «многие-ко-многим». А с реляционной точки зрения те же данные, представляют собой единое отношение неоднородных кортежей, и для них, соответственно, допустима не только поэлементная, но и групповая (реляционная) семантика операций по обработке данных. В отличие от РМД, допускаются дубли кортежей, допускаются ссылки не только на кортежи, но и на их поля. Поскольку нормализация отношений часто затрудняет обработку сложно организованных данных, её следует отменить. В частности многозначные атрибуты и неатомарные поля данных вполне допустимы. Помимо прямого доступа к любому элементу данных, необходимо обеспечить возможность свободное изменение его размера, структуры и/или количества связей с другими элементами. Разнообразие типов данных может быть сколь угодно большим. Конечно, количество базовых типов (BOOLEAN, FLOAT, URL) относительно невелико — ведь при их определении приходится прописывать (а нередко и программировать) методы и правила их обработки, а это достаточно сложное и трудоёмкое занятие. А вот создание пользовательских типов (TUPLE, ENUM, RELATION) куда проще — здесь есть, где разгуляться! Можно определять как реляционные (именованная группа полей одного узла), так и графовые типы данных (именованная группа полей разных узлов). Например, тип ADDRESS может быть представлен как кортеж (Страна, Город, Улица, Дом, Квартира) или как субграф (Квартира -> Дом -> Улица -> Город -> Страна). И хотя для конечного пользователя эти два типа вряд ли различимы, уже сам факт использования графового типа ADDRESS позволяет выявлять логические ошибки в данных: СУБД просто не позволит внести неверные данные сообщением, вроде: «В этом городе такой улицы нет».

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

Применение суррогатного ключа в качестве идентификатора позволяет сохранить традиционные преимущества сетевой модели: прямой доступ к данным, навигационные выражения в запросах. Но теория операций групповой обработки данных по-прежнему представлена всё той же реляционной алгеброй. Более высокая потенциальная мощь сетевой модели сегодня не используется вообще из-за отсутствия соответствующего математического аппарата для работы с множествами. Проблема также и в том, что рёбра графа не могут быть представлены ни как ключи в РМД (теряется прямой доступ к данным), ни как указатели в CODASYL (нарушается принцип независимости данных, ведь указатели зависят от природы физического хранения данных и потому требуют перестройки при обновлении данных или изменении схемы БД). И вообще подобная модель содержит массу весьма сложных алгоритмических и технических проблем. Но ведь нужно же что-то делать с этой лавиной обрушившихся на нас данных, нужно как-то разгребать эту свалку! Хватит играть в реляционные погремушки!

Комментарии (52)


  1. lair
    30.05.2019 19:05
    +2

    Давайте, что ли, начнем с конкретики.


    Например, тип ADDRESS может быть представлен как кортеж (Страна, Город, Улица, Дом, Квартира) или как субграф (Квартира -> Дом -> Улица -> Город -> Страна).

    Предположим, мы рассматриваем второй сценарий, при котором каждый элемент адреса (квартира, дом, улица и так далее) — это узел графа. Чем является в таком случае сам "пользовательский тип ADDRESS"? Ссылкой (идентификатором) узла в графе? Кортежем таких ссылок? Чем-то третьим?


    Чтобы вопрос стал понятнее, давайте попробуем еще сильнее упростить: сведем все к "Город — Страна". Страна — это пользовательский тип, представляющий собой узел графа с идентификатором и названием. Верно? Или как-то иначе? Город — это пользовательский тип, представляющий собой… что?


    1. valemak
      30.05.2019 19:44

      del


  1. Tzimie
    30.05.2019 19:18
    +3

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


  1. rybvv Автор
    30.05.2019 19:46
    -13

    Ладно, хоть у меня и режим «1 коммент в сутки», в честь моего выхода из очередного «месячного» бана, отправлю коммент не только сюда: sint.wc.lt/habr.htm

    Ишь ты поди ж ты! Вышел я из бана, а карма у меня уже -47, а рейтинг у меня -101 с копейками… но это, конечно, было ожидаемо, а вот что мой рейтинг КАК ЛОМАНУЛ вверх!.. :) Уже -97.0 и заметка моя уже +8 имеет, без единого минуса! Я же заявлял выше, что именно от этой заметки ожидаю падение кармы ниже -100! Правда, ещё и полутыщи просмотров нет, так что ещё не вечер… :) Нет, уже 629 просмотров, всё ещё +8, и даже карма поднялась до -46.

    lair
    Давайте, что ли, начнем с конкретики.
    Вы — и конкретика?! Это что-то новенькое… :)

    Предположим, мы рассматриваем второй сценарий, при котором каждый элемент адреса (квартира, дом, улица и так далее) — это узел графа. Чем является в таком случае сам «пользовательский тип ADDRESS»?
    Видите ли… заметку эту я написал минут за двадцать, сильно сократив описание одной из глав моей книги. И это действительно СЛОЖНАЯ тема! Она НАМНОГО сложнее «комми», не говоря уже о сраном «сортире». Ну не Ваш это уровень, не берите в голову. Тем более, что в заметке написано, что это есть «элемент графового типа данных (именованная группа полей разных узлов)».

    Чтобы вопрос стал понятнее, давайте попробуем еще сильнее упростить: сведем все к «Город — Страна». Страна — это пользовательский тип, представляющий собой узел графа с идентификатором и названием. Верно? Или как-то иначе?
    Иначе, иначе! И НАМНОГО сложнее! Ладно, вот Вам фрагментик таблицы из моей книги. И даже не «для общего развития», а чтобы вопросы не задавали. :)

    8|tag|6|STRING|STRING|STRING|STRING|BYTE
    9|data|8|Россия|Курск|Лсная|5|NULL
    10|class|11|Страна|NULL|Города
    11|type|12|TEXT|SET/IDN|
    12|tag|10|STRING|ARRAY/DW/BYTE
    13|data|12|Россия|3 / 17 / 18 / 19
    14|class|15|Город|NULL|Страна|Улицы
    15|type|16|TEXT|IDN|SET / IDN
    16|tag|14|STRING|DW|NULL
    17|data|16|Курск|13
    18|data|16|Тверь|13
    19|data|16|Новгород|13
    20|class|21|Адрес|Страна|Город|Улица|Дом|Квартира
    21|logic|22|0|1|2|3|4
    22|ptrn|23|3 / 2 / 2 / 1|3 / 2 / 1|3 / 1|1|2
    23|type|24|TEXT|TEXT|TEXT|INT|INT
    24|tag|20|WORD|BYTE|DW
    25|data|24|5|NULL|27
    26|tag|0|STRING|DW
    27|data|26|Лесная|17

    Tzimie
    Ведь именно за счет последовательного скана без перемещения головки реляционные базы рвали остальных по производительности, как тузик грелку (а сетевые приводили к хаотическому перемещению головки)
    Нет, ребята, всё не так! Всё не так, ребята!(с) :) Ситуация НАМНОГО сложнее, и проблемы там именно алгоритмические, а не технические.


    1. Peter03
      30.05.2019 20:18
      +6

      а вот что мой рейтинг КАК ЛОМАНУЛ вверх!.. :) Уже -97.0 и заметка моя уже +8 имеет, без единого минуса!
      Наверное на хабре люди более адекватные чем вы себе представляете и при публикации статьи с интересным контентов не смотрят на ваши прошлые заслуги
      Ну не Ваш это уровень, не берите в голову.
      Продолжайте в том же ключе и ваша карма вернётся к тому что было. Если у вас есть что конструктивно сказать по этому поводу, создайте аккаунт rybvv2 и выскажитесь по существу, без поливая помоев всех кто по вашему мнению ничего не понимает (даже если действительно не прав и не понимает)
      Но ведь нужно же что-то делать с этой лавиной обрушившихся на нас данных, нужно как-то разгребать эту свалку! Хватит играть в реляционные погремушки
      Есть высказывание — практика, это критерий истины. И если вы не видите причин почему реляционные базы данных используются в подавляющем большинстве случаев, это не значит что их нету.

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

      Если же вы считаете что Oracle/MS/IBM создают искусственные препятствия на пути сетевой модели, посмотрите на open source. Тоже не видно множества кандидатов, хотя некоторые из RDBMS уже добавили часть возможностей сетевых баз.


    1. Hardcoin
      30.05.2019 20:23
      +9

      У вас один комментарий в сутки, а вы его тратите на то, что ты нахамить. Какой результат своих действий вы ожидаете?


    1. lair
      30.05.2019 21:15
      +2

      Видите ли… заметку эту я написал минут за двадцать, сильно сократив описание одной из глав моей книги.

      Поскольку книга мне недоступна (да и вроде она не является темой статьи), будем обсуждать то, что написано в статье. Как сократили — так и сократили.


      Тем более, что в заметке написано, что это есть «элемент графового типа данных (именованная группа полей разных узлов)».

      Я специально перечитал статью еще дважды, и там такого не написано. Там написано уже процитированное мной "тип ADDRESS может быть [...] как субграф" (понятие "субграф" нигде не определяется), и далее "факт использования графового типа ADDRESS". Наверное, из этого можно предположить, что "субграф" и "графовый тип" — это одно и то же. Это так или нет?


      Что важно, так это то, что ADDRESS — это пользовательский тип. Как тип может быть "элементом типа"?


      Вернемся к вашей фразе "графовый тип данных (именованная группа полей разных узлов)". Что это означает? Что мы взяли какие-то узлы, у них выбрали поля (то есть значения) — и получили тип? Можете показать конкретный пример?


      Иначе, иначе! И НАМНОГО сложнее! Ладно, вот Вам фрагментик таблицы из моей книги.

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


      Или давайте даже вернемся еще на этап назад: что такое в вашей терминологии "пользовательский тип"? Можете дать полное непротиворечивое определение и привести примеры?


      1. RussDragon
        30.05.2019 21:46
        +2

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

        Вам не жалко своё время? Не мне, конечно, судить…


        1. lair
          30.05.2019 21:51
          +4

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


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


    1. McKinseyBA
      30.05.2019 21:16

      Вы поднимаете интересные вопросы, но этим «комментом по Фаберже» убиваете желание дискутировать. А жаль. На Хабре редко пишут о таких вещах. Если позволите ИМХО: как посоветовали ранее — создавайте новый аккаунт и попробуйте писать статьи, но не комментарии.


  1. musicriffstudio
    30.05.2019 20:23
    +1

    Что такое модель данных, толком не знает никто.


    википедия знает все
    В классической теории баз данных, модель данных есть формальная теория представления и обработки данных в системе управления базами данных (СУБД), которая включает, по меньшей мере, три аспекта:

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


    И дело даже не в мощнейшем «реляционном лобби», а в том, что продукт этот достаточно сырой


    аналогично, википедия

    Such databases have existed since the late 1960s, but did not obtain the «NoSQL» moniker until a surge of popularity in the early 21st century

    за 50 лет остались сырыми — это называется иначе.

    Ну и т.д.

    Нужно было просто в самом начале определиться что значит «Сложные базы данных» в конкретных цифрах, поделить по простоve количеству таблиц-сущностей-объектов связанных между собой

    — меньше 100 — простая база данных
    — от 100 до 1000 — сложная база данных
    — свыше 1000 — очень сложная база данных

    Скажем, база данных с постами и пользователями сайта Хабр.ком — скорей всего менее 100 таблиц, т.е. простая. База с данными клиентов банка и платежами скорей всего в пределах 1000 таблиц, т.е. сложная.

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


    1. FDA847
      30.05.2019 23:06

      Как я понимаю, бешеная популярность реляционных БД объяснятся как минимум следующим:
      1. Они могут описывать любую предметную область.
      2. Существует чёткий математический аппарат (реляционная алгебра) для работы с ними.
      3. Сама суть «таблички» чрезвычайно понятна практически любому человеку, даже неспециалисту.
      Безусловно, у них есть недостатки при хранении сложно структурируемых данных.
      Но чёткая формализация, по всей видимости, всё таки является довольно сильным доводом в плане удержания их позиций.


      1. Mikluho
        31.05.2019 00:22
        +1

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

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


        1. norguhtar
          31.05.2019 09:25

          В их прокрустово ложе при некоторых ухищрениях можно уложить практически все что угодно. Плюс эта же ограниченность позволяла получать более менее нормальную производительность. Раньше еще была проблема когда надо положить слабо структурированные данные. И это решалось через EAV, что скажем было не очень удобно. То сейчас к примеру в PostgreSQL решается через специальное поле хранящее JSON. И да о ужас по этому полю можно строить индекс.


          1. InChaos
            31.05.2019 13:13

            В MS SQL тоже есть JSON поля, в угоду современным разработчикам и индекс тоже можно. Но как всегда но… или проще писать или быстрей выполняться, что выберают современные разработчики понятно и так.

            При сравнении JSON поля с нормальной структурой, которой можно описать все
            Основная таблица — Ид_Док, Наименовение_Поля, Ид_Тип, Ид_Значение + 2 таблицы (таблица типов и таблица значений)
            При выборках начиная уже от десятков тысяч записей JSON поля сливают по полной, т.к. постоянно динамически парсится, а в таблицах уже все связано, проиндексировано и дергается по ключам.
            При возрастании кол-ва данных, разница в скорости выборки начинает изменятся геометрически.


            1. norguhtar
              31.05.2019 13:16
              +1

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


            1. lair
              31.05.2019 13:17

              Просто используйте JSON-поля по назначению, и будет у вас все хорошо. А не по назначению не используйте.


              1. InChaos
                31.05.2019 14:14

                Полностью соглашусь. Все надо использовать к месту. Но это вечная проблема разработчиков — «О есть новая фишка, теперь не надо думать как, а просто ее использовать», на тестах в 10 записях все гуд, а потом в продакшене при росте базы имеем тормоза, и никакой ADB это не поправит.


                1. lair
                  31.05.2019 14:16
                  +1

                  Но это вечная проблема разработчиков

                  С этим надо бороться образованием, смена СУБД вам не поможет.


      1. Tzimie
        31.05.2019 08:08
        +2

        Ох уж мне эта пресловутая "реляционная алгебра". Так можно сказать что язык C построен на четкой Булевой алгебре, ведь в самом низу — двоичные биты!


        В общем, утверждение как бы абсолютно правильное и абсолютно бесполезное. Мы на воздушном шаре!


        1. VlK
          31.05.2019 09:25

          Все немного хуже даже. Sql вдохновлялся реляционной моделью и алгеброй. А своя трактовка там так себе...


        1. musicriffstudio
          31.05.2019 19:23
          +1

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


          Разработчики скл-серверов реализуют и оптимизируют это в ораклах с постгресами.


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


          Все просто.


      1. VlK
        31.05.2019 09:21

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


        Но поезд ушёл. :-)


    1. eduard93
      31.05.2019 14:42
      +1

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

      Тысяча это скорее минимум.


      Есть ещё такая интересная особенность: таблиц может быть даже немного — та же тысяча. Но конечные запросы пишутся к вьюхам, причем часто многоуровневым вьюхам. Это существенно повышает сложность анализа базы данных.


    1. lair
      31.05.2019 15:05
      +1

      Я вот взял открытую в соседнем окне БД ERP-системы (сложной, да), там больше 1300 таблиц, это без дополнительных пакетов и с учетом того, что простейшие расширения делаются через EAV.


  1. McKinseyBA
    30.05.2019 22:09
    +1

    deniskin, комментарий выше сподвиг узнать о бэкенде Хабра. Недавно была крутая статья о фронте, а про бэк не нашел ничего в блоге ТМ среди публикаций 2019. Возможно раньше? Можете ссылку дать на статью, а если ничего свежего нет, то вдруг и написать…


    1. Exosphere
      30.05.2019 23:30
      +1

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


  1. lair
    30.05.2019 23:22
    +1

    Совершенно отдельно, кстати, интересно, как все написанное в статье соотносится с уже существующими мультимодельными БД (Orient, Azure Cosmos, AWS Neptune).


  1. Mikluho
    31.05.2019 08:03

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

    Это мне напомнило опыт из 2000-го, когда у нас было в БД (MS SQL) объектное хранилище, а для оптимизации хранения и доступа некоторые сущности вытаскивались в табличное хранение, но так как запросы к данным выполнялись через апп-сервер, для конечного потребителя ничего не менялось в запросе.
    В объектном хранилище — гибкость (динамический список атрибутов, связи так же в атрибутах), но медленный доступ.
    В табличном хранилище — быстрый доступ, но сложнее менять атрибутный состав сущности.
    А следующий этап развития апп-сервера — на основании определённых метрик принимать решение о необходимости переноса сущности из объектного в табличное хранилище и автоматическое изменение атрибутного состава (да, апп-сервер мог модифицировать структуру БД).


  1. InChaos
    31.05.2019 13:00

    Не буду комментировать построчно, жаль своего времени, но на 50% вся статья просто бред. Остальные 50% можно поделить как 10% — что то в этом есть и 40% — натянуть сову.
    Автор чистый теоретик (причем с некоторой долей теоретик-сказочник) в СУБД и рассуждает с примерно такой позиции: — Фотография не есть отражение реальности. В реальности я вижу глазами отражение фотона от лепестка цветка, а на фото от простой краски на бумаге, но она не является лепестком, а значит это все обман, и следовательно все фото — фейки.


  1. rk938
    31.05.2019 16:33
    +3

    Решил даже зарегистрироваться, чтобы ответить.
    Вот этот пример таблицы прекрасно показывает почему реляционные базы данных более удобны:
    1) табличное (или хотя бы объектное) представление данных проще для человека и его легче отобразить,
    циклы в графах (14-15-16) довольно сложны для восприятия.
    2) поскольку случайный доступ очень медленный (особенно на HDD), в данной ситуации с графами приходится
    задавать схему (отношение tag->data в данном графе). Без этого full-scan запрос вместо одной таблицы будет
    обходить вообще всю базу.
    3) конкретно этот пример прекрасно представляется в ввиде таблиц при необходимости:
    — метаданные выносятся в на уровень приложения (в какой-нибудь json), их в любом случае нужно очень аггресивно
    кэшировать
    — для каждого тега создается отдельная таблица с данными из data
    4) единный уникальный ключ для всех типов данных: нужна блокировка всего кластера при master-master репликации.
    5) если считать поле атомарным объектом, то очень сложно сделать транзакционную блокировку записи, т.к.
    она представляет собой множество независимых элементов, а не просто указатель на место в файле таблицы.


    1. rk938
      31.05.2019 21:16
      +1

      Поскольку автор отвечает через страницу на своем сайте, отвечу тут.


      М-м-м… И где "таблица"? :)

      Немного промахнулся, имел ввиду данный пример:


      Пример

      8|tag|6|STRING|STRING|STRING|STRING|BYTE
      9|data|8|Россия|Курск|Лсная|5|NULL
      10|class|11|Страна|NULL|Города
      11|type|12|TEXT|SET/IDN|
      12|tag|10|STRING|ARRAY/DW/BYTE
      13|data|12|Россия|3 / 17 / 18 / 19
      14|class|15|Город|NULL|Страна|Улицы
      15|type|16|TEXT|IDN|SET / IDN
      16|tag|14|STRING|DW|NULL
      17|data|16|Курск|13
      18|data|16|Тверь|13
      19|data|16|Новгород|13
      20|class|21|Адрес|Страна|Город|Улица|Дом|Квартира
      21|logic|22|0|1|2|3|4
      22|ptrn|23|3 / 2 / 2 / 1|3 / 2 / 1|3 / 1|1|2
      23|type|24|TEXT|TEXT|TEXT|INT|INT
      24|tag|20|WORD|BYTE|DW
      25|data|24|5|NULL|27
      26|tag|0|STRING|DW
      27|data|26|Лесная|17


      1. rk938
        31.05.2019 23:47

        Нет, нужно ОБЪЕДИНИТЬ графовый и реляционный подходы!

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


        И эта штуковина УЖ ТОЧНО никак не "ложится в документоориентированные базы данных"! :)

        Та же mongodb поддерживает разное количество и тип полей в документах одной коллекции, т.е.
        данный пример прекрасно сохраняется как есть, т.к. там вообще нет схемы.
        Основная проблема при попытке переложить граф на таблицы и документы в том что каждая связь
        объекта с другими добавляет как минимум одно дополнительное чтение с диска.
        С join в реляционных бд тоже самое, но поскольку данные как правило сильно структурированны,
        количество join будет сильно меньше.


        Что за "графы (14-15-16)", что за "цикл из моего примера" — я так и не понял. :)

        Имелся ввиду цикл между элементами 14, 15, 16 в Вашем примере:
        class(14) -> type(15)
        type(15) -> tag(16)
        tag(16) -> class(14)
        Если убрать type(15), то будет class(14)->tag(16)->class(14), т.е. class определяется через tag
        который определяется через class. Такой цикл сложно отображать и работать с ним.


        Ох, как Вы ошибаетесь! Буквально в каждой фразе! Классификации-то иерархические, но как же они жутко повязаны в многомерный граф! И он нужен ВСЕГДА! А вот дерево несчастное — лишь иногда. :)

        Как показывает практика 90% структурированных данных прекрасно ложится в таблицы, при этом все чтения и выборки (без join) остаются линейными.
        Деревья через тот же nested sets тоже выбираются линейно.
        Многомерный граф с циклами (вот даже на пример 14-15-16) уже сложно понять и представить, чем больше элементов в цикле, тем сложнее.


        Здесь Вы ошибаетесь ещё больше, но это долго объяснять. :)

        В случае с графами можно сделать относительно быстрый поиск группы элементов для некоторых случаев, условно
        select * from streets where name="лесная"
        сначала найдет строку "лесная", а уже потом все связанные записи, но вот в случае если нужна обработка данных,
        уже будет обход всех элементов как минимум этого типа.
        т.е. select x1^3+x2^2+x3 from some_numbers будет обходить весь граф, если не хранить их рядом.
        Но т.к. схема не обязательна (а значит будет множество не структурированных элементов), это довольно сложно осуществимо.
        Это частично решаемо индексами (но Вы против них в заметке).


        Графу по барабану. И дело не в "оверхеде", а что делать с этими таблицами будете?

        Тоже самое что и с графом. Выбирать нужные элементы после фильтрации, подключать связанные
        элементы через join, несколько запросов к серверу или map reduce.


        Ещё точнее — его вообще нет физически. СОВСЕМ нет! :)

        Допустим это просто указатель на место в файле/блочном устройстве, в любом случае он будет указан внутри
        всех IDN, поэтому при наличии более одного сервера нужно все это синхронизировать.
        И как-то синхронизировать операцию "реструктуризации", которая явно не тривиальна.


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

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


        А ну-ка, давайте удалим элемент ГРАФОВОГО типа! :)

        И получим дырку в файле, которую можно закрыть только элементом с полностью такой же схемой (а их может быть мало).
        Если полностью отказаться от схемы (object_id|field_name|type|value), то увеличатся затраты на хранение указателей для каждого поля, плюс потеряется линейность чтения (одно поле в начале файла, другое поле в конце).


        Можно как-то динамически реструктурировать базу под популярные запросы, но это сложно и сильно повышается цена поддержки
        бд, возрастает количество ошибок.


        опять же, благодаря прямому доступу к данным, получается экстремально быстрое чтение конкретных полей, НЕЗАВИСИМО от количества элементов в базе.

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


        Это будет работать на NVMe дисках (даже не SSD) или в памяти, где операции с random access
        сравнительно близки по скорости к операции линейного чтения.
        Но даже для памяти это не совсем так, при линейном чтении (особенно в колоночных бд) например можно использовать векторные инструкции, которые в несколько раз быстрее.
        Плюс, если данные сильно разбросаны по диску, будет прочитано много данных которые вообще не используются, в случае с диском это вроде порядка 4KB (размер страницы), при том что поле может быть всего 4 байта.


        1. lair
          01.06.2019 02:35
          +1

          select * from streets where name="лесная"

          Я вот, если честно, совершенно не понимаю, как в предлагаемой автором физической схеме сделать такой запрос без полного перебора (особенно если речь идет не о точном совпадении, а о «начинается с», типичный кейс для выпадающих списков).


          1. rk938
            01.06.2019 14:04
            +1

            При наличии индекса (например binary tree) префиксный поиск очень быстрый (просто находим нужные ветки и выбираем всех детей), вот для постфиксного (заканчивается на) скорее всего придется делать full scan, если изначально не затачивать структуру индекса под это.
            Но всегда есть выбор по маске (?есн?), где индексы не помогут и останется только full scan.


            1. lair
              01.06.2019 14:07
              +2

              При наличии индекса (например binary tree)

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


              1. rk938
                01.06.2019 16:06
                +1

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


                1. lair
                  01.06.2019 21:26
                  +1

                  Ну во-первых, что не сложнее — это надо подумать. Равно как и проблем с консистентностью не будет, если хорошо подумать, а не просто "взял и добавил".


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


                  Про реализацию всех клевых идей-то кто будет думать?


                  Либо у автора есть какое-то решение без индексов (что я собственно и пытаюсь понять).

                  Как можно видеть по цитируемым вами репликам, автор вообще не в курсе того, что такое индексы в СУБД, и зачем они нужны.


        1. rk938
          01.06.2019 16:03
          +1

          Нужно ведь объединить графовый и реляционный подходы в рамках ОДНОЙ модели! ОДНОЙ СУБД!

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


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


          Существующие подходы к графовым бд не дают этого. Как это предлагается решать, при сохранении преимуществ
          реляционных бд, я и пытаюсь понять.
          Без этого заметку можно свести "RAM лучше HDD, потому что поддерживает random access". Толку-то, если оно
          дороже и имеет меньшую емкость?


          Про ограничения реляционных бд понятно всем кто с ними работал, но как правило эти ограничения можно так или
          иначе обойти в конкретных случаях, не теряя в производительности для остальных.
          Например:
          1) упорядоченные списки, как простой пример "меню сайта", где нужно менять порядок полей, решается через дополнительное
          поле order (которое довольно сложно менять консистентно).
          2) деревья, реализуются довольно быстро через те же nested sets.


          нет смысла плодить эти таблицы сотнями и тысячами — она ОДНА!

          И будет работать со скоростью одной таблицы? Или все же сохранится скорость реляционной бд при многих таблицах?
          В целом, я не вижу особых отличий таблицы от "tag" в Вашей схеме, от того что вместо тысячи таблиц будет тысяча
          tag и одна таблица с точки зрения логики и операций над данными ничего особо не изменится, а вот сохранится ли скорость
          уже другой вопрос.


          Там-то, может, и нет, но у меня-то есть! :)

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


          Какая разница, что она там "поддерживает — у неё ЕСТЬ прямой доступ к элементу или его НЕТ?

          Элемент это поле или строка? И что есть прямой доступ? Возможность чтения по указателю, вместо ключа?
          В целом:
          1) в табличных базах легко организовать чтение по указателю даже поля, при этом достаточно знать схему
          таблицы и указатель элемента. Указатель элемента получается из ключа.
          2) в mongodb (ну и вообще в документоориентированных базах данных), указатель документа так же вытаскивается
          из индекса по ключу, дальше обход документа (он не большой, поэтому это относительно быстро).


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


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


          Если верить Вики, она базируется всё на том же поганом JSON

          JSON там используется только для пользовательского интерфейса, формат хранения другой. В плане чтения/понимания
          человеком, JSON довольно хороший.


          Ядра-то у неё НЕТ! Или есть? :)

          Что есть ядро?


          Я реально моделировал работу БД, в которой ни у одного элемента не было менее четырёх связей с другими, а некоторые узлы имели МИЛЛИОНЫ связей на элемент! Кто Вам сказал эту ересь?

          И сколько чтений будет для выбора одной конкретной связи у элемента с миллоном связей?


          И при чём тут вообще join и реляция?

          Join это всегда как минимум одно дополнительное чтение.


          И какая разница, насколько сильно структурированы данные?

          Большая. Простой пример:
          1) Таблица [Имя, Фамилия] состоящая из одной записи [Иван, Иванов].
          Для поиска элемента с именем "Иван" и фамилией "Иванов" нужно сделать ровно одно чтение.
          2) Три таблицы: [Имя_id, Фамилия_id], [Имя_id, Имя], [Фамилия_id, Фамилия].
          Для поиска нужно сделать три чтения!


          Я просто для наглядности метаданные каждого уровня доступа к БД разнёс по отдельным узлам

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


          Ха-ха-ха! Да что же там может "показывать практика", если ДАЖЕ ПОПЫТОК поработать с РЕАЛЬНО сложными данными ешё не предпринималось!

          Там где нужны именно графы они уже давно используются. Если считать граф сложными данными, а таблицу простыми, то 90% данных простые.


          Я же говорил уже: попробуйте тот граф, который получился для схемы городского транспорта Москвы уложить в этот несчастный JSON — хотя бы на уровне постановки задачи!

          Зачем пытаться запихать круглое в квадратное? JSON это иерархическая структура данных, понятно что туда граф будет довольно сложно запихать.


          Заметка посвящена ТОЛЬКО КОНЦЕПЦИИ! Хватит играть в реляционные погремушки, граф и таблица есть одно и то же! Вот она, концепция.

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


          а) графу пофиг, что там "хранится рядом", а что нет — у него прямой досту к данным по ID

          Графу может быть. А вот чтение [Имя, фамилия] в случае если "Имя" является указателем на начало
          файла, а "Фамилия" указателем на конец файла будет намного медленее, чем если бы они находились рядом.


          б) схема не обязательна, но и не запрещается и вообще может быть гибкой и даже отдана на откуп СУБД

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


          г) Да, я против индексов, но если Вам удобно оперировать этим понятием, можете считать, что они есть всегда, что они вообще встроенные.

          Вот это кстати очень важный момент. Если индексов нет, по я предполагаю что одинаковые данные одинакового типа хранятся
          рядом, это так?
          Т.е. условно Улица(название: Лесная) и Человек(фамилия: Лесная) указывают на один и тот же блок данных (строку)?
          Если нет, то хранятся ли данные одного тега всегда рядом?


          То есть Вы в запросах должны ЗНАТЬ структуру БД, состав этих самых таблиц? Графу тоже пофиг, да и вообще не юзеровское это собачье дело! :)

          Даже в графе нужно знать как минимум тип узла (tag/class в Вашей схеме), и название нужных полей. Без этого можно получить человека вместо улицы,
          например.


          А ЧТО ИМЕННО Вы собрались "синхронизировать", когда и зачем?

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


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

          Т.е. конкретный узел графа всегда будет только на одном сервере? И будет модифицироваться только на нем?
          Это хорошее решение для конкретной ситуации, но далеко не универсальное.
          1) Атомарная модификация двух узлов (пользователь A перевел пользователю B денег) все равно будет требовать блокировки, если
          узлы пользователей находятся на разных серверах.
          2) К конкретному узлу может придти огромное количество запросов, которое один сервер просто не выдержит, поэтому
          часто приходится держать один узел на нескольких серверах. Как в этом случае будет работать атомарное изменение без блокировки?


          А вот фигушки Вы угадали! :) Во-первых, если мы удалим элемент ГРАФОВОГО типа, то получим НЕСКОЛЬКО дырок (хотя, не исключено, что всё-таки одну).

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


          Во-вторых, никаких дырок мы вообще не получим, и ничего там "закрывать только элементом с полностью такой же схемой" не требуется.
          Вспомните: любой элемент может вообще поменять свою схему в любой момент, да ещё и прозрачно для юзеров!

          При смены схемы, например string(10bytes) на string(200bytes) точно так же будет появлятся дырка.
          Есть файл, в нем [<данные>,string(10bytes),<данные>]. Если мы переносим или удаляем эти 10 байт, то в файле получается
          10 пустых байт, которые можно использовать только другими 10 байтами, или N элементов у которых суммарный размер 10 байт.
          Более того, эти 200 байт скорее всего будут записаны в конец файла (или в любое свободное место размером 200 байт), что
          с большой вероятностью далеко от предыдущего расположения.


          Если записать в середину файла вместо 10 байт 200 байт, то файл будет фрагментирован и мы просто перемещаем логику на уровень файловой системы.
          Фиксированная схема позволяет избежать этой фрагментации и гарантировать что большая часть элементов расположена рядом.


          и это не так уж сложно, и никакая "цена поддержки" сильно не "повышается". А уж про ошибки уж чья бы корова мычала, а реляция молчала! :)

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


          Так в чём проблемы? Смотрите для групповой обработки на граф именно на реляцию!

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


          И с какой радости у Вас появилось "множество элементов ОДИНАКОВОЙ структуры"?

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


          Только потому, что этот хромоногий SQL должен получить свой select from table ABC where?
          А как насчёт select from ALL tables?

          Т.е. каждый запрос select from table будет работать со скоростью select from all_tables?
          В "количество таблиц" раз медленее?
          Конкретнее, будет ли


          select from all_tables where class="улица" and улица.name="лесная"

          работать со скоростью


          select from streets where name="лесная"
          ?

          > И забудьте Вы про «физику», про все эти диски — проблема концептуальная, проблема алгоритмическая!

          Если не учитывать ограничения «физики» в алгоритмах, то да, графовая бд может работать со скоростью реляционной,
          вообще без особых изменений. Только толку-то, если она должна работать на реальном железе, а не на бумаге.


          1. rk938
            01.06.2019 16:40
            +1

            Ну как, конвертнём его в JSON или куда-нить в какую-нить БД? Просто чтобы увидели ЧТО ТАКОЕ сильно перевязанный граф и попробовали его уложить в эту поганую реляцию.

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


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


            Ещё проще: имеем уже подготовленный список айдишек и выдаём результат, без всякого дерева — что для префиксного поиска, что для постфиксного, что даже для поиска по маске.
            ЛЮБОЙ популярный запрос может быть проиндексирован, если есть желание (точнее, если возникнут раздражающие тормоза для большой группы юзеров).
            Правда, перидётся поддерживать все эти индексы в актуальном состоянии, так что это имеет смысл разве что для СУПЕРпопулярных запросов.

            Такой же подход используется в CouchDB, вместо индексов просто задаются view, которые динамически обновляются по мере поступления данных, т.е.
            для каждого запроса появлся очень специализированный индекс.
            Этот подход работает если запросы в целом одинаковые (а в большинстве приложений это так). Но мы не избавились от full-scan, просто
            перенесли его на уровень "создания индекса".
            Например, в новой версии приложения добавился новый вид запросов, которых не было раньше, нужно проиндексировать всю бд, чтобы создать индекс,
            а бд огромная и это займет очень много времени (даже в случае реляционных бд это может быть несколько суток).


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


            Почему же? Даже если нет индекса, практически всегда есть куча долполнительной информации, которая ограничяивает пространство поиска.
            Например, в данном случае (есн) можно смело выбрасывать из рассмотрения нетекстовые узлы, тексты на английском, китайском, персидском… так что даже full scan обычно не очень-то и full. :)

            Проблема в том что, чтобы отбросить узел без индекса, нужно его сначала прочитать и узнать его тип.


      1. rk938
        01.06.2019 17:13
        +1

        Давайте о терминах договоримся.
        Если индекс — это что-то, что позволяет получипть прямой доступ к элементу БД, то он нафиг не нужен: айдишка и есть индекс.
        Если это средство не проводить поиск по БД, а использовать результат аналогичного поиска, проведённого ранее, то можно просто запомнить результат в базе и при следующих поисковых запросах просто отдавать этот готовый результат.
        Другое дело, что с изменением БД результат этот устаревает, а потому эту хрень нужно поддердивать в актуальном состоянии.
        Любой индекс дает прямой доступ к элементу бд И использует результат поиска проведенного ранее.
        Если мне нужен очень быстрый ответ на запрос конкретного формата, я либо добавлю индекс (в бд где они поддерживаются), либо
        просто пошлю миллион одинаковых запросов (если индексы строятся динамически), чтобы прогреть кэш и запрос от реального пользователя
        не завис на full-scan.


    1. rk938
      01.06.2019 20:08
      +1

      Да что Вы говорите?! И что за "решение"? Что, теперь по ссылочному ключу можно доступ к элементу получить? Это же революция в РБД! Это же навигационные выражения в запросах! Это же никаких рекурсивных SQL-запросов! Так что за "решение"? :)

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


      Да кто бы спорил! То-то в БД OSM одних только Южных полюсов 50 штук! Разве это "особая разница"? Фигня какая — подумаешь, 49 лишних! :) Только юзеры почему-то недовольны: говорят, в этот районе 12 банкоматов, а эта падла показывает только 6!

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


      А зачем, сэр? Данные-то зачем дублировать?

      Потому что сервер обязательно сломается и в большинстве случаев не хотелось бы потерять эти данные.


      :lol: Откуда у РБД скорость-то? Я в книге так и писал: "Говорить о скорости доступа к данным при концепции поиска по ключу – насмешка над здравым смыслом".

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


      А что такое "графовые запросы"? Термин явно требует согласования.

      Я бы предложил примерно такое определение: "запрос связей элемента без конкретизации".
      Т.е. например "выбрать все города которые связаны с пользователем A", но не "все пользователи у которых город рождения == москва".
      Т.к. город рождения легко отображается через поле таблицы.


      Я же сказал, как! Если надо — смотреть на данные, как на граф, если надо — как на реляцию!

      А хранить-то как? Плюс, реляционная бд накладывая ограничения на данные так же ограничивает


      Да на кой они вообще нужны, деревья-то?

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


      О! Именно! Только вот "логика и операции над данными ещё как изменятся! Например, можно спокойно компоновать в единые блоки РАЗНОРОДНЫЕ элементы!

      При этом скорость выборки блоков с разнородными элементами будет медленее выборки блоков с однородными элементами как минимум при первом запросе.


      А что за "проблема не структурированных данных"? Синдбад может работать вообще с данными неизвестной структуры. :)

      Под структурированными данными я имел ввиду однородность и отсутствие внешних связей, но действительно, не совсем верный термин.


      В Синдбаде оно ВСЕГДА "организовано", и не требует знания схемы (которая, к тому же, может многократно изменяться во время жизни БД).

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


      Да кто же спорит! Либо мгновенный доступ к элементу, либо поиск — какая разница? :) Впрочем, в Синдбаде ключ и указатель — это вообще одно и то же. И файловая система к этому не имеет ни малейшего отношения.

      Поиск по бинарному дереву конкретного смещения нужного ключа? А как без него?
      Я вижу три варианта:
      1) Не сохраняем линейность файла и при изменении структуры (добавилось поле), пишем по конкретному смещению вместо 10 байт 11,
      пересчитывая все указатели которые выше текущего. Файл фрагментируется и тот же самый поиск будет на уровне файловой системы.
      2) При удалении элемента оставляем дырку в файле, на месте указателя. При большом количестве удалений база будет постоянно расти,
      даже если реальное количество данных не изменится.
      3) При удалении элемента обходим все элементы которые указывают на текущий и удаляем указатель (что может быть довольно много).
      При этом указатель становится снова свободен, но в него можно записать только данные с той же схемой. Т.к. субд сама выбирает схему
      данных и нет ограничений на пользователя, то вполне возможна ситуация когда не будет нового элемента который можно записать по данному
      указателю.


      Ядро СУБД. Которое может быть либо графовым, либо реляционным, либо, как я предлагаю, и тем, и другим. :)

      А может быть СУБД без ядра? Но mongodb документоориентированная, тем нет реляционной модели.


      Чтений ЧЕГО? Что такое "выбор одной конкретной связи"? Обращение к тому элементу? Что-то ещё?

      Чтений с диска при выборе одной связи у элемента с миллионом связей. Например:
      "все города у которых есть связь с пользователем A".
      При этом у одного конкретного города миллион связей (и нужно будет обойти их все).


      Ну, и в каком же случае данные структурированы? :)

      Вариант с [Имя, Фамилия] будет обрабатываться быстрее. Согласен, что определение не совсем верно.


      В любом случае, для поиска нужно делать МНОГО чтений — не рассматривать же всерьёз БД из одного элемента!

      Проблема в том что в данном случае есть вероятность что 1 и 3 превратятся в N и 3N, что при большом количестве
      данных будет ощутимо дольше.


      Да где же тут "цикл"? Они просто ДОСТУПНЫ как единое целое при ссылке на ЛЮБОЙ из этих узлов! Как если бы они сидели дружной кучкой в одном узле — только и всего!

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


      Ну так вперёд! КАК мне схему транспорта Москвы представить хотя бы в JSON?

      А кто, где и когда утверждал что JSON это графовый формат данных?
      Даже станции метро имеют N ссылок на соседние (до которых есть ветка). Если есть конкретные запросы которые не требуют графового
      представления (мы согласны потерять ссылки на соседние станции), то можно сделать какое-то древовидное или табличное представление,
      в частном случае будет граф.


      Ну, а делать-то ЧТО? Как это вогнать в базу данных — пусть даже не реляцуионную, а самую наикрутейшую?

      Взять любую графовую бд, например Neo4j или что-то похожее и запихать именно как граф любой связанности?


      Ежу понятно, что "таблица это частный случай графа". Даже не просто графа, а двухуровневого дерева. А что же делать СО СЛОЖНЫМИ данными прикажете?

      Использовать именно графовые бд, если данные это общий случай графа?


      Ну да. Реляция и граф в одном флаконе. То есть разрешение Великого Спора к обоюдному удовольствию. :)

      Ну вот пока не совсем очевидно как сохранить скорость именно для структурированных данных.


      Но, прочтите, проход по построенным индексам РБД тоже ведь, как Вы говорите, будет "намного медленнее", и точно по той же причине. :)

      Индекс:
      1) Меньше всей таблицы
      2) Как правило обеспечивает быстроее выполнение каких-то конкретных запросов.
      Постфиксный поиск по бинарному дереву заточенному под префиксный поиск это full-scan, и он будет медлненее чем full scan всей таблицы.
      Реляционная бд в случае если не возможно быстро получить данные из индекса, просто не будет его использовать.


      А какое дело скорости запросов до схемы? Что до "реструктуризации БД" — это отдельная песня! Это штука непрозрачная!

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


      РБД, насмколько я помню, вообще реструктурировать невозможно?

      Можно добавить индексы, добавить/удалить/изменить поля, что еще нужно?


      Даже в графе нужно знать как минимум тип узла (tag/class в Вашей схеме), и название нужных полей. Без этого можно получить человека вместо улицы,


      Абсолютно не обязательно! Более того: если структура БД отдана на откуп СУБД, это вообще невозможно узнать! Ну, если только СУБД расскажет.
      Как не обязательно? Вот я хочу получить все улицы на которых более 10 домов, пишу запрос:
      select from graph where class="улица" and relation(class="дом")>10
      Как сделать запрос не зная тип узла (улица/дом) и то что улица связанна с домом?

      Ну, дайте одному серверу половину данных, а второму — другую половину и забудьте о синхронизации! :)
      Т.е. конкретный узел графа всегда будет только на одном сервере? И будет модифицироваться только на нем?

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


      Блокировки-то здесь зачем? Схема ведь похожа на работу протокола TCP: послал, получил квитанцию, закрыл проводку. Нет? :)
      Я всегда смеялся над этим способом взлома банков. Проблема-то решается элементарно: "В очередь, суки, в очередь"! И вообще, какое дело СУБД до алгоритмов работы каких-то ситстем, на ней базирующихся? Хотят блокировать? Да пусть блокируют! Хотят дублировать? Да пусть дублируют! Это ведь ИХ проблемы!

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


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

      А куда делись? Данные не удаляются с диска вообще?


      Дырка будет появляться, простите, ГДЕ? Мы уж лучше как-нить без дырок будем работать. :)

      В файле/блочном устройстве, где субд хранит данные.


      Забудьте как страшный сон! :) Я потому и говорю, что в работу ядра СУБД нельзя лезть своими грязными лапами. Доступ разрешён только к логическому уровню, который вообще НИКАК не зависит от организации данных на физических носителях. СУБД САМА разберётся, куда и как "эти 200 байт будут записаны". :)
      Вообще-то, с большой вероятностью на то же самое место, но, быть может, и далеко оттуда. Забудьте. Считайте, что вся эта хрень с "дефрагментацией" инкапсулирована в ядре СУБД, не мешайте модель данных с "физикой" процесса.

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


      Да на кой Вам это надо? КАКИЕ элементы будете рядом располагать? Близкие по алфавиту? По дате занесения? По структуре данных? По их тематике? Кончайте заниматься фигнёй! Ещё цитата из книги:
      Таким образом, идеальная СУБД не только не требует от пользователей знания схемы данных, но сама должна выбирать наиболее оптимальную схему их хранения и поддерживать её в актуальном состоянии. В конце концов, именно СУБД занимается обработкой данных, и ей лучше знать, какова должна быть их структура. Кстати, сама возможность реструктуризации БД автоматически уменьшает требования к качеству определения схемы базы данных при проектировании – наиболее сложной и трудоёмкой операции при работе с базами данных – практически до нуля.

      Те элементы, которые наиболее часто обрабатываются вместе.
      Если изменится структура запросов, я просто поменяю схему. В "идеальной субд" я могу только надеятся что она выберет оптимальную схему, но всегда остается
      риск что это будет не так, и что делать в этом случае? Править исходники (если они доступны) или лезть дебаггером в базу данных под нагрузкой?
      Стоимость поддержки схемы руками довольно минимальна по трудозатратам по сравнению со случаем если "идеальная субд" выберет не оптимальную схему.


    1. rk938
      01.06.2019 20:30
      +1

      Странное следствие… :)

      Стоимость поддержки операционной системы намного выше стоимости поддержки калькулятора. Чем больше логики и кода
      в конкретной системе, тем больше ошибок и сложнее добавить новую логику.


      … сложность обрабатываемых данных тут же ограничивается форматом табличного представления. Оно нам надо? :)

      А простые данные обрабатывать не надо?


      Или даже быстрее. :)

      Дак вопрос в том что select from table всегда должен работать быстрее чем select from all_tables.


      На реальном железе она ТОЖЕ будет работать с прямым доступом к любому элементу данных, а не ковыряться в первичных ключах.

      Линейность доступа не менее важна чем прямой доступ к элементу. Заменяя первичные ключи на прямой доступ мы получаем оверхед
      при удалении данных.


      Мы как раз избавились от full-scan! Один раз разбить тексты по языкам (или там по ключевым словам) — и пользуйся "ещё много-много раз"!

      А вот и не избавились. При первом запросе (когда данные еще не разбиты) будет full scan. И теперь при каждой вставке нового
      текста у нас будет снова это разбиение. Это работает только на бд где много чтений и мало изменений.


      Зачем? Выполнил один раз запрос от пользователя и просто сохранил результаты! Вот и вся "индексация".

      А запрос (посколько индексов для этого конкретного запроса нет и раньше не было похожих) займет двое суток. Чем это лучше создание индекса?
      При этом т.к. субд "умная", она может удалить этот индекс, или решить что раз во время запроса пользователь отключился из-за проблемы
      со связью, то достраивать его не нужно.


      Не обязательно. Вон, в примере таблицы у "России" есть готовый список городов — так зачем нам "узнавать из тип"? А о более позднем примере написано так: Важный нюанс состоит в том, что сотрудник {46} имеет два договора {46.3}, а один из этих договоров {51} имеет сразу три исполнителя (т.е. реализовано отношение «многие-ко-многим»), и даже разных классов {51.2}: одна Компания, и двое Сотрудников. И там, и там в списке по три айдишки, и совершенно наплевать, какие там у них типы.

      Да, пропустил что там сохраняется связь. Предположим из таблице в примере нам нужно выбрать все элементы типа class у которых второе поле равно "Город".


    1. rk938
      02.06.2019 00:06
      +1

      А у меня ID ЛЮБОГО элемента И ЕСТЬ индекс! Он же ключ. И не надо никого никуда "посылать". :)

      Т.е. у поля String("Лесная") всегда есть свой индекс, для получения указателя из строки?


      Как Вы ключи в ссылки переводить собираетесь? Как тот самый граф, который "схема трансорта Москвы" в реляцию запихивать будете?

      Данные и иерархия (Ветка->станция метро) в реляционной бд, какие-то связи (например соседние станции метро) в графе.
      Зачем переводить ключи в ссылки? графовая бд просто даст дополнительные отношения вида <left_id, right_id, rel_type>.


      Ну так и работаем с графами общего вида — все "частные случаи" вольются туда автоматом!

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


      Это задача так называемого "уровня хранения", который вообще не знает, что такое "структура" и что такое "поле".
      Зато он знает, что такое "куча" и как с ней работать, знает, когда можно "писать по конкретному смещению вместо 10 байт 11", а когда нет, как удалять элементы, чтобы даже "при большом количестве удалений" база не росла и не "обходить все элементы которые указывают на текущий и не удалять там указатели".

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


      Так они ведь УЖЕ СЧИТАНЫ! Что ещё читать-то?

      Кем и когда? Это первый запрос, индексов нет.


      С какой радости? Загляните в любой телефонный справочник и посмотрите, чего там больше: имён, фамилий или их комбинаций?

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


      Да неужели? Ну, попробуйте запихать тут самую транспортную систему Москвы. ХОТЯ БЫ В ОДНУ бд из этих "любых". :)

      А в чем проблема? Это графовые бд, они специально для этого созданы. Я не готов сейчас парсить кучу htm страниц.


      НУ ОТКУДА Вы можете знать что-то о возможных запросах? СУБД — может, на основе сбора статистики, а Вы-то откуда? Тем более, что схему Вы задаёте ещё ДО создания БД!

      Потому что все запросы пишу я и конечный пользователь вообще не имеет прямого доступа к субд, кроме как интерфейс приложения?


      Да откуда Вы знаете, что улица — это именно класс, а не атрибут или даже значение?
      А даже если знаете, кто может гарантировать, что СУБД три часа назад не поменяла реляционный тип адреса (который Вы "знаете") на графовый?

      И каким образом тогда отличать улицу "Лесная" от человека с фамилией "Лесная"?


      Или что в базе есть ОБА этих класса или ещё какие-то (например, просто строка)?
      В БД OSM, например, СОВЕРШЕННО ТОЧНО присутствуют все три вида, да ещё и с вариациями!

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


      Ох, бедолага! Что же он со всей базой будет делдать, если даже с одним сраным узлом справиться не в состоянии? :)

      На конкретный узел приходит 100ГБит запросов, сетевая карта 10ГБит. Если не распределять узлы по разным серверам, эту
      ситуацию никак не обработать.


      СУБД должна обеспечивать эффективную работу пользователей! А это всё к пользователям не имеет никакого отношения.

      К пользователям не имеет отношения:
      1) то что бд перестанет работать в случае физической поломки одного сервера?
      2) возможность потратить больше денег чем есть на счету?
      3) отсутствие возможности работы на нескольких серверах?


      А зачем?

      Ох. Чтобы место на диске не закончилось?


      Об общей концепции. Знаете, как работает диспетчер памяти в операционке? Вот примерно так работает и уровень доступа. К модели данных это не имеет НИКАКОГО отношения!

      Постраничный доступ? Примерно так же работает файловая система. Если не учитывать структуру и тип данных, то потеряется линейность доступа.


      Что Вы собрались "просто и быстро решить в реляционной бд"?

      Отсутствие фрагментации данных и линейность чтения однородных данных.


      Решите вопрос прямого доступа к элементу и, соответственно, навигационных выражений в запросах. :) Я вот не вижу не только "простого", а вообще НИКАКОГО способа!

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


      Просто потому, что она информирована в 100500 раз лучше Вас.

      Кто ее информировал о моих намерениях и планируемых запросах? Она умеет в телепатию?


      Ха-ха-ха! И что же это за "элементы"? Ну, взять хотя бы карты OSM. Как группировать будем? По координатам? По типу элементов? По языкам? Как ВЫЯВЛЯТЬ будете эти элементы?

      Для OSM действительно лучше граф. Тот же телефоный справочник пихать в граф довольно мало смысла.


      ЧТО???!!! А конвертировать БД в новую схему Вы тоже будете руками? Кстати, а почему тогда именно проектирование схемы БД считается САМОЙ затратной частью разработки?

      Именно так. Как правило вообще параллельно запускается кластер из нескольких серверов и данные туда мигрируются, параллельно записывая новые в два места.


      А не тем легче будет выявить и исправить ошибки?

      Ошибка в данных или ошибки в коде? Я говорю про ошибки в коде.


      Простые данные тоже проблему представляют? Ну, хорошо: как будете В ПРОСТЫХ данных ошибки исправлять? В тех же телефонных справочниках? Мне вот кажется, ГРАФОВЫМИ методами! :)
      Для телефоного справочника из [телефон, имя, фамилия] какие же ошибки будут найдены "графовыми" методами?
      Все ошибки в телефоне решаются нормальной маской и валидацией. Имя/Фамилия (а нужно ли в них вообще искать ошибки?) при желании ищутся статистическими
      методами.

      Не знаю даже, как комментировать… АБСОЛЮТНО ВСЁ неверно! :)

      Линейность не важна? Если не удалять данные, то конечно оверхеда не будет, но это далеко не универсальный случай.


      С какого бодуна?! Добавил новую айдишку к старому списку — и все дела! А то и добавлять даже не надо! :)

      А разбивать строку на кейворды кто будет? Кто будет определять язык текста?


      Тем, что запросы пользователей СУБД ОБЯЗАНА выполнять, а заниматься всякой хернёй на всякий случай — нет.
      Может, этот индекс и не понадобится никогда! А эта тварь будет струячить по двое суток на каждую вдарившую в процессор мочу. :)

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


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

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


    1. rk938
      02.06.2019 20:50
      +1

      У поля, в принципе, тоже. По крайней мере, адресоваться можно и к полю. Только не "для получения указателя". Указатель-то кому и зачем нужен?

      Чтобы вытащить по этому указателю связанные объекты?


      Так в том-то и дело, что НЕТ там никакой "иерархии"! Точнее, там МНОЖЕСТВО иерархий!
      По виду транспортного средства, скажем — метро там или трамвай какой.
      По их маршрутам, по тем же станциям метро, по выходам из них, по автобусным остановкам, которые САМИ ПО СЕБЕ являются контейнерами
      маршрутов (пересадочными узлами), да ещё если в шаговой (10-20 метров) или в ближайшей (50-100 метров) доступности, по школам и магазинам,
      которые рядом с этими остановками стоят, по картам, на которых они расположены. Надо не "какие-то связи", а те самые, которые в графе!
      Как решать задачу будем? Каким инструментом? Вот они, СЛОЖНЫЕ данные, а не реляционные погремушки! Ну? ;)

      Так а в чем задача? Какие запросы? Что мы хотим получить из этих данных? Без этого, метод хранения "куча htm файлов в архиве"
      ничем не хуже бд.


      Ну зашибись! Как ДОСТУП К ЭЛЕМЕНТУ будете получать по этому говну? Рекурсивным SQL-запросом? ;)

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


      А если "графовая бд просто даст отношения", то какая же это, в жопу, "графовая бд"? Это лишь сраная реляционная эмуляция!

      А что еще нужно от графовой бд кроме отношений между узлами?


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

      Мы сейчас говорим про абсолютно разные вещи. Я ничего не говорил про линейность/экспоненциальность алгоритма.
      Я говорил про линейное и случайное чтение (random access). Граф (по крайней мере в той схеме, что была представлена как пример)
      не обходится линейно, там будут прыжки по указателям постоянно. А вот nested sets можно вывести именно линейно.


      :lol: Это почему же? Какое собачье дело линейному чтению до структуры?

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


      Но элемент-то СЧИТАН! Вот в текущем и сидят его связи, стопочкой!

      Т.е. элемент с миллионом связей считывается всегда со списком его связей?


      И когда же это не верно? А если даже и неверно, за каким хером тогда нужны эти две таблицы? Нормальная СУБД тут же оптимизирует структуру хранимых данных! :)

      Я привел конкретный пример когда внешние ключи увеличивают количество чтений.


      ЧАВО???!!! Юзер не может писать запросы к СУБД?! На кой тогда она ему усралась, говно такое? И при чём тут "прямой доступ" — это же ЗАПРОСЫ!

      Мы опять говорим про разные вещи похоже.
      Для меня СУБД это просто хранилище данных, все запросы пишет приложение, которое пишу я. В данном случае у бд только один пользователь — приложение.
      Конечный пользователь моего приложения не знает о том что там где-то есть какая-то бд и ему это вообще не важно.
      Что Вы имеете ввиду под бд?
      1) отдельный сервис хранения данных, запросы к которому делают приложения. конечный пользователь делает запросы только к приложению и
      даже не догадывается о существовании какой-то там бд.
      2) бд это конечное приложение, запросы к которому пишет человек.
      Это две совершенно разные вещи, и второй вариант это довольно малый процент субд, разве что какие-то аналитические системы, которых опять же довольно
      малый процент.


      Да тем же самым! По дополнительным сведениям, связанным с объектом! Откуда юзеру знать, что улица — это именно класс, а не атрибут или даже значение? Он же схему не составлял, он её не модифицировал, он её знать не знает! Ну, напишет он (или Вы) этот запрос про класс, а в БД данные лежат именно в значениях! В той самой таблице, скажем:

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


      О! Знали бы Вы, СКОЛЬКО подобных ошибок как раз в реляционных базах данных! Тысячи! Сотни тысяч! Миллионы! Ибо верификацией данных в БД вообще никто не занимается!

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


      Что за "узел" такой? Что за криворукая реализация?
      Тем более, что этот узел при большом количестве запросов, просто ОБЯЗАН постоянно торчать в кеше!
      Увольнять надо бригаду разработчиков такой БД! Всем стадом, не разбираясь в подробностях! :)

      Узел — атомарный элемент данных, который нельзя разбивать и нельзя модифицировать в нескольких местах одновременно.
      Если запихать его в кэш, то он будет на нескольких серверах одновременно, и схема "всегда обращаемся к конкретному серверу
      для операций над конкретным элементом" уже не будет работать.
      Если под кэшем вы имели ввиду какой-то кэш на том же самом сервере, то он никак не спасет, т.к. один сервер просто
      физически не может обработать весь поток запросов.
      И да, это реальный пример из практики. 30% нагрузки кластера из 500 серверов приходилось на один атомарный элемент.


      АБСОЛЮТНО! НИ МАЛЕЙШЕГО! Пользователям насрать, сколько там серверов и как часто они ломаются — им нужен простой и эффективный доступ к данным, и ничего более.

      Пользователям важно:
      1) чтобы данные никто не потерялись и не испортились (в том числе "умной" субд, которая нашла "ошибку" в данных)
      2) чтобы доступ к данным был быстрым (причем пользователь знает гораздо больше о приоритетах запросов, чем бд).
      реальный пример, один сложный запрос выполняется раз в месяц, но он должен выполнятся максимально быстро. "умная" субд просто снесет
      все индексы которые редко используются.
      3) доступность данных, если какой-то сервер сломался, данные должны быть доступны для обработки, вне зависимости от этого.


      А с какого хера оно должно закончиться, если мы данные УДАЛЯЕМ?

      Мы удаляем данные или нет? Ответ "А зачем?" я воспринимаю что как "не удаляем"


      Не совсем. Страницы-то ведь тоже могут потребоваться разного размера (для неоднородных данных).

      Ну, могу говорить примерно про linux, я не знаю всех подробностей реализации, но в целом оно работает примерно так:
      1) все страницы порядка 4КБ
      2) если приложение запрашивает 16KB, ему просто дадут 4 страницы по 4KB
      3) страницы при этом могут находится в разных регионах памяти, что приведет к фрагментации.
      5) если нужна нормальная производительность, в ядре дополнительно включаются и аллоцируются huge pages,
      хотя бы по несколько MB, в идеале GB.
      6) если мы удаляем данные из середины, мы можем их закрыть только элементом той же структуры.
      7) если не рассматривать случаи с linked list и другими медленными контейнерами, то элемент должен не только
      иметь ту же структуру, но и тот же смысл, чтобы его можно было обрабатывать вместе с окружающими элементами.


      И — повторяю — уровню хранения АБСОЛЮТНО насрать на структуру и тип данных, он умеет работать даже с данными НЕИЗВЕСТНЫХ типов НЕИЗВЕСТНОЙ структуры.

      Тогда он будет работать медленее, чем мог быть.


      Ой, ну утомили Вы своей "фрагментацией"! Давайте считать, что все данные всегда сидят в ОЗУ, чтобы этой хернёй с файловой системой не маяться.

      Ну, будет фрагментация в ОЗУ, будем прыгать по указателям вместо линейного чтения. Да, потеря производительности будет меньше, чем в случае
      с HDD, но зато мы ощутимо потеряем в объеме данных которые можем хранить.
      И уж если говорить про бд работающие в ОЗУ, то там тем более нужна максимальная производительность.


      Тоже ведь мода новая просматривается на такие БД! :)

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


      А данные бывают НЕОДНОРОДНЫЕ! Данные постоянно усложняются, и уже с нынешими всё это реляционное говно справиться не может! Особенно в этих долбаных "нормальных формах".

      Ну вот даже используя бд без схемы (например mongo), не было необходимости пихать туда именно неоднородные данные.


      Да ОТКУДА, блин?!

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


      СТАТИСТИКА! На Ваши намерения ей насрать, она видит РЕАЛЬНУЮ картину запросов, а не Ваши несчастные "планы".

      Дак я тоже вижу статистику! Причем вижу статистику за годы, со всеми трендами. У меня так же есть статистика
      с stage/testing серверов, к которым продакшн бд просто не имеет доступа.


      Человек, пользуясь своими, часто неосознанными метазнаниями, легко выявляет подобные ошибки, но может ли это сделать машина, да ещё без словаря? Как оказалось, может!

      Не может. И человек без дополнительных действий тоже не может. Вот даже на вашем примере "Алекандр": откуда человек или субд
      может узнать что:
      1) этой ошибки нет в паспорте (тогда в любых юридически значимых документах нужно писать именно с ошибкой)
      2) эта ошибка не была сделана целенаправленно? т.е. человека назвали именно "Алекандр"?
      Далее, вот на примере даже обычного списка контактов в телефоне (чем не телефонный справочник?). У меня есть как минимум несколько
      контактов, у которых вместо фамилии записана должность. Да, это ошибка с точки зрения данных, но мне так удобнее и я не буду
      пользоваться любой программой которая начнет исправлять ошибки, которые ее не просили исправлять.
      И это не учитывая кучи ложно-положительных результатов, в которых программа просто испортит данные, потому что ей показалось
      что фамилия похожа на должность. И человек в данном случае точно так же может ошибится, поэтому данные нужно сверять
      с реальными данными, а не пытаться угадать.
      Про предыдущий пример с OSM, где 50 южных полюсов: да в данном случае их можно удалить если они находятся на одинаковых координатах.
      Но только используя знание о том что южный полюс один. Откуда у программы будет это знание?
      Вот в доме два магазина "продуктовый", на одинаковых координатах. Как без физического визита узнать количество магазинов?
      Или в отделении банка, на одинаковых координатах три банкомата. Удалить два? Потеряем информацию о количестве банкоматов.
      Оставить оба? А вдруг второй случайно добавили? Нужно идти ногами и проверять.
      Ну и все эти ошибки на самом деле не настолько важны. Если их действительно много в базе (>10%) и мы точно знаем что
      это именно ошибки, то нужно исправлять интерфейс. Если их 1-2%, то пусть будут, какая разница? От того что в телефоном
      справочнике кто-то записан как "Алекандр" вот вообще ничего не изменится. Найти телефон человека все еще можно, позвонить
      ему можно. Бессмысленные запросы типа "количество человек с именем 'александр'" мало кто будет делать, а даже если и сделает,
      вряд ли ему нужна точность.


      Ну и как, "мигрируете" Вы мой граф по транспорту Москвы ХОТЬ КУДА-НИБУДЬ? :)

      Без конкретных запросов и хоть какой-то информации о том что нужно из него получить, я могу его
      мигрировать разве что из zip в bz2.


      Ошибки в коде должны выявляться ДО выхода продукта на рынок! По крайней мере, 99.999% из них.

      Это не реально, на любом более-менее сложном продукте. Причем продукт постоянно обновляется.


      Линейность-то важна, но по сравнению с прямым доступом у данным это вообще тьфу — плюнуть и растереть! Первичные ключи вообще не нужны — это ссылочные ключи должны бы давать прямой доступ, а с удалением данных нет ВООБЩЕ НИКАКИХ проблем!

      Не будет линейности — не будет прямого доступа. Придется как сайгак скакать по указателям которые ссылаются на разные физические страницы.
      Указатель от первичного ключа вообще ничем не отличается. Просто один обрабатывает ОС, а второй бд.


      С какого бодуна "теперь при каждой вставке нового текста у нас будет снова это разбиение"? Посмотрел новый элемент, добавил (или не добавил) новую айдишку к старому списку — и все дела!

      Дак мы на каждом новом элементе это делаем. Если в базе N элементов, а завтра добавят 2N элементов, то придется делать это для всех 2N новых элементов.
      И чем это отличается от full-scan?


  1. rybvv Автор
    31.05.2019 19:48
    -3

    Подошло время очередного «суточного» коммента. Что-то нет желания мне его сюда писать. На своей странице я и так комментирую, на страницу, судя по счётчику, народ заходит — что ещё надо? А здесь это разве что повод для очередной порции антилайков. Так что дам я, пожалуй, одну лишь ссылочку на сегодняшнее своё «произведение». Там, где я его опубликовал, оно было воспринято вполне благосклонно. Вдруг и здесь понравится?
    www.facebook.com/vladimir.rybinkin/posts/2391234017664225


    1. infund
      31.05.2019 20:37
      +5

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


    1. lair
      01.06.2019 01:47
      +4

      Что-то нет желания мне его сюда писать.

      Что лишний раз показывает, что никакой задачи, чтобы ваши идеи поняли, у вас нет.


  1. Mikluho
    01.06.2019 07:40
    +5

    Ну, началось! :))) И меня посчитали :))

    Ну, начнём с того, что вы, Владимир, видимо забыли в этой заметке рассказать суть вопроса, ради которого писали оную… Худо-бедно можно понять, что имеется в виду под сложными БД, но какую именно реальную практическую проблему вы хотите решить — решительно не понятно.
    Много слов про историю вопроса, а цель писания где? Неужто только вот в этом: «Хватит играть в реляционные погремушки!»?

    Так, а здесь что? А здесь проснулся Mikluho, который изрёк гениальнейшую мысль: «реляционные БД коммерчески более успешны для пользователей». Интересно, кто, когда, о чём это быдло (в смысле, пользователей) спрашивал? Ну хоть раз! А ещё он фактически процитировал мою заметку, сказав про «достаточно простой язык запросов» — работать со сложными данными стадо даже и не рыпается! А дальше понёс клиническую ахинею про «скорость работы с данными» и «персистентные хранилища», которые «до сих пор не слишком быстры на фоне объёмов данных». Так ВАЛИТЬ НАДО НАХЕР от этих долбаных таблиц! Не говоря уже про эти долбаные «сбалансированные деревья поиска». Хули вы там «искать» собрались, бараны? Тем и хороша графовая модель, что там ничего искать не надо! Ссылку кинул — и порядок!

    Во-первых, а зачем спрашивать, если пользователь голосует деньгами?
    Во-вторых, если вдруг не понятно, пользователь — это не тот, кто счета в формочки вбивает, а компания, которая для своих нужд покупает СУБД. А посему совсем не уместно упоминать тут какие-то стада, ибо они нам и вам зарплату платят.
    В-третьих, со сложными БД они таки не пытаются, а просто работают. И выбирают СУБД в том числе из коммерческих соображений.

    Далее вы опять занимаете любимую позицию «кто со мной не согласен — быдло, всё, кроме моих мыслей — ахинея» :)
    Но так уж и быть, попробую прояснить то, что большинству понятно, а вам невдомёк. Ну или вы, быть может, снизойдёте с небес да проясните, как в вашей идеологии решается конкретная задача.

    Есть у нас некая БД, в которой лежат финансовые отчёты. Формат данных задаётся снаружи всякими международными или более локальными нормами. Отчётных форм много, собираются они с разной периодичностью, многие формируются в определённых административно-территориальных разрезах. А ещё состав или способ вычисления показателей в отчётах иногда меняется по требованиям внешних организаций (например центробанка). Каждая форма характеризуется набором статических атрибутов и наборов табличных данных (уж от этих таблиц нику не деться). Часть данных в этих формах опираются на справочники, которые иногда меняются, т.е. в один период времени во всех отчётах должен использовать один набор значений конкретного справочника. Это позволяет, в частности, сравнивать данные из разных отчётов и делать аналитические и сводные отчёты.
    В такой картинке у конкретного отчёта есть несколько базовых атрибутов (т.е. общих для всех отчётов), таких как: «название отчётной формы», «версия», «отчётный период», «источник», «дата формирования», «автор». Набор остальных данных в отчёте зависит от формы и её версии.
    Конечные пользователи, конечно, хотят видеть отчёты в табличном представлении. И хотят видеть списки отчётов, отобранных по определённым атрибутам. И хотят, чтобы отчёт им на просмотр открывался быстро, т. е. кликнули в списке на нужный — и через пару секунд видят его в удобном табличном представлении, даже если в нём тысячи строк. А ещё они хотят, чтобы сводные и аналитические отчёты быстро вытягивали из БД значение всех показателей конкретных финансовых отчётов. Даже если эти отчёты из сильно разных дат.

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

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

    Mikluho
    Это мне напомнило опыт из 2000-го
    Лапуль, может, не надо тут про «опыт» от MS SQL? Статья посвящена как раз тому, чтобы ВЫШВЫРНУТЬ К ЧЕРТЯМ СВИНЯЧЬИМ это вонючее «табличное хранение»! И своё долбаное «объектное хранилище» засуньте туда же! Какой дебил когда сказал, что «в табличном хранилище — быстрый доступ»?! С КАКОГО БОДУНА? Быстрый доступ — это В ГРАФОВЫХ базах данных! Причём графовых НА УРОВНЕ ЯДРА, а не с этой вашей долбаной «эмуляцией»!

    да, апп-сервер мог модифицировать структуру БД
    Да?! А вот с этого места поподробнее, плиз! Кто там что и как мог «модифицировать»? :spy:


    Я вам не «лапуль»! Спрячьте ваше свинское фамильярство куда поглубже, можно даже в место, куда не заглядывает солнце :)

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

    «Модифицировать» — это значит, что наш апп-сервер при добавлении атрибута к сущности добавлял столбец в таблицу. Понятное дело, удалять и модифицировать столбцы он не пытался :).

    И да, пока вы не объясните, как ваши графовые бд делают удобно то, что нужно реальным массовым пользователям (т. е. тем, кто за всю эту красоту платит), вы балабол и теоретик, а не программист.


  1. rybvv Автор
    03.06.2019 06:40

    Ну что, разговор, похоже, окончен? По крайней мере, для него эта площадка совершенно не нужна. Только что отписался на Фейсбуке: Так тупой же, Свет! Я ж не эти распальцованные придурки! Кстати, хлебальники все эти долбаные «учителя» захлопнули, видимо, окончательно — молча шипят и гадят: карма -51, рейтинг -95.7. Ибо набор этих мудацких «правил» стимулирует превращение этого «сообщества разработчиков» в вонючую помойку, где правит бал отмороженное быдло. И вот с этим говном нам «догонять Америку»? Правда, в Америке система почти такая же, так что шансы какие-то есть. :)

    Ладно, дам СЮДА мой вчерашний коммент (может, даже подредактирую чуток по сравнению с тем, что на моей страничке написано), и пора валить отседова, на радость визжащему стаду. :)

    rk938
    Чтобы вытащить по этому указателю связанные объекты?
    Я же говорил: объекты вытаскиваются не по указателю, а по айдишке. Указатели требуют обслуживания — например, при перемещении объекта — и это делает почти неработоспособной саму идею графовой БД. Это концепция CODASYL, и её вполне справедливо критиковал Кодд.

    Так а в чем задача? Какие запросы? Что мы хотим получить из этих данных? Без этого, метод хранения «куча htm файлов в архиве ничем не хуже бд.»
    При чём тут htm-файлы? Я их просто нагенерил из базы стареньким генератором. А задача схемы простейшая: «как пройти в библиотеку». Как добраться из пункта A в пункт B с наименьшими затратами. В принципе, есть и другие задачи, но эта самая распространённая.

    Да хотя бы просто пачкой запросов. Не нравится SQL — всегда можно взять map-reduce функцию.
    Доступ К ОДНОМУ элементу пачкой запросов? Это и означает, что никакого доступа НЕТ. Со всеми вытекающими. Например, это мгновенный крест на графовых типах данных.

    Пока нет конкретных запрос, что мы хотим получить из этих данных, нельзя выбрать ни схему, ни конкретное хранилище.
    Господи, да при чём тут вообще запросы? Какое они вообще имеют отношение к схеме? Что Вы вообще можете знать о данных в БД или, тем более, будущих запросах пользователей? ДА НИЧЕГО! От данных мы хотим получить всю информацию, которая там вообще есть. Тогда ещё что-то можно говорить о выборе схемы.

    А что еще нужно от графовой бд кроме отношений между узлами?
    Вот как раз отношения между узлами нафиг не нужны! Они лежат мёртвым грузом, и пока не попасть в них запросом, не пошевелятся. А вот СВЯЗИ — это дело другое! Я вообще определяю «значение» как содержимое узлов графа, а «смысл» — как содержимое его рёбер.

    Мы сейчас говорим про абсолютно разные вещи. Я ничего не говорил про линейность/экспоненциальность алгоритма.
    АБСОЛЮТНО разные! Вы говорите про возню головками по дорожкам, про фрагментированные файлы, а я про прямой доступ к данным. Если его нет, эффективная работа с БД невозможна в принципе!

    Я говорил про линейное и случайное чтение (random access).
    Вот именно, про сраный seek. А как узнать, КУДА ИМЕННО нужно прыгать — не подскажете? :)

    Если элементы структуры не расположены рядом, а раскиданы по указателям, линейного чтения не будет.
    А какое оно будет, простите? Квадратичное? Логарифмическое? Экспоненциальное? :) И — повторяю — уровню хранения нет АБСОЛЮТНО никакого дела до структуры! Как стек протоколов TCP/IP работает — знаете? Любому уровню ПО БАРАБАНУ содержимое пакетов предыдущего — он работает только со СВОИМИ метаданными — остальное для него «чёрный ящик». Здесь ровно то же самое.

    Т.е. элемент с миллионом связей считывается всегда со списком его связей?
    Как пожелаете. Но связи — вот они, хранятся вместе с элементом. Не хотите — можете не читать. :)

    Я привел конкретный пример когда внешние ключи увеличивают количество чтений.
    Ничего подобного! Просто вместо значений будут сравниваться их айдишки (ключи в реляционной терминологии). Ещё неизвестно, что быстрее. :)

    Мы опять говорим про разные вещи похоже.
    Очень похоже! Кто такой Вы? Посредник между СУБД и пользователем? Даже Кодд задумывал свою модель именно ддля пользователей-непрограммистов! То есть посредники должны УБИРАТЬСЯ, а они плодятся и размножаются.

    Конечный пользователь моего приложения не знает о том что там где-то есть какая-то бд и ему это вообще не важно.
    Это ВАШИ пользователи. А для меня, как для разработчика СУБД, пользователем является именно Ваше приложение. Не взаимодействуют Ваши пользолватели с СУБД? Ну и забыли про них — «умерла, так умерла»! Хорошо, будем считать юзером именно Ваше прилолжение — принято. :)

    Пользователь это приложение, приложение прекрасно знает что улицы это класс, потому что все запросы на добавление данных были отправленны именно с учетом этого.
    А откуда ему знать-то? Ваше приложение — это юзер, а вот я, как СУБД, САМ буду определять, что там класс, что атрибут, а что значение! Это МОЯ зона ответственности! Беда, коль пироги начнёт печи сапожник!(с) :)

    Такие ошибки будут в любой базе и их не исправить без участия человека, хотя бы потому что у бд не будет тех знаний, что есть у человека.
    Ха-ха-ха! Это как раз с участием человека их не исправить! Ибо он тупой, страшно медленный и невнимательный. Только СУБД! Причём не РСУБД — та тоже нифига не видит.

    Узел — атомарный элемент данных, который нельзя разбивать и нельзя модифицировать в нескольких местах одновременно.
    Даже так? У меня — произвольная структура данных. Даже субграф можно считать узлом в большинстве случаев! Ну, хорошо: а почему «если запихать его в кэш, то он будет на нескольких серверах одновременно»? Мы ведь запихаем его в кеш ТОГО САМОГО сервера — остальные про этот узел и знать не знают!

    Если под кэшем вы имели ввиду какой-то кэш на том же самом сервере, то он никак не спасет, т.к. один сервер просто физически не может обработать весь поток запросов.
    Поток запросов НА ОДИН УЗЕЛ?! Да ещё и атомарный? Да ещё и вечно сидящие в кеше? Я же говорю: увольнять надо эту шоблу программистов! Немедленно! :)

    И да, это реальный пример из практики. 30% нагрузки кластера из 500 серверов приходилось на один атомарный элемент.
    Оба-на! Что за «элемент» — не подскажете? Ему же памятник надо поставить! :) И, заодно, что за софтина на нём захлебнулась?

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

    Ну вот видите? А Вы не только не занимаетесь верификацией данных, но и прямой доступ к элементу Вас не интересует! Что же делать бедолаге-пользователю? Только к моей СУБД бежать, сломя голову! :)

    реальный пример, один сложный запрос выполняется раз в месяц, но он должен выполнятся максимально быстро.
    Это не «реальный пример» — это «сферический конь в вакууме». ЧТО ЗА «сложный запрос»?

    «умная» субд просто снесет все индексы которые редко используются.
    Ну и правильно сделает! Ей ДОВЕРИЛИ право принимать решения? Так отойдите в сторонку — ей ЛУЧШЕ знать, что и как ей делать!

    3) доступность данных, если какой-то сервер сломался, данные должны быть доступны для обработки, вне зависимости от этого.
    Скажите, пожалуйста, сколько раз Вы видели сломавшийся сервер? Мне пока что не попадался ни разу. А вот сообщения «данные недоступны» — сплошь и рядом! Может, «дело было не в бобине»? :)

    Мы удаляем данные или нет? Ответ «А зачем?» я воспринимаю что как «не удаляем»
    Логически — удаляем. Физически — а зачем? В любом случае, с какого бодуна объём будет РАСТИ?

    2) если приложение запрашивает 16KB, ему просто дадут 4 страницы по 4KB
    Господи, в наше-то время?! У меня вот в «сортире»… ща гляну… блоки по 256К, при этом я могу заказывать до 8К таких блоков. Нужно, видимо, увеличить размер блока, но УМЕНЬШАТЬ ДО 4К!!! Операционке что, заняться нечем? Кстати, на фрагментацию памяти моему сортиру тоже совершенно насрать — память заказывается блоками, но работает он с ней как с непрерывным куском ОЗУ.

    5) если нужна нормальная производительность, в ядре дополнительно включаются и аллоцируются huge pages, хотя бы по несколько MB, в идеале GB.
    Сколько десятилетий назад написан этот кусок операционки? :)

    6) если мы удаляем данные из середины, мы можем их закрыть только элементом той же структуры.
    Ну, это ВАШИ проблемы. А вот МЫ спокойно удаляем что угодно и откуда угодно! :) Вы лучше ЗАПРОСЫ к СУБД давайте, если клиентское приложение, а СУБД уж как-нить сама со своими страницами и файлами разберётся!

    Тогда он будет работать медленее, чем мог быть.
    За счёт чего, интересно? У меня даже фантазии не хватает предположить, ЧТО ЖЕ сумеет его замедлить?

    Ну, будет фрагментация в ОЗУ, будем прыгать по указателям вместо линейного чтения. Да, потеря производительности будет меньше, чем в случае с HDD, но зато мы ощутимо потеряем в объеме данных которые можем хранить.
    Мы уже, кажется, договорились: СУБД со своими проблемами как-нить сама справится. :)

    Я вот вижу моду на колоночные бд, где данные одного поля хранятся вместе, чтобы их можно было обрабатывать векторными инструкциями.
    А моду на прямой доступ к элементу не завели ещё? Если нет, то какая разница, какой там ДРУГОЙ очередной онанизм нынче в моде?

    Ну вот даже используя бд без схемы (например mongo), не было необходимости пихать туда именно неоднородные данные.
    Ну так Вы просто никогда не сталкивались со сложными данными.

    Там нет навигационных выражений? К сожалению, я не работал с навигационными данными, не смогу подсказать что-то конкретное.
    Да откуда? Там же сказано: РЕЛЯЦИЯ! Я же писал:
    Третий Манифест: «РМ-предписания и запреты не могут быть предметом компромисса». Даже несчастный курсор «категорически запрещается», а уж более примитивной навигации просто не бывает в природе! РМД именно категорически запрещает их иметь, ибо концепция ключа сразу же превращает любые навигационные операции в рекурсивный SQL-запрос: раз кортежи идентификатора иметь не могут, нам придётся рыскать по значениям, хоть ключом их обзови.

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

    с stage/testing серверов, к которым продакшн бд просто не имеет доступа.
    ЧАВО?! СУБД не имеет доступа к данным о запросах, которые поступают ИМЕННО К НЕЙ?! Это круто! Это реально круто! Даже не так: это НЕРЕАЛЬНО круто! :)

    Не может. И человек без дополнительных действий тоже не может. Вот даже на вашем примере «Алекандр»: откуда человек или субд может узнать что:
    1) этой ошибки нет в паспорте (тогда в любых юридически значимых документах нужно писать именно с ошибкой)
    2) эта ошибка не была сделана целенаправленно? т.е. человека назвали именно «Алекандр»?

    ВОТ! Вы сами сказали: «человек или субд»! Я знаю, что встречается имя Алекандр. Но я утверждаю, что КАК человек, ТАК И СУБД в состоянии оценить ВЕРОЯТНОСТЬ того, что это ошибка. И что на те 10000+ исправленных ошибок не найдётся и 10- ошибок внесённых. Которые лечатся уже персональными запретами — и снова КАК для человека, ТАК И для СУБД.

    Далее, вот на примере даже обычного списка контактов в телефоне (чем не телефонный справочник?). У меня есть как минимум несколько контактов, у которых вместо фамилии записана должность. Да, это ошибка с точки зрения данных, но мне так удобнее и я не буду пользоваться любой программой которая начнет исправлять ошибки, которые ее не просили исправлять.
    И этот человек говорил мне что «если кто-то назвал человека „ул. Ленина“, я не хочу его обрабатывать в качестве улицы». Да на Вас не угодишь! :) А это Ваша персональная БД или всё-таки многопользовательская? ;) Да, кстати: а Вы поисковиками-то пользуетесь? Ведь эти суки так и норовят исправить слова запроса в соответствии со совими мудацкими представлениями о том, какитм он должен бы быть!

    И это не учитывая кучи ложно-положительных результатов, в которых программа просто испортит данные, потому что ей показалось
    Вы просто никогда не видели, СКОЛЬКО испорченных данных в БД, причём испорченных именно ЧЕЛОВЕКОМ! Ещё фрагмент из моей книги:
    Ошибки в данных могут быть какими угодно! H (h) вместо Н (н), замена значения (вместо 5-го поля записано в 6-м), неверное написание названий (например, компаний), что приводит к фактическим дублям, ссылки на несуществующие адреса, неверное количество цифр в номере телефона, etc, etc, etc. Мы уже не говорим про такие «мелочи», как регистр, разное количество пробелов, порядок слов в предложении и т.п. Причём количество ошибок весьма слабо коррелирует со стоимостью разработки БД. Простейший пример: дублирование данных при вводе названия улиц в РазНОм рЕгИСТрЕ. Более сложный пример «улица Ифонава» (улица Иванова), поскольку мы (точнее, Синдбад) не знаем заранее – может быть, и существует адрес: 215-й этаж 666-го Синепоросячьего Корпуса на Улице Вязов. Проверить, скажем так, сложно. Но самая большая сложность – это не найти, а понять, какое из лексикографически близких слов записано! Принять решение об изменении данных!

    Но только используя знание о том что южный полюс один. Откуда у программы будет это знание?
    От формата записи координат, котрый я предложил в заметках про OSM. Они просто автоматически схлопнутся в одну точку. :)

    Вот в доме два магазина «продуктовый», на одинаковых координатах. Как без физического визита узнать количество магазинов?
    По базе, разумеется! Не один же Вы способны наносить «физические визиты»! :)

    Или в отделении банка, на одинаковых координатах три банкомата. Удалить два? Потеряем информацию о количестве банкоматов.
    Зачем удалять? Их же три! :)

    Оставить оба? А вдруг второй случайно добавили? Нужно идти ногами и проверять.
    Ага! А Вдруг Вы соврали? Вас тоже надо «ногами проверять»! А потом меня, а потом… так и будем ВЕЧНО ногами топать? :)

    Ну и все эти ошибки на самом деле не настолько важны. Если их действительно много в базе (>10%) и мы точно знаем что это именно ошибки, то нужно исправлять интерфейс. Если их 1-2%, то пусть будут, какая разница?
    А как Вы вообще узнаете, что там есть хотя бы одна? Вы же верификацией СОВСЕМ не занимаетесь! :)

    вряд ли ему нужна точность.
    Конечно, конечно! Нафиг нужна точность? Подумаешь, 50 Южных полюсов! Подумаешь, ошибка в имени! Я приводил пример: сотрудники два дня искали одного старичка с фамилией ИBАНОВ (в нижнем регистре иbанов). Так старичку тому ДЕНЕЖКА полагалась! А ему её НЕ ВЫПЛАЧИВАЛИ из-за этих криворуких набивщиков и тупой модели данных, которой НАСРАТЬ на ошибки в них! Но кого волнует какой-то старичок? Чиновникам больше денег останется! И никто не виноват!

    Без конкретных запросов и хоть какой-то информации о том что нужно из него получить, я могу его мигрировать разве что из zip в bz2.
    С конкретными тоже не сумеете. Проверено! ;)

    Это не реально, на любом более-менее сложном продукте. Причем продукт постоянно обновляется.
    Да, согласен. Программисты вымерли, как мамонты. А то, что осталось, ЗАИТНТЕРЕСОВАНО в ошибках в коде!

    Не будет линейности — не будет прямого доступа. Придется как сайгак скакать по указателям которые ссылаются на разные физические страницы.
    Я же говорю: у меня в задаче коммивояжёра программа так и скачет, так и скачет по узлам! И работает со свистом! А без прямого доступа она ВООБЩЕ не была бы способна что-то делать! Линейность я рекламировал как раз в «сортире» — действительно, быстрее читать и писать данные именно непрерывным потоком! Но, во-первых, не так уж чтобы НАМНОГО быстрее — ну, на порядок, да и то вряд ли. Во-вторых, посмотрите, какой там визг поросячий стоял по поводу моего алгоритма вообще и поточного чтения/записи, в частности. :)

    Указатель от первичного ключа вообще ничем не отличается. Просто один обрабатывает ОС, а второй бд.
    УХ ТЫ! Сами придумали? Классный перл! :)
    По делу: чушь свинячья, разумеется! Указатель от ключа отличается тем, что указатель УКАЗЫВАЕТ на положение элемента в БД, а ключ НЕ указывает! И если не решить ЭТУ проблему, то вся эта мышиная возня с «фрагментацией файлов» не отразится на производительности ВООБЩЕ НИКАК!

    И чем это отличается от full-scan?
    Я писал: Один раз разбить тексты по языкам (или там по ключевым словам) — и пользуйся «ещё много-много раз»! Вы писали: При первом запросе (когда данные еще не разбиты) будет full scan. И теперь при каждой вставке нового текста у нас будет снова это разбиение. Вопрос: так у нас full-scan будет выполнен ОДИН раз или «при каждой вставке нового текста»? ;)


    1. lair
      03.06.2019 10:27
      +1

      Указатели требуют обслуживания — например, при перемещении объекта — и это делает почти неработоспособной саму идею графовой БД.

      Нет, не делает. Графовая БД — это концепт, а указатели — это реализация. А вы даже не можете определиться, на каком уровне вы ведете обсуждение.


      Господи, да при чём тут вообще запросы? Какое они вообще имеют отношение к схеме?

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


      То есть посредники должны УБИРАТЬСЯ, а они плодятся и размножаются.

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


      Ваше приложение — это юзер, а вот я, как СУБД, САМ буду определять, что там класс, что атрибут, а что значение! Это МОЯ зона ответственности!

      А нахрена мне, как пользователю, СУБД, которая сама что-то там решает и, как следствие, не дает мне возможности сделать нужные мне запросы?


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


      Только СУБД!

      И как же конкретно СУБД будет исправлять ошибки пользовательского ввода? И какими средствами для исправления таких ошибок обладает описанная вами модель данных, которые нельзя реализовать поверх "традиционной" РСУБД?


      Скажите, пожалуйста, сколько раз Вы видели сломавшийся сервер?

      Несколько раз в месяц я их вижу.


      СУБД со своими проблемами как-нить сама справится

      Нам всем очень интересно, как конкретно ей это удастся. СУБД должна давать своим пользователям гарантии, как в терминах производительности, так и в терминах CAP или ACID ("должна" в том смысле, что СУБД, которая ничего не гарантирует, не представляет практического интереса для прикладного использования). Какие гарантии дает ваша СУБД?


      У неё вся информация для принятия решения и так имеется!

      Откуда бы? Часть информации — да, вся — конечно, нет.


      СУБД не имеет доступа к данным о запросах, которые поступают ИМЕННО К НЕЙ?

      Вы невнимательны. Не к ней.


      Но я утверждаю, что КАК человек, ТАК И СУБД в состоянии оценить ВЕРОЯТНОСТЬ того, что это ошибка.

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


      А это Ваша персональная БД или всё-таки многопользовательская?

      Персональная, конечно: выше уже условились, что под "пользователем" понимается приложение.


      1. lair
        03.06.2019 12:48
        +1

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

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


        1. Опишем модель предметной области


          create entity type Street with
              required string property Name

        2. Загрузим какое-то количество данных


          create Street with
              Name 'Лесная'
          
          create Street with
              Name 'Огородная'

        3. Запросим то, что нам интересно


          get Street which
              Name starts with 'Лес'


        Тут как бы все понятно. Не важно, что диалект птичий, важно, что операции понятны, и относительно задаваемого ими контракта можно строить ожидания и гарантии. А в предлагаемой вами модели как все то же самое выглядит?