Pull to refresh
7
0
Алексей @UltimaSol

Разработчик

Send message

Постарался исправить перечисленные моменты

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

Вон оно как. Казалось бы, кого волнуют изыскания какого-то там ещё одного строителя конструктора… Прямо бросил тень на весь мир разработчиков СУБД.
Что вы воспринимаете как критику? Я уберу или перефразирую.

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

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

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

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

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

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


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

Это паранойя.

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

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

Вы это серьезно — неправильная настройка системы?
Статья не ищет ответа на вопрос «как правильно настроить систему» и не агитирует переходить на новую систему, а исследует поведение различных решений.

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

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

У конструктора есть индекс и по этим 12.5 млн, поэтому он сразу найдет нужные записи и обработает их — также всего одну штуку. Это выйдет заметно быстрее.

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

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

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

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

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

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

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

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

В конструкторе то же самое — мы находим те 12.5 млн записей, а среди них ищем одну опять по индексу — получается очень быстро (но дорого в плане пространства!). Когда же под выборку попадают десятки тысяч записей, то конструктор будет метаться среди них, собирая данные с диска и тратя драгоценное время.

Это всё и показано в таблице.

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

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

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

это несколько минут на изучение сторонним специалистом и один запрос в БД.

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

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


Список чеков


Создание чека — вносим только сумму, остальное заполнено


Отчет по чекам


Результат выполнения отчета


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

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

Разумеется, штатными средствами Маженты или опубликованными до этой статьи. Ваши скрипты миграции мы в этом случае учитывать не можем.
Хорошо, я нашел таблицу eav_entity_int, в которой есть все поля и индексы.
Теперь проверим пункты 4 и 5 опросника для этой таблицы: покажите как в этой системе описаны типы, используемые для создания других типов и их реквизитов, которые описывают наборы связанных данных. В этой же таблице или любой другой, удовлетворяющей пунктам 1 и 2.
Время хранится серверное для всех timestamp.
У конструктора есть несколько внутренних контекстных значений, доступных по именам: пользователь, его ID, временной сдвиг относительно сервера и другие. Их можно использовать в построителе запросов или сохранять в базе при регистрации чеков, например.
Если нужно, в запросе будет учтён сдвиг — прибавлен ко времени для приведения серверного времени к локальному пользовательскому. Сервер вычислит это, выполняя запрос.
Вы про это спрашивали?
Рисунок в начале статьи, где показано, что на начальном этапе развития системы, когда в ней немного данных, запросов и пользователей, накладные расходы в несколько раз превышают расходы в традиционно построенной базе данных
Сам запрос целиком и полностью будет выполнен на стороне БД (а конструктором только правильно сформирован)
Возьмите EAV Entity и проверьте по опроснику.

Взял здесь, проверяю, несмотря на очевидно иное предназначение этой таблицы, нежели в описанном мной конструкторе.
Итак,
1. Все данные хранятся в одной таблице (см. также п.3.), содержащей как минимум следующие поля: ID, Parent ID, Type ID, Value
Структура и индексы
        /**
         * Create table 'eav_entity'
         */
        $table = $installer->getConnection()->newTable(
            $installer->getTable('eav_entity')
        )->addColumn(
            'entity_id</b>',
            \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
            null,
            ['identity' => true, 'unsigned' => true, 'nullable' => false, 'primary' => true],
            'Entity Id'
        )->addColumn(
            'entity_type_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            null,
            ['unsigned' => true, 'nullable' => false, 'default' => '0'],
            'Entity Type Id'
        )->addColumn(
            'attribute_set_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            null,
            ['unsigned' => true, 'nullable' => false, 'default' => '0'],
            'Attribute Set Id'
        )->addColumn(
            'increment_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_TEXT,
            50,
            ['nullable' => true, 'default' => null],
            'Increment Id'
        )->addColumn(
            'parent_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_INTEGER,
            null,
            ['unsigned' => true, 'nullable' => false, 'default' => '0'],
            'Parent Id'
        )->addColumn(
            'store_id',
            \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            null,
            ['unsigned' => true, 'nullable' => false, 'default' => '0'],
            'Store Id'
        )->addColumn(
            'created_at',
            \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
            null,
            ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT],
            'Created At'
        )->addColumn(
            'updated_at',
            \Magento\Framework\DB\Ddl\Table::TYPE_TIMESTAMP,
            null,
            ['nullable' => false, 'default' => \Magento\Framework\DB\Ddl\Table::TIMESTAMP_INIT_UPDATE],
            'Updated At'
        )->addColumn(
            'is_active',
            \Magento\Framework\DB\Ddl\Table::TYPE_SMALLINT,
            null,
            ['unsigned' => true, 'nullable' => false, 'default' => '1'],
            'Defines Is Entity Active'
        )->addIndex(
            $installer->getIdxName('eav_entity', ['entity_type_id']),
            ['entity_type_id']
        )->addIndex(
            $installer->getIdxName('eav_entity', ['store_id']),
            ['store_id']
        )->addForeignKey(
            $installer->getFkName('eav_entity', 'entity_type_id', 'eav_entity_type', 'entity_type_id'),
            'entity_type_id',
            $installer->getTable('eav_entity_type'),
            'entity_type_id',
            \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
        )->addForeignKey(
            $installer->getFkName('eav_entity', 'store_id', 'store', 'store_id'),
            'store_id',
            $installer->getTable('store'),
            'store_id',
            \Magento\Framework\DB\Ddl\Table::ACTION_CASCADE
        )->setComment(
            'Eav Entity'
        );
        $installer->getConnection()->createTable($table);



Вижу entity_id, entity_type_id, parent_id
Упс… Value не нашел.
Какими именно?
Что конструктор имеет накладные расходы и в простейших случаях производительность ниже, я заявляю на иллюстрации и в самой статье.

Тексты и планы всех-всех запросов нужны?

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

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

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

Вот и славно. Никто так не делает, как вы сами подтвердили.
А вся разница как раз в этом:
Индекс логически как бы разбивает строки на под-таблицы, но технически это обычное ускорение выборки по условию.


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

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

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

В чем проблема с семантикой? В любом случае ссылка делается по ID, а его запись всегда является типом.
«костыль» — это StoreID в Magento, если я правильно понимаю это как ID магазина. Вот это действительно адский ад.

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

Доказать вашу правоту очень просто: берете опросник, любой аналог и за 5 минут кровавого копи/пейста показываете идентичность.
Почему не выполняется? Индекс в системе на аналогичных полях есть? Есть. В этих таблицах могут хранится значения атрибутов? Могут.

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

Одна система — один проход опросника.

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

Даже первые два пункта не пройдены: нет ссылки на систему, нет её структуры, нет её индексов. О чем говорить?

И это мы еще не добрались, что в этой системе описаны типы, используемые для создания других типов и их реквизитов, которые описывают наборы связанных данных (связанных как раз через ссылки на тип или объект).
Знаю. Стоит у меня на компьютере. Там добавлен индекс на «Type ID + Value». По аналогии с другими таблицами.

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

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

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

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

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

Да, может. Это был я, например. Только я еще выкинул всё остальное ненужное и добавил что-то от себя. Получился совсем другой продукт.
Дело в том, что только добавление этого индекса ничего принципиально не решит и не является единственным отличием.
нет в таблицах для товаров, но есть в других
А слова есть в других вы типа не заметили? Там вообще-то тоже EAV. У вас нигде нет требования, чтобы это было только для товаров.

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

Вот на это я хочу ответить развернуто. Укажите, пожалуйста, какой минимальный объем можно уже считать большим?
1
23 ...

Information

Rating
Does not participate
Location
Москва, Москва и Московская обл., Россия
Date of birth
Registered
Activity