Comments 78
По этой же причине, например, стоит изучить язык Rust. Практической пользы прямо сейчас мало, а концепты, которые реализованы в языке – пустые типы, типажи, владение и так далее, самый передовой уровень.
невозможности на лету добавить атрибут для конкретного факта.
Я правильно понимаю, что вы пытаетесь добавить колонку в таблицу в реляционной СУБД? А почему эта операция занимает столько времени и с такими сложностями (нужно выгнать пользователей и ждать десятки минут)? Или "атрибут" и "факт" имеют какие-то другие смыслы в данном контексте?
А при каких размерах таблиц (кол-во записей, размер в байтах) данный эффект (ждать десятки минут) возникает?
А при чём тут ERP? Вернее, при чём тут таблицы и колонки RDBMS, если некая коммерческая ERP добавляет новый атрибут к объекту? Это вопросы к авторам "коммерческой ERP" — что за логику они реализовали на десятки минут и почему нужно выгонять пользователей. Уверяю вас, такого же эффекта разрабы ERP могли добиться и на NoSQL-базах, и на файловой системе, и, если постараются, в оперативной памяти и при гораздо меньших объёмах данных. Вы как-то слишком широко обобщили свой негативный опыт с ERP сразу на все РСУБД.
Стесняюсь спросить, но не могу не уточнить, а вы с какой конкретно RDBMS имели дело и каким образом добавляли атрибут к объекту колонку к таблице? Очень хочется узнать всё-таки, какая из RDBMS так тормозит на ALTER TABLE
.
Посмотрел на MySQL (10.1.34-MariaDB) — действительно, есть ощутимые задержки при изменении структуры таблицы (взял навскидку таблицу с самым большим кол-вом строк и самую большую по объёму данных из имеющихся на локалке):
table: report_viewed_product_index
rows: 1,384,812
size: 57,245,696 bytes
ALTER TABLE report_viewed_product_index ADD habrotest varchar(100) NULL;
time: 18.177s
table: sales_order_item
rows: 185,011
size: 118,161,408 bytes
ALTER TABLE sales_order_item ADD habrotest varchar(100) NULL;
time: 9.271s
Полагаю, что вам ещё повезло, что при миллиарде записей по паре мегабайт на каждую ваш процесс уложился в полчаса. Сочувствую, что вам приходится иметь дело с такими приложениями.
В системах NoSQL я могу к одному конкретному объекту добавить атрибут, не затронув остальные, и это очень круто, а в РСУБД нужно добавлять колонку в таблицу.
вам нужно на курсы какие-то сходить, начальные. не надо так делать, за такое и побить могут
структуры таблиц крупнейших ERP наверно с 80х не менялись.
если так хочется конкретики, ну есть она у меня. конкретно сейчас работаю со spark на датафреймах. как и каша можно использовать обычный sql, есть обычный жава/скала синтаксис. в отличие от каши там полноценный оптимизатор и относительно декларативная работа с датафреймами. т.е. фреймворк и его оптимизатор решает как и в какой последовательности полезть к данным. там все кластерные прибабахи сразу из коробки. причем датафреймы не лезут за данными сразу, т.е. если в каше код выполняется как написано, датафреймы в спарке не тянут данные пока клиент не потребовал нечто, что требует результат. т.е. я могу задефайнить датафрейм, отправить в «процессор», который задефайнит фильтры, агрегаты, потом отправить в другой «процессор», который с чем-то заджоинит, но за данными оно полезет только когда я попрошу первые строки. и оптимизатор будет оптимизировать итоговый датафрейм, со всеми фильтрами, джоинами и прочей логикой разбросанной по разным классам. при этом это все в jvm — запросто прилаживается любые жава либы, начиная с ML. при этом это фреймвок, ему относительно пофигу как данные хранятся. оно работает и на файликах хадуп и на монге, игнайт, kudu.
вообщем совершенно иной уровень, чем каша. и этот уровень все равно не дотягивает до того что у меня было в оракле. побеждает лишь ценой.
Проблема скорее в том, что хранение и обработка — это действительно, совсем два разных мира, два разных детства. Факты мы храним или неструктурировано (тексты, картинки, видео и т.п.), или структурировано, и тогда здраствуй, дедушка Кодд с исчислением предикатов, сущностями, связями и всем тем, что мы называем РБД. А в обработке мы вынуждены так либо иначе жить в объектной парадигме (даже если не применяем ООП, всё равно по факту даже ячейка памяти — это тоже объект).
Задача ORM выглядит как пустяк, но в настоящий момент, насколько мне известно, её никто и нигде целиком нормально не решает. Сделать вид и показать на игрушечных примерах, что она решена — легко, но что нам в кровавом энтерпрайзе с этого вида?
на лицо противоречиеНалицо.
Извините.
Caché — безусловно достойная и интересная тема. Но я как-то услышал и перенял полезную привычку называть эту штуку фразой «мифическая СУБД Кашé».
Было бы любопытно услышать от народа соображения, почему эта, как декларируется, фантастически прекрасная вещь всё никак по-настоящему не взлетает.
… это вынуждает программистов постоянно ликвидировать семантический разрыв с помощью неуклюжего промежуточного слоя данных. И, тем самым, вызывать у себя внутреннее дихотомическое напряжение, системный дискомфорт и отладочную бессонницу.Кашé тоже, похоже, не убирает неуклюжий промежуточный слой, а лишь маскирует его синтаксическим сахаром. На детских примерах всё получается красиво (на Джанге, кстати, даже ещё красивее), а на взрослых эти самые упомянутые дихотомическое напряжение и системный дискомфорт должны приходить с той же силой и в том же объёме.
Переубедите меня, пожалуйста, если я не прав.
спасибо!
То ли затея страдает от ошибок в маркетинге, то ли есть какой-то врождённый порок реализации, то ли оно всё есть один большой хитро спрятанный концептуальный просчёт.
Проще всего свалить всё на маркетинг/продвижение, но есть смысл подумать и над последними двумя пунктами.
Это как TypeScript называть синтаксическим сахаром для JavaScript или Kotlin – сахарком для Java ;)
А вот Kotlin — это не суперсет от Java, а самостоятельный язык, потому что компилируется в JVM-байткод, а не в Java (или и вовсе в какой-нибудь Javascript, кстати; как я понимаю, там и Kotlin-native где-то в работе).
Как только чувствуем ограничения в производительности (в Caché есть встроенные средства профилирования), дополняем объектными индексами и прочими инструментами расшивки узких мест.
При этом модель, предложенная Коддом имеет строгие математические основы и в состоянии описать любые данные.
Прикрываясь «строгой математической основой», необходимо её использовать. А что-то примеров строго соответствия реляционной модели по Кодду среди РСУБД не видно. Как-то все своими «граблями» обходятся.
Я говорю о сравнении «мёртвых данных» в таблицах с живыми объектами в программах. И хочется про это поговорить.
Я говорю о разнице между манипуляцией данными и общением объектов между собой. Как хранятся данные физически — это из другой оперы.
То есть self.att.run_obj_method("%DeleteId", [id]) читаем как «эй дружок тебя не взяли в космонавты». И он что-то там делает по самоудалению из хранилища. Может метку поставит "«здесь был Вася» или «отправит сообщение другому объекту — регистратору несостоявшихся космонавтов: внеси меня в свой список». Это уже неважно. Структуры данных так не делают – они же записи в таблице, а не объекты.
А если продолжить и вспомнить про архитектуру хранения в современных СУБД?
Разработчики СУБД, чаще всего используют разновидности B-дерева
В этих перипетиях с «мешками с байтами» есть приятное исключение – СУБД Intersystems Caché
Хранить можно все типы данных, включая символьные и бинарные потоки.
Так каким образом она это все хранит-то?
Самая важная магия в строчке: self.att.run_obj_method("%Save",[])
Именно так мы имеем возможность сохранять объекты прямым указанием и без необходимости применять дополнительные библиотеки и каркасы/фреймворки, вроде вездесущих и неприглядных ORM.
Чем это отличается от ORM? Я бы даже сказал, чем это отличается от ActiveRecord?
Итак, на этих примерах видно, что не обязательно думать одновременно о своей модели данных и её табличной схеме хранения.
Эти примеры ничем не отличаются от кода, использующего ORM. С ORM, пожалуй, код выглядит даже чище и понятнее.
Осталось добавить участника в мероприятие
haJS.addAttendee(att.att)
Список участников хранится в самом объекте Event? Как получить информацию, в каких мероприятиях участвует участник?
Так каким образом она это все хранит-то?
Как и всё мейнстимовые СУБД — разновидность B-деревьев. Только не прячет этот факт за фасадом SQL, а активно использует на благо разработчиков.
Чем это отличается от ORM? Я бы даже сказал, чем это отличается от ActiveRecord?Фасадом. Фактически ORM отсутствует для разработчика приложения. Я люблю Ruby, но это было так давно… А сегодня только так.
Список участников хранится в самом объекте Event? Как получить информацию, в каких мероприятиях участвует участник?
Участников этого мероприятия — да, в Event. Ссылкой на Attendee. Этот кусочек кода для примера и взят приложения, где один и то же участник посещает разные Event. Этой части в примерах нет, а там объект-участник знает в каких он мероприятиях участвовал. А внутри Event может быть в разных ролях: слушателем, докладчиком и комментатором.
Только не прячет этот факт за фасадом SQL, а активно использует на благо разработчиков.
В чем это выражается? В коде примеров нет никаких отличий от кода с SQL ORM.
Фактически ORM отсутствует для разработчика приложения.
Вот код с ActiveRecord:
class User extends ActiveRecord
{
...
}
function createUser()
{
$user = new User();
$user->login = 'TestUser';
$user->save();
}
Логически ничем не отличается от примеров из статьи. Но используются средства языка программирования, а не магические константы.
Этой части в примерах нет, а там объект-участник знает в каких он мероприятиях участвовал.
То есть в Event хранится список Attendee, а в Attendee список Event, и это 2 разных массива, которые можно менять независимо?
В чем это выражается? В коде примеров нет никаких отличий от кода с SQL ORM.
Сознательно отказался от примеров с SQL. Если интересно, посмотрите примеры в большом обзоре про глобалы 1, 2, 3.
Если будет много вопросов, подумаю над дополнительным материалом для публикации.
Вот код с ActiveRecord
Отличается. Если я правильно пониманию, ActiveRecord работает только с кортежами.
Магических констант что-то не припомню :) Два языка и привязки между ними. При использовании только ObjectScript всё ещё проще.
То есть в Event хранится список Attendee, а в Attendee список Event, и это 2 разных массива, которые можно менять независимо?
Да, два разных «массива» (это не массивы). Дальше как разработчику заблагорассудится. У меня зависимые объекты (в примере этой части нет).
И спасибо за вопросы! Хорошая мне тренировка для изучения новых тем и хабр-разметки :)
Если интересно, посмотрите примеры в большом обзоре про глобалы
Там это точно так же спрятано за специальным языком.
Отличается. Если я правильно пониманию, ActiveRecord работает только с кортежами.
ActiveRecord работает с объектами языка программирования, с обычным ООП. В моем примере User
это класс, как и в вашем.
Магических констант что-то не припомню
att.run_obj_method('какая-то строка')
— "какая-то строка" это и есть магическая константа. С точки зрения языка это константы, а на самом деле запускают разную логику.
Да, два разных «массива»
То есть технически возможна ситуация, когда Attendee находится в списке участников объекта Event, но этого объекта Event нет в списке событий объекта Attendee. Ну тогда получается это обычная NoSQL со всеми их недостатками.
Реляционные базы выбирают в том числе и из-за контроля целостности данных. Даже если не поставить внешние ключи для промежуточной таблицы attendee-event
(что иногда делают по техническим причинам), база все равно не даст создать запись без указания attendee_id
или event_id
.
Там это точно так же спрятано за специальным языком.
ActiveRecord работает с объектами языка программирования, с обычным ООП. В моем примере User это класс, как и в вашем.
Это про одно и тоже. Поэтому будем есть этого слона по частям.
ActiveRecord основан на соглашениях и специальном языке. Он вводит свой DSL. Как минимум для миграций это нужно.
Примеров объектов на ActiveRecord, окромя кортежей, не обнаруживаю. Скажите где посмотреть?
att.run_obj_method('какая-то строка') — «какая-то строка» это и есть магическая константа. С точки зрения языка это константы, а на самом деле запускают разную логику.
По мне странно называть всё 'что в кавычках' константами. Обоснуете?
IMHO, вполне обосновано — inline константа. Как анонимные функции, только анонимные константы. Я в Magento с этой бедой постоянно сталкиваюсь. Написано 'status' и пойди пойми, этот 'status' в этом месте то же самое, что 'status' в другом методе другого класса или только названия одинаковы. А если написано:
namespace Vendor\Project\Module\Path\To\Class;
class Order {
const STATUS='status';
}
то и вопросов возникает гораздо меньше.
Реляционные базы выбирают в том числе и из-за контроля целостности данных. Даже если не поставить внешние ключи для промежуточной таблицы attendee-event (что иногда делают по техническим причинам), база все равно не даст создать запись без указания attendee_id или event_id.
Именно так и написал. Хотите целостности — получите хоть в объектном, хоть в реляционном виде. Нет такой потребности — на здоровье.
ActiveRecord основан на соглашениях и специальном языке. Он вводит свой DSL.
Не знаю, что вы под этим подразумеваете, ничего он такого не вводит. Если он что-то и вводит, то только то же самое, что и Cache.
Примеров объектов на ActiveRecord, окромя кортежей, не обнаруживаю. Скажите где посмотреть?
Я привел пример с созданием пользователя. Где там кортежи?
Вы уходите от ответа на вопрос. Чем конкретно ваш код отличается от моего кода с ActiveRecord? По-моему, кроме названий он не отличается ничем.
По мне странно называть всё 'что в кавычках' константами. Обоснуете?
Всё, что в кавычках — это по определению "строковая константа", другое название "строковый литерал".
Именно так и написал. Хотите целостности — получите хоть в объектном, хоть в реляционном виде.
Вы написали, что там 2 разных массива. Как гарантируется целостность? Конкретно для этого примера, как гарантируется отсутствие ситуации, когда в event.visitors пользователь есть, а в его свойстве attendee.events такого события нет?
В статье вы говорите, что Cache лучше подходит для разработки, чем реляционные БД. Ссылочная целостность это одно из качеств реляционной БД. Сравнивать их без учета этого нет смысла.
В комментариях вы высказываете необоснованные утверждения и уходите от ответов на вопросы. Складывается впечатление, что вы не разбираетесь в теме. Статья конечно рекламная, но техническим моментам можно было больше внимания уделить.
Обманное впечатление :) Верно другое – разбираюсь в теме. ObjectScript для меня новый язык.
Про отличную документацию и сообщество написал выше. Если приглядеться к фамилиям, то каждый 10 будет нашим соотечественником (но это не точно).
Про REST «из коробки» напишу как-нибудь поподробнее и с примерами.
И на дворе уже 2019 год наступил ;)
суть современных реляционных субд — оптимизатор. т.е. сегодня план один, завтра таблички подросли и оптимизатор перестроит план. у cache же код не декларативный, доступ к данным зашивается насмерть. никакого смысла возвращаться в 90е с такой технологией нет.
никакого смысла возвращаться в 90е с такой технологией нет.
подставь свой вариант :)
Сегодня всё сильно другое. Если включить свежий незамутненный прошлым взгляд, а себя переступить/обновить очень боязно, наверное, то можно увидеть прогресс. Я, например люблю среду Оберона, но обжёгся на Дельфи. С++ меня долго ломал и, наверное к нему не вернусь. А у сегодняшнего Каше, по сравнению даже с тем что было 7-10 лет назад, резкий прогресс. И любовь его настоящих разработчиков, как бы пафосно это не звучало. Я вот и решил разобраться сам, отчего такие полярные мнения.
Пока вывод такой, кто не работал вплотную с Caché последние 5 лет, ничего по делу сказать не могут. А резкий рост новых разработчиков и успех на рынке говорят сами за себя.
Чуть выше Михаил michael_vostrikov устроил мне вполне качественный детальный допрос/разнос с примерами живого кода. :)
Ну что же вы сразу "разнос") Ничего такого не хотел, просто поинтересовался. Может слишком настойчиво, так как не было тех ответов, которые я ожидал.
А дальше? В первом приближении разница в именовании. Объект оживает сам. А в $user->login = 'TestUser' что-то странное. У меня по объектно-православному att.new(«Аким»). Но после вопроса уверенность пропала))
Довериться Кодду или своим объектам?