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


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


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




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


Есть два качественных улучшения в управлении данными:


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

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


Рамки задач ядра: управление структурой, запросы и базовый интерфейс для изменения данных.


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


Теперь рассмотрим упомянутые нюансы.


Все данные физически хранятся в одной таблице из 5 полей: ID, родитель (ID), тип (тоже ID), порядок среди равных (число), значение (набор байтов). У неё есть 3 индекса: ID, тип-значение, родитель-тип. Вместо обращения к базе данных, которая найдет таблицу, в ней найдет поле, в котором найдет данные, ядро обращается к единственной таблице, в которой по индексу сразу находит данные нужного типа.


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


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


Индексирование данных


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


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


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


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


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


Невозможность использования индекса


Избегайте использовать критичный к быстродействию фильтр по неиндексируемому значению поля:


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

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


Например
  1. Если в номерах банковских счетов вы анализируете код валюты по 6-8 символам, то вместо использования выражения SUBSTRING(Валюта, 6, 3) для отбора валют счетов следует вынести код валюты в отдельное поле в таблице счетов и делать выборку по его значению
  2. Когда вам требуется быстро найти человека по последним цифрам номера его телефона, то вместо поиска по маске %4567 стоит создать дополнительное поле с инвертированными номерами 89101234567 => 765432 (необязательно номер целиком) и затем также инвертировать условие поиска перед отправкой его в запрос: 7654%


Отсутствие индекса


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


Пример


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


Если же мы ставим значение «NULL» (текстовое) по умолчанию, то оптимизатор быстро найдет все невыполненные заказы при помощи индекса.



Последовательность выборки связанных сущностей


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


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


Пример

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



Оптимизатор может начать строить произведение таблиц, начиная с Отдела, прежде чем начнет применять фильтр к телефонам. Это может занять большое время.


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



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


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

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


  1. gasizdat
    30.05.2018 09:02

    Стесняюсь спросить, так чего в итоге изобрели-то? (Следующий вопрос будет — зачем?)


    1. AlexTest
      01.06.2018 01:49

      Человек заново «изобрел» adjacency list model (очевидно не подозревая о ее существовании) прикрутив к ней зачем то еще дополнительное поле типа. Более того он утверждает, что

      не используются триггеры и constraints, просто потому что всё это до сих пор не понадобилось
      при этом не объясняя как ему удается сохранять консистентность хранимых данных и не терять ресурсы и производительность на рекурсивных запросах.
      Я думаю это просто следствие того, что он не знает про limitations of the adjacency list model.

      UltimaSol пожалуйста, прежде чем патентовать что-то — прочтите для общего развития хотя бы вот эту простую статью из топа гуглопоиска по данной теме.
      Если не можете читать на английском — хабр вам в помощь.
      Вон например люди еще в 2012 году в статье и обсуждении размышляли как можно улучшить Adjacency List (что-то вроде ваших типов в отдельной таблице), но им даже в голову не пришло патентовать очевидные вещи!


      1. UltimaSol Автор
        01.06.2018 08:12

        прикрутив к ней зачем то еще дополнительное поле типа

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


        1. AlexTest
          01.06.2018 17:13

          Как вы можете рассуждать, не понимая о чем речь?
          Ок, не хочу больше спорить про техническую сторону.
          Последний вопрос к UltimaSol:
          Правильно ли я понимаю что вы запатентовали структуру данных?


          1. UltimaSol Автор
            01.06.2018 17:24

            Неправильно.
            Систему хранения и способ обработки.


            1. lair
              01.06.2018 17:31

              А ознакомиться с патентом где-нибудь можно?


              1. UltimaSol Автор
                01.06.2018 17:38
                -1

                Я же дал здесь ссылку. Вы просто пишете, не читая. Пишите дальше.


                1. lair
                  01.06.2018 17:40
                  +1

                  Ссылку на патент? В посте я ее не нашел. Вас не затруднит повторить, я надеюсь.


            1. michael_vostrikov
              01.06.2018 19:43

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

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


              1. UltimaSol Автор
                01.06.2018 19:51

                С точки зрения патентного права, оба случая закрыты этим патентом.
                Хотя это всё вообще не важно.


                1. michael_vostrikov
                  02.06.2018 07:11
                  +1

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

                  Magento EAV


                  Обратите внимание на названия полей.

                  Я правда не разбираюсь в патентах, но в обратном случае в существовании патентов не было бы смысла.


                  1. UltimaSol Автор
                    02.06.2018 18:51
                    -1

                    Обратите внимание на названия полей.

                    Я правда не разбираюсь в патентах, но в обратном случае в существовании патентов не было бы смысла.


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

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


                    1. michael_vostrikov
                      02.06.2018 19:39
                      +1

                      То есть вы, как разработчик программы, защищенной патентом, согласны, что никакие функционально эквивалентные вариации указанной на рисунке схемы не являются нарушением вашего патента?

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


              1. lair
                01.06.2018 23:58

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


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


                Вообще, конечно, этот патент — это прекрасная иллюстрация к тезису "запатентовать можно что угодно". Особенно жгут "фиг. 8" и следующее к ней обоснование:


                Основная проблема информационных систем — это растущая цена их поддержки при возрастании сложности системы, причем зачастую затраты на разработку и сопровождение растут экспоненциально (см. Фиг. 8). Два основных фактора риска здесь: несовершенство разработки программного кода и компромисс при выборе архитектуры базы данных. Заявляемая система позволяет пользователю самостоятельно задать сколько угодно сложную структуру данных и правила их обработки без необходимости создания таблиц базы данных, индексов, хранимых процедур и функций, программного кода. Таким образом, нет необходимости обращаться к дорогостоящей команде разработки: аналитик, ведущий разработчик, программист/кодер, тестировщик, внедренец. Заявляемая группа изобретений используют уже готовый программный код и архитектурное решение в виде ограниченного набора примитивных блоков, из которых можно построить информационную систему любой сложности, обеспечивая универсальность системы, в которой зависимость затрат на сопровождение от сложности системы будет не хуже линейной. Это преимущество обеспечивается определенной избыточностью данных, поскольку в ней проиндексированы все хранящиеся данные, и вычислений, однако по стоимости эти затраты намного ниже временных и материальных затрат на содержание команды разработки. Самый главный риск — человеческий фактор при проектировании и реализации программного кода и базы данных — полностью исключен.


  1. lair
    30.05.2018 09:31

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


    1. UltimaSol Автор
      30.05.2018 09:59

      Это не EAV, поэтому подразумеваемых вами недостатков тут нет.
      Постарайтесь без клише обойтись и, если интересно, я расскажу по пунктам, что и как.
      Статью старался не перегружать, потому что есть отдельные ссылки, где всё можно посмотреть и потрогать.


      1. lair
        30.05.2018 10:05
        +2

        Все данные физически хранятся в одной таблице из 5 полей: ID, родитель (ID), тип (тоже ID), порядок среди равных (число), значение (набор байтов).

        Не EAV, допустим. Тогда что? Ключ-значение с иерархией? Возьмите список недостатков от KV.


        Ну и вопросов про ошибки и шардинг это все равно не отменяет.


  1. UltimaSol Автор
    30.05.2018 10:24

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


    1. mayorovp
      30.05.2018 10:33
      +2

      И какие же у низкоуровневой работы с данными риски?


    1. lair
      30.05.2018 11:02
      +2

      Не KV

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


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

      Это все, простите, общие слова (которыми, к слову, пестрит маркетинговая документация практически любой СУБД). А конкретику можно какую-нибудь, которая бы их подтверждала?


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


      Или возьмем консистентность. Как конкретно в вашей системе гарантируется ссылочная целостность, и почему это проще и лучше, чем в традиционной реляционной БД?


      1. leotsarev
        30.05.2018 11:39

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


        Ах да, транзакций же тоже нет. Тогда не знаю


  1. lair
    30.05.2018 11:05
    +1

    Все данные физически хранятся в одной таблице из 5 полей: ID, родитель (ID), тип (тоже ID), порядок среди равных (число), значение (набор байтов).

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


    1. UltimaSol Автор
      30.05.2018 12:33

      Будет такая структура в Редакторе типов:


      Так выглядит добавленный объект:


      А так имевшиеся ранее и новые строчки в базе:


      1. lair
        30.05.2018 12:46

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


        1. UltimaSol Автор
          30.05.2018 13:09

          Добавятся строки метаданных (зеленым) и данных (синим)


          Сама книга будет выглядеть в редакторе так:


          А в Словаре этак:


          1. lair
            30.05.2018 13:18

            Parent | ID  | Value
            220    | 221 | 1923
            220    | 224 | 670

            А теперь объясните мне, почему это не EAV.


            1. UltimaSol Автор
              30.05.2018 13:27

              А при чем здесь этот фрагмент картинки?

              Я вам совсем другое показывал, и вот то — не EAV.


              1. lair
                30.05.2018 13:30

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


                1. UltimaSol Автор
                  30.05.2018 13:41

                  При том, что это — EAV, и это нижний уровень.


                  Что «это»?

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


                  1. lair
                    30.05.2018 13:43

                    Что «это»?

                    Ваше хранилище.


                    Я говорю про принципиально иную структуру

                    То есть данные в вашем хранилище имеют "принципиально иную структуру", нежели показанная вами же в примере выше? Так какую же, расскажите нам.


              1. Hardcoin
                30.05.2018 19:40
                +1

                Ваше хранилище выглядит как EAV и крякает как EAV. Серьезно, если это не EAV — верю на слово, но в чем разница? Желательно техническими словами, а не маркетинговыми.


                1. UltimaSol Автор
                  30.05.2018 21:07
                  -2

                  Ваше хранилище выглядит как EAV и крякает как EAV.

                  Я зачесываю волосы налево. По-вашему, я такой же зверюга, как Гитлер. Я, правда, ещё и рыжий. Ну, наверняка комик, скажете вы. А если я крякну?

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

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


                  1. Hardcoin
                    30.05.2018 22:11
                    +1

                    По-вашему, я такой же зверюга, как Гитлер.

                    Ну какая глупость. Я же говорю, верю на слово, что отличается, но чем? От Гитлера вы, например, отличаетесь тем, что не возглавляете партию (и можно ещё сотню существенных отличий найти).


                    Ваше решение выглядит как СУБД поверх хранилища EAV. Во всяком случае на первый взгляд.


                    техническими словами EAV как таковой неработоспособен

                    Это не "технические слова", извините. Это как раз маркетинговый булшит — "как таковой неработоспособен".
                    Технический специалист из вашей команды может чуть более техническую статью написать? Математика, бенчмарки, примеры синтаксиса для сложных случаев. Мы же на Хабре всё-таки. Если есть, конечно, желание и время.


                    1. UltimaSol Автор
                      30.05.2018 22:19

                      Вот здесь есть тестовый стенд, бенчмарки мордой лица на вас смотрят.


                      1. Hardcoin
                        30.05.2018 22:26

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


                    1. UltimaSol Автор
                      31.05.2018 12:35

                      Я сделал выгрузку и анализ журналов одного из сервисов.
                      Это рекрутерский сервис, интегрированный с HH.RU: оттуда забираются анкеты кандидатов, хранятся вакансии, можно назначать встречи, отправлять СМС и письма.
                      Вчера там работал 21 пользователь, и они за день сделали чуть больше 10000 запросов на изменение, которые заняли в сумме 2.26 секунды согласно журналу:


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

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


                      Это за самый нагруженный час:


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


                      1. lair
                        31.05.2018 13:25

                        и они за день сделали чуть больше 10000 запросов на изменение

                        … а сколько "запросов на изменение" у вас происходит, когда пользователь обновляет четыре свойства у одного объекта?


                        1. UltimaSol Автор
                          31.05.2018 13:54

                          При создании, удалении и изменении — по 1 запросу на свойство, при удалении объекта — 1 запрос на все.


                          1. lair
                            31.05.2018 13:55

                            … то есть когда пользователь изменяет четыре свойства, вы шлете в четыре раза больше запросов на изменение, чем, гм, традиционные решения?


                            1. UltimaSol Автор
                              31.05.2018 13:59
                              -1

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


                              1. lair
                                31.05.2018 14:14

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

                                Вы правда хотите пообсуждать разницу в стоимости низкоуровневых и высокоуровневых операций?


                                1. UltimaSol Автор
                                  31.05.2018 14:43

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


                                  1. lair
                                    31.05.2018 14:50

                                    Это быстро работает даже сейчас, при эмуляции всего процесса в базе данных, с громадным оверхэдом

                                    "Быстро" — понятие очень относительное.


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

                                    Если кто-то сможет его с этими характеристиками написать.


                                    1. AlexTest
                                      31.05.2018 15:07

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


                              1. roscomtheend
                                01.06.2018 14:28

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

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

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


                      1. Hardcoin
                        31.05.2018 21:21
                        +1

                        Спасибо. Теперь намного понятнее, на какую нишу вы позиционируетесь.


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


                  1. lair
                    30.05.2018 22:28

                    Ок, техническими словами EAV как таковой неработоспособен, если пытаться сделать приложение только средствами EAV

                    Прекрасно. Осталось объяснить нам, чем конкретно ваше решение отличается от EAV.


                    Я же утверждаю, что это решение подходит для любых задач прикладной разработки.

                    Утверждать-то можно что угодно.


  1. m03r
    30.05.2018 11:11
    +1

    Внимательно прочитал текст, и не могу избавиться от ощущения взаимоисключающих параграфов. Так, в начале читаем: «вся черновая, рутинная работа программиста вынесена “за скобки”». Но при этом далее: «адаптация этих средств под конкретный проект сопоставима с написанием их с нуля».

    Ещё: заявлено «повышение надёжности базы данных за счёт минимизации ошибок при добавлении новых данных», но при этом — нельзя задать CONSTRAINT'ы.

    Ещё в работе с СУБД «лавинообразное» (читай квадратичное) снижение производительности обычно связано с отсутствием правильных индексов, добавлением которых проблема решается.

    В примере с «последовательностью выборки связанных сущностей» планопостроитель любой СУБД построит правильный запрос при нормальной реляционной структуре таблиц, здесь преимущества мне совершенно неочевидны.


    1. UltimaSol Автор
      30.05.2018 20:47

      Так, в начале читаем: «вся черновая, рутинная работа программиста вынесена “за скобки”». Но при этом далее: «адаптация этих средств под конкретный проект сопоставима с написанием их с нуля».


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

      Ещё: заявлено «повышение надёжности базы данных за счёт минимизации ошибок при добавлении новых данных», но при этом — нельзя задать CONSTRAINT'ы.


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

      Ещё в работе с СУБД «лавинообразное» (читай квадратичное) снижение производительности обычно связано с отсутствием правильных индексов, добавлением которых проблема решается.


      Заставьте программиста залезть в базу, найти ВСЕ тонкие места и починить. И починить правильно. Бизнес-пользователю такое удается редко, точнее, почти никогда.

      В примере с «последовательностью выборки связанных сущностей» планопостроитель любой СУБД построит правильный запрос при нормальной реляционной структуре таблиц, здесь преимущества мне совершенно неочевидны.


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


      1. lair
        30.05.2018 21:06

        Бизнес-пользователю такое удается редко, точнее, почти никогда.

        А вы думаете, бизнес-пользователь способен построить правильную сущностную модель системы? Так нет, не способен. Тогда при чем тут бизнес-пользователь?


        1. UltimaSol Автор
          30.05.2018 21:20

          Как раз тут не про бизнес-пользователя, а про программиста: его не нужно заставлять делать неблагодарную, незаметную, не оплачиваемую отдельно работу, когда Интеграл почти всю её сделал за него.


          1. lair
            30.05.2018 22:26

            Ну так не надо заставлять программиста делать неблагодарную и неоплачиваемую работу — просто заплатите ему.


            1. UltimaSol Автор
              30.05.2018 23:41

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


      1. m03r
        30.05.2018 21:23

        Спасибо за разъяснения, но у меня всё равно осталась путаница. Что входит в обязанности администратора, программиста и бизнес-пользователя?


  1. leotsarev
    30.05.2018 11:34

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


    1. UltimaSol Автор
      30.05.2018 12:43

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

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


      1. lair
        30.05.2018 12:47
        +2

        А говорю, что устраняю непродуктивные накладные расходы и риски за счет добавления некоторой избыточности

        А избыточность, значит, не добавляет накладных расходов?


      1. Hardcoin
        30.05.2018 19:42

        сделать эту работу за него

        А кто будет делать эту работу за него? Программист? Или автоматический оптимизатор? Непонятно пока.


        1. UltimaSol Автор
          30.05.2018 21:35

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


          1. Hardcoin
            30.05.2018 21:59

            Т.е. оптимизатор автоматический? Хорошо. В mysql или posrgres так же используются оптимизаторы для построения плана запроса. Какие вы видите преимущества в вашем проекте по сравнению с ними?


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


            1. UltimaSol Автор
              30.05.2018 22:39

              Т.е. оптимизатор автоматический? Хорошо. В mysql или posrgres так же используются оптимизаторы для построения плана запроса. Какие вы видите преимущества в вашем проекте по сравнению с ними?


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

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


              Пример с пятью миллионами объектов, что составляет 31 872 291 строку в представленной здесь архитектуре.
              Можете попробовать сделать аналог в классической СУБД (или найти существующий, коих полно), который будет работать в 10 раз быстрее.


              1. m03r
                30.05.2018 22:51

                А сколько весит таблица и индекс для КЛАДРа?


                1. UltimaSol Автор
                  30.05.2018 23:25

                  Кладр весом в 320МБ в плоских файлах будет весить 500МБ в классической СУБД с индексами по популярным полям поиска и 1500МБ в Интеграле, где проиндексировано всё. Порядок чисел таков.


              1. Hardcoin
                30.05.2018 22:55

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


                P.S. найти у вас "Селезневская, 10" не вышло, хотя такой адрес явно есть.


                1. UltimaSol Автор
                  30.05.2018 23:22

                  Вы предлагаете это сделать мне? Повторюсь, это очень странное предложение. Мне интересно посмотреть на сравнительный бенчмарк (если он есть или вы планируете его сделать).

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

                  P.S. найти у вас «Селезневская, 10» не вышло, хотя такой адрес явно есть.

                  Там тоже есть P.S.:
                  P.S. Сервис немного глючноват в плане перебора комбинаций (все таки его суть не в этом), предложения по исправлению с благодарностью принимаются.


          1. lair
            30.05.2018 22:30

            Ядро сделает работу: создаст структуру и перестроит индексы

            И где гарантии, что оно построит индексы правильно?


            (Вот у MS в Azure для таких оптимизаций прикручено наблюдение за статистикой в очень больших объемах и модель машинного обучения. И то они автооткат сделали.)


            1. UltimaSol Автор
              30.05.2018 22:47
              +1

              А там всего 3 индекса на всё, сложно сделать неправильно.

              Я не первый, кто пытался заставить работать такую архитектуру. Есть эпичные случаи, но у парней не особо получалось. Azure идет путём тех парней, применяя танковые клинья и ковровое бомбометание наблюдение в очень больших объемах и модель машинного обучения, я — своим, упрощая всё.


              1. lair
                30.05.2018 22:51

                А там всего 3 индекса на всё, сложно сделать неправильно.

                Всегда три индекса? А как же write vs read? Покрывающие индексы, разные виды деревьев, пространственные, прочая смешная требуха?


                One size doesn't fit all.


                1. UltimaSol Автор
                  30.05.2018 23:05

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

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


                  1. lair
                    30.05.2018 23:13

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


                    1. UltimaSol Автор
                      30.05.2018 23:32

                      Нет-нет, что вы!


                      1. lair
                        30.05.2018 23:35

                        Хотя, архитектуру определяет один человек

                        Не везде это так.


              1. roscomtheend
                31.05.2018 14:10

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


                1. UltimaSol Автор
                  31.05.2018 21:15

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

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


                  1. roscomtheend
                    01.06.2018 14:19
                    +1

                    > Сложность вполне решаемая.

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


                    1. UltimaSol Автор
                      02.06.2018 19:04

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


                      1. lair
                        02.06.2018 19:31

                        А напомните еще раз, как вы строите индексы по строковым значениям длиннее килобайта?


  1. leotsarev
    30.05.2018 11:37

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


    1. UltimaSol Автор
      30.05.2018 19:45

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


      1. leotsarev
        01.06.2018 07:59

        А группировка там есть? Having?
        Приведите пример, во что транслируется запрос «все авторы с двумя или более книгами» на вашей базе.


        1. UltimaSol Автор
          01.06.2018 19:44

          Есть аналог HAVING.

          Запрограммированный отчет в интерфейсе будет выглядеть примерно так:


          В базу улетит примерно такой запрос:

          SELECT a227.val v1_217,COUNT(a217.val) v2_217 
          FROM test a217 
          LEFT JOIN (test r227 JOIN test a227) ON r227.up=a217.id AND a227.id=r227.t AND a227.t=225 
          WHERE a217.up!=0 AND a217.t=217 
          GROUP BY v1_217 
          HAVING v2_217>=99999999 AND v2_217<=2
          


          Как это делается можно также посмотреть на видео (полторы минуты).


  1. DEbuger
    30.05.2018 11:40

    В пред статьях было написано что интеграл построен на PHP + MySQL. Как оно может работать быстрее MySQL?


    1. roscomtheend
      31.05.2018 14:18

      Легко — делаете крайне неоптимальную структуру на MySSQL в сравнительном тесте и…


  1. eugenero
    30.05.2018 19:27
    +1

    Кажется, я понял. Автор изобрёл не EAV и не ORM, а дерево типов, а также способ уложить его в таблицу. Очень знакомо. Удивительно, что такую тривиальность можно запатентовать. UltimaSol, можно ссыль на патент или просто вложите сюда текст.


    1. UltimaSol Автор
      30.05.2018 21:14

      Спасибо, коллега! Вы первый комментатор, кто вдумался о чем речь.
      На самом деле, запатентовать можно что угодно, и в ходе патентного поиска я насмотрелся всякого. Гораздо сложнее добиться практической работоспособности, и я начинал именно с неё.
      Ссыль


      1. eugenero
        30.05.2018 21:59

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


        1. UltimaSol Автор
          30.05.2018 22:15

          Но ведь такая конструкция возникает во всякой более-менее развитой информационной системе

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


          1. lair
            30.05.2018 22:33

            В качестве самодостаточного работоспособного решения я такого нигде не видел и даже не слышал.

            Вы-то не видели, а я на рубеже века разработал систему со схожим механизмом хранения и успешно ее внедрил как минимум дважды.


            1. UltimaSol Автор
              30.05.2018 22:52

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


              1. lair
                30.05.2018 22:53

                … а я где-то говорил, что отчаялся? Та ни, я EAV до сих пор использую.


        1. stychos
          31.05.2018 21:28

          Для одной логистической конторки такой же костыль лепил лет пятнадцать назад. И не подумал бы что изобретаю что-то выдающееся, и в упор не знал (да и не знаю) о буковках EAV =)


          1. UltimaSol Автор
            31.05.2018 21:31

            Да все лепили подобные костыли, именно поэтому такая реакция у читателей.


            1. stychos
              01.06.2018 10:38

              И у большинства оно работало, отсюда вопрос — а что патентуется, если это уже обжёвано, обмусолено в теории и практике тысячи раз до?


      1. TischenkoSergey
        01.06.2018 19:53

        >Спасибо, коллега! Вы первый комментатор, кто вдумался о чем речь.

        Удивительно то, что читателям приходится гадать, что именно автор статьи имел ввиду. Тут естественно кто-то угадает, кто то нет…

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


    1. lair
      30.05.2018 22:32

      Автор изобрёл не EAV и не ORM, а дерево типов, а также способ уложить его в таблицу.

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


      1. UltimaSol Автор
        30.05.2018 22:56

        Да бог с вами, назовите это EAV, если вам так лучше.
        EAV и Интеграл ничем не отличается в плане хранения всех атрибутов в одной таблице.
        В EAV, наверное, тоже есть встроенный редактор типов, там можно работать с миллионами записей, произвольно создавать структуры данных, писать запросы, которые реализуют любые конструкции SQL и всё такое.
        Да EAV, чё…


        1. lair
          30.05.2018 23:00

          там [в EAV] можно работать с миллионами записей, произвольно создавать структуры данных, писать запросы, которые реализуют любые конструкции SQL и всё такое.

          Можно, конечно.


          Ну а встроенный редактор типов — это, извините, как ваша "экосистема": "учитывая простоту архитектуры, адаптация этих средств под конкретный проект сопоставима с написанием их с нуля". В том смысле, что если кто-то построил (как я в свое время) фреймворк на базе EAV, то редактор типов там был второй реализованной задачей (и она тривиальна).


          Да EAV, чё…

          Да я же не против, я искренне спрашиваю "в чем отличия", только пока что-то никто не рассказывает.


      1. eugenero
        30.05.2018 23:04

        Более высокий уровень абстракции — как множества vs категории. Это красиво и, время от времени, идеологически необходимо.


        1. lair
          30.05.2018 23:11
          +1

          А более конкретно? Я выше уже приводил пример:


          Parent | Type | Value
          220    | 218  | 1923
          220    | 223  | 670

          (это реальная структура хранения от автора статьи)


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


          1. eugenero
            30.05.2018 23:34

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


            1. lair
              30.05.2018 23:36

              Лично меня вряд ли может, потому что в этом клубе джентельменам на слово не верят.


            1. roscomtheend
              31.05.2018 14:24

              И лишиться патентов, которые получены минимум на 20 лет позже разработанного? Новизны-то в них не окажется.


          1. AlexTest
            31.05.2018 06:09

            там нет оптимизации для выборки объектов произвольной глубины
            Уверен что UltimaSol даже не представляет как это его «изобретение» будет жрать как не в себя ресурсы и жутко тормозить на т.н. рекурсивных запросах к этой единственной таблице если таких объектов произвольной глубины будет в ней достаточно много. Думаю уже ста тысяч хватит чтобы все просто умерло даже на самом крутом железе.


            1. UltimaSol Автор
              31.05.2018 13:09

              Вполне представляю и могу вам показать — см. комментарий выше.

              Статистика взята из сервиса, где одновременно работают от 15 до 30 человек, в работе у них больше 50 тысяч кандидатов.
              Сервер самый простой: стоимость менее 25$ в год, 1 ядро @2.5MHz, RAM 1Gb.


              1. AlexTest
                31.05.2018 14:43

                Вы хоть понимаете о чем речь?
                Где в этом сервисе объекты произвольной глубины?
                Как вы их ищете по атрибуту, который может быть на ЛЮБОМ уровне в ЛЮБОЙ ветке дерева данных такого объекта?
                Как вы в конце концов извлекаете и собираете такие объекты, где чтения данных КАЖДОГО уровня КАЖДОЙ ветки требуется ОТДЕЛЬНЫЙ запрос к БД?


                1. UltimaSol Автор
                  31.05.2018 20:38

                  Вы хоть понимаете о чем речь?
                  Где в этом сервисе объекты произвольной глубины?

                  Немного понимаю. Вот, ниже структура таблиц, как она видна программисту в этом сервисе:


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

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

                  Как вы их ищете по атрибуту, который может быть на ЛЮБОМ уровне в ЛЮБОЙ ветке дерева данных такого объекта?
                  Как вы в конце концов извлекаете и собираете такие объекты, где чтения данных КАЖДОГО уровня КАЖДОЙ ветки требуется ОТДЕЛЬНЫЙ запрос к БД?


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


                  1. lair
                    31.05.2018 22:04

                    Вот, ниже структура таблиц, как она видна программисту в этом сервисе:

                    Я что-то в этой структуре глубины больше двух-то и не вижу.


                    Так и ищу, по коду типа. Индекс выводит меня прямо к нужному листу нужной ветки, не пробегаясь по всему дереву.

                    Дадада, вот только теперь как от этого листа в один запрос попасть к соответствующему началу дерева?


                    Грубо говоря, представьте себе, что у вас есть "авторы", у них есть вложенные сущности "книги" (да, в рамках этой задачи у каждой книги есть только один автор, и книги без авторов не бывает; "вложенная" — это когда parent этой сущности — это другая сущность), у "книги" есть вложенная сущность "глава", у "главы" — "страница", у "страницы" — "абзац", а вот в "абзацах" бывают "термины". Вот получили в в один запрос нужный "термин" — а теперь можете ли вы в один запрос сказать, у какого автора он встретился? А если задачу немного — совсем немного — усложнить, и сказать, что под "книгой" бывают "разделы", а под "разделами" — другие "разделы", и так до бесконечности, а вот уже в "разделах" — "термины"?


                    1. UltimaSol Автор
                      31.05.2018 22:11

                      В любой СУБД вам придется сделать столько JOIN, сколько уровней от автора до нужной вам сущности. Точно такой же запрос с тем же количеством JOIN'ов будет выполнен и в этой архитектуре — один запрос.


                      1. lair
                        31.05.2018 22:13

                        В любой СУБД вам придется сделать столько JOIN, сколько уровней от автора до нужной вам сущности.

                        Эээ, конечно же, нет. Если система заточена под иерархии (как видно из вашего ответа, ваша — не заточена), то будет не больше одного JOIN.


                        Точно такой же запрос с тем же количеством JOIN'ов будет выполнен и в этой архитектуре — один запрос.

                        … так что же делать, если количество уровней неизвестно?


                        1. UltimaSol Автор
                          31.05.2018 22:16

                          Вы о чем сейчас? Приведите пример, пожалуйста.
                          Это решение эмулирует РСУБД и её возможности.


                          1. lair
                            31.05.2018 22:18

                            Я сейчас о способах хранения древовидных структур в БД — которых даже для РСУБД не меньше трех (а еще ведь есть нереляционные БД).


                            Собственно, все, что я хотел увидеть — это то, что на хранение именно древовидных структур ваша система тоже не заточена.


                            1. UltimaSol Автор
                              31.05.2018 22:40

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


                              1. lair
                                31.05.2018 22:42

                                В данном случае нет цели хранения древовидных структур

                                Вот, собственно, и ответ на "автор изобрёл [...] дерево типов". Что и требовалось доказать.


                                Повторюсь в очередной раз, система решает задачу РСУБД в общем

                                Эм, зачем решать задачу РСУБД, если есть РСУБД?


                                без экзотики и спецнаправлений.

                                Древовидные структуры — это нифига не экзотика.


                                1. UltimaSol Автор
                                  31.05.2018 22:51

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


                                  1. lair
                                    31.05.2018 22:53

                                    В том-то и беда, что ни что, ни как, ни зачем в статье не указано. Обо всем приходится гадать.


                  1. michael_vostrikov
                    01.06.2018 06:04

                    Вот, ниже структура таблиц, как она видна программисту в этом сервисе

                    Подскажите, какой запрос (на SQL) летит в базу, если мы хотим найти все вакансии, на которые откликнулись кандидаты с фамилией "Иванов", и вывести город, зарплату от/до, и работодателя вакансий. С разделением по страницам, естественно.


                    1. UltimaSol Автор
                      01.06.2018 21:05

                      Примерно такой запрос, как ниже.
                      Количество записей на странице определяется параметром отчета, номер страницы передается также параметром.

                      SELECT a330.val v1837447_321,a208.val v1837452_0,a236.val v1837453_208,a260.val v1837454_208,a261.val v1837455_208,a210.val v1837456_0 
                      FROM hr4hr a209 
                      LEFT JOIN (hr4hr r321 JOIN hr4hr a321 ) ON r321.up=a209.id AND a321.id=r321.t AND a321.t=321 
                      LEFT JOIN hr4hr a330 ON a330.up=a321.id AND a330.t=330 LEFT JOIN hr4hr a208 ON a208.t=208 AND a209.up=a208.id 
                      LEFT JOIN (hr4hr r236 JOIN hr4hr a236 USE INDEX (PRIMARY)) ON r236.up=a208.id AND a236.id=r236.t AND a236.t=234 
                      LEFT JOIN hr4hr a260 ON a260.up=a208.id AND a260.t=260 
                      LEFT JOIN hr4hr a261 ON a261.up=a208.id AND a261.t=261 
                      LEFT JOIN hr4hr a210 ON a210.t=210 AND a208.up=a210.id 
                      WHERE a209.up!=0 AND a209.val!='' AND a209.t=209 AND a330.val ='Иванов'
                      LIMIT 10,20
                      


              1. kahi4
                31.05.2018 18:12

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


                1. UltimaSol Автор
                  31.05.2018 20:44

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

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


          1. UltimaSol Автор
            31.05.2018 13:17
            -1

            (это реальная структура хранения от автора статьи)


            Нет, это обрезанная версия, зачем передергиваете, «джентльмен»?


            1. lair
              31.05.2018 13:23

              Я, вроде, нигде и не говорил, что она полная.


              А, главное, если опущенные мной фрагменты влияют на классификацию — то вы покажите, как именно.


              1. UltimaSol Автор
                02.06.2018 18:45
                -1

                Фатально


                1. lair
                  02.06.2018 18:47

                  Докажите.


                  1. UltimaSol Автор
                    02.06.2018 19:09
                    -1

                    На выкинутые вами поля построены индесы. Они принципиально меняют план запроса к базе.


                    1. lair
                      02.06.2018 19:15

                      (1) у вас есть индекс на поле Order, который "принципиально меняет план запроса к базе"?
                      (2) выкинутое мное поле ID влияет на план запроса к БД (на самом деле — не всегда), но не на классификацию. Но вообще, конечно, да, для запроса конкретного свойства это поле очень нужно — чтобы добавить в план запроса key lookup и джойн… вы же покрывающие индексы строить отказываетесь, хотя они бы избавили вас от лишней ветки.


                      1. lair
                        02.06.2018 19:29

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

                        … ну да, так и есть, добавление в индексы INCLUDE резко улучшило план запросов (пять index seek, ни одного скана, ни одного key lookup).


  1. lair
    01.06.2018 23:47

    Администратор работает с предельно простой базой данных, в которой задачи кластеризации, зеркалирования, шардирования и подобные решаются также значительно проще

    О, кстати, о "решаются проще". Есть, значит, простая задачка: у меня есть книги и есть их содержимое (текст + источник + еще несколько полей). Я хочу, чтобы данные по книгам лежали на SSD, а их содержимое (очевидно, этих данных больше на несколько порядков, но зато они намного реже используются) лежали на HDD. Как это сделать в MS SQL с традиционной схемой, я хорошо знаю и представляю. А как это сделать в вашем решении мечты?


  1. lair
    01.06.2018 23:54

    Все данные физически хранятся в одной таблице из 5 полей: ID, родитель (ID), тип (тоже ID), порядок среди равных (число), значение (набор байтов). У неё есть 3 индекса: ID, тип-значение, родитель-тип.

    И еще раз кстати. А как вы решаете ту проблему, что далеко не все значения вообще можно проиндексировать (например, в MS SQL в индекс нельзя включить поля длинее 900 байт, в InnoDB есть аналогичные ограничения)?


  1. lair
    02.06.2018 01:32
    +1

    … я, значит, не поленился и создал маленькую тестовую БД. Схема тривиальна: авторы-книги, у автора только имя, у книги — автор, название, год и число страниц. 100 тысяч авторов, для каждого автора от 1 до 25 книг. Таблицу из поста воспроизвел как понял на основании описания в посте, комментах и патенте.


    Сначала просто статистика по объему: в таблице с авторами — 100k строк, с книгами — ~1.25m строк, в плоской таблице — ~6.5m. По объему, соответственно, 8, 141 и 536 Мб. Если кто-то думает, что место нынче бесплатно, то нет.


    Ну а теперь запросы. Начнем с авторов, у которых в имени есть 5300: select Name from Authors where Name like '%5300%'. 20 записей, никаких чудес, index scan (индекс по имени автора, конечно же, есть, но толку от него здесь пренебрежимо мало). CPU time = 234 ms, elapsed time = 242 ms. Добавим идентификатор: `select Id, Name...: время не изменилось, план выполнения не изменился. Пока все предсказуемо.


    Теперь все то же самое на плоской таблице: select Value from Flat where Value like '%5300%' and Type = 705712. В плане выполнения — index seek с критерием по типу, число прочтенных строк (как и выше) — 100k. Время выполнения тоже не отличается. Добавим идентификатор: select ParentId, Value.... Время выполнения подросло: CPU time = 219 ms, elapsed time = 314 ms, в плане выполнения появился key lookup и join (еще бы, никто же не озаботился покрывающим индексом на ParentId), но пока еще терпимо — неудивительно, все на SSD, памяти много, ресурсов хватает всем и на всё.


    Ладно, давайте посмотрим на книги этих авторов.


    select Authors.Id, Authors.Name, Books.Id, Books.Name, Books.Pages, Books.Year
    from Authors 
        inner join Books on Authors.Id = Books.AuthorId
    where Authors.Name like '%5300%'

    308 строк, CPU time = 218 ms, elapsed time = 765 ms, в плане выполнения — index scan (авторы), index seek (книги по авторам) и key lookup (сами книги). Все предсказуемо, как топор.


    А теперь...


    select AuthorName.ParentId, AuthorName.Value, BookAuthorId.ParentId, BookName.Value, BookYear.Value, BookPages.Value
    from Flat AuthorName
        inner join Flat BookAuthorId on BookAuthorId.Type = 705715 and BookAuthorId.Value = AuthorName.ParentId
        inner join Flat BookName on BookName.Type = 705717 and BookName.ParentId = BookAuthorId.ParentId
        inner join Flat BookYear on BookYear.Type = 705719 and BookYear.ParentId = BookAuthorId.ParentId
        inner join Flat BookPages on BookPages.Type = 705721 and BookPages.ParentId = BookAuthorId.ParentId
    where AuthorName.Type = 705712 and AuthorName.Value like '%5300%'

    308 строк на выходе. CPU time = 1641 ms, elapsed time = 2117 ms. В плане выполнения — два полных скана таблицы и три пары index seek/key lookup (ну и соответствующее количество джойнов). И это у нас всего шесть полей в выводе.


    Снижение риска деградации производительности, говорили они...


    1. UltimaSol Автор
      02.06.2018 18:40

      И здесь вы всё переврали, не повторив таблицу из 5 полей с 3 индексами. Но в этот раз ваш косяк виден как на ладони.

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

      Я тоже сделал табличку с 1048552 книгами (сколько влезло на лист экселя) и 142654 авторами.

      Книги:


      Авторы:


      Также я сделал отчет, но не писал SQL, а набрал нужные поля и сразу вписал условие (перебрал их несколько, пока не получил не менее 300 и не более 1000 результатов):


      Последнее условие вернуло такой результат — 465 строк с авторами по маске, к которой неприменим индекс:


      Все запросы при построении отчета, а их было 6 штук (проверка токена пользователя, поиск отчета, сбор метаданных, выполнение отчета), выполнились за 124.3 мс, из которых 121.3 мс заняло выполнение собственно запроса для отчета.

      Сам запрос получился такой:

      SELECT a225.val v1_225,a217.val v2_217,a223.val v3_217,a219.val v4_217
      FROM test a225
      LEFT JOIN (test r217 JOIN test a217 USE INDEX (PRIMARY)) ON r217.up=a217.id AND a225.id=r217.t AND a217.t=217
      LEFT JOIN test a223 ON a223.up=a217.id AND a223.t=223 
      LEFT JOIN test a219 ON a219.up=a217.id AND a219.t=219 
      WHERE a225.up!=0 AND length(a225.val) AND a225.t=225 AND a225.val LIKE '%aro%'
      


      План его выполнения:


      1. lair
        02.06.2018 18:46

        Но в этот раз ваш косяк виден как на ладони.

        Да? И в чем же он конкретно?


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

        Докажите.


      1. michael_vostrikov
        02.06.2018 19:31

        Вы бы лучше дамп базы скинули. Чтобы все могли повторить тесты на тех же данных.