Глобалы MUMPS: Экстремальное программирование баз данных. Часть 1

Original author: Rob Tweed
  • Translation
  • Tutorial
Примечание переводчика.

Есть интересная технология в мире БД — MUMPS. Этот язык программирования и доступа к данным известен уже несколько десятилетий, отлажен и является взрослой проверенной технологией.

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

Перед вами перевод первой части статьи «Extreme Database programming with MUMPS Globals». Если сообществу он покажется интересным, то последует перевод второй части.


Глава 1. Глобалы: альтернатива реляционному подходу


Истинное сердце технологии MUMPS — механизм хранения данных. Он основан на том, что называется глобальными переменными, или (более популярное название) глобалами (Globals). Глобалы — невероятно простая концепция, однако, при этом невероятно мощная.

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

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

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

Все системы MUMPS и их современные модификации, например, Caché, используют глобалы в качестве основы механизма хранения. Многие современные системы MUMPS и/или расширения предлагают более «привычный» взгляд на ключевые конструкции глобалов. Например, на глобалах можно создать представления (view) которые будут работать как объектная, реляционная или XML база данных. Более того, в теории та же самая физическая база данных на основе глобалов может быть логически представлена и использоваться в одной из этих форм (и даже во всех сразу). В итоге, появилось множество разработчиков, которые не в курсе, что в основе инструментов лежат глобалы. Они не знают, что это такое, как работает и как используется. Этот текст поможет вам узнать этот тайный и, мы надеемся, что вы согласитесь, очень увлекательный мир.

Так что же такое глобалы?

Вкратце, глобал — это постоянный, разреженный, динамический, многомерный массив, содержащий текстовые значения. MUMPS разрешает использовать как сохраняемые на диске (persistent), так и содержащиеся только в RAM многомерные массивы, известные как «локальные массивы».

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

Employee(company,country,office,employeeNumber) = employeeDetails 

и отдельной записью:

Employee(“MGW”,”UK”,”London”,1) = “Rob Tweed`Director`020 8404 3054”

В этом примере элементы данных, из которых состоит информация о сотруднике (имя, должность, номер телефона), прикрепляются друг к другу в сочетании с символом обратного апострофа в качестве разделителя. MUMPS никак не управляет и не контролирует то, как вы организуете свои структуры: нет никакой схемы или словаря данных, описывающего ваши записи. Это предоставляет невероятную гибкость и ускоряет разработку. Вы можете произвольно назначить один или более разделителей данных, которые будут разбивать текстовое значение записи массива на любое количество «полей». Максимальная общая длина одной записи массива зависит от имплементации MUMPS, однако в Caché она составляет до 32k. Длина строки является переменной, и, как вы понимаете, исходя из наличия символа-разделителя, длина отдельных полей — тоже переменная. Это делает глобалы MUMPS очень эффективным механизмом хранения данных (в отличие от таблиц): в файлах MUMPS на диске практически нет места, которое бы хранило пустые, неиспользуемые пространства.

В примере выше запись сотрудника содержится в том, что называется «локальным массивом». Если бы вы вышли из сессии MUMPS, массив бы исчез, так же, как массив PHP после исчезновения страницы или сессии.

А теперь начнем веселье! Чтобы хранить запись сотрудника на диске постоянно, то есть, в виде глобала, просто добавьте "^" перед именем массива:

^Employee(company,country,office,employeeNumber) = employeeDetails 

пример:

^Employee(“MGW”,”UK”,”London”,1) = “Rob Tweed`Director`020 8404 3054” Вот и все!

Чтобы создать такой элемент в глобале, вам нужно использовать команду MUMPS «set»:

set ^Employee(“MGW”,”UK”,”London”,1) = “Rob Tweed`Director`020 8404 3054”

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

s ^Employee(“MGW”,”UK”,”London”,1) = “Rob Tweed`Director`020 8404 3054” 

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

^Employee(“MGW”,”UK”,”London”,1)

Чтобы извлечь значение из глобала и присвоить его переменной обычно используют команду “set”, например:

Set companyRecord= ^Employee(“MGW”,”UK”,”London”,1)

Переменная companyRecord теперь содержит строковое значение: “Rob Tweed`Director`020 8404 3054”

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

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

Чтобы удалить запись из глобала, вы можете использовать команду “kill”:

Kill ^Employee(“MGW”,”UK”,”London”,1)

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

Запомните, что ничто в MUMPS не поддерживает какую-либо методологию дизайна баз данных. Вы можете добавлять инструменты контроля и проверки, которые будут следить за логикой, единообразием и отсутствием ошибок в вашей базе. Это означает, что вы будете выполнять ту работу, которую за вас выполнили бы привычные СУБД. Однако, вы быстро поймете, что можно автоматизировать наиболее часто повторяющиеся задачи и легко управлять базой данных на основе MUMPS

Создание простой многоуровневой структуры

Вы можете использовать несколько размерностей в одном и том же глобале одновременно, например:

^Employee(“MGW”,”UK”,”London”) = 2
^Employee(“MGW”,”UK”,”London”,1) = “Rob Tweed`Director`020 8404 3054”
^Employee(“MGW”,”UK”,”London”,2) = “Chris Munt`Director`01737 371457”

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

Ссылки между разными глобалами должен указывать программист. MUMPS, «из коробки», не предоставляет автоматическую индексацию и не устанавливает перекрестные ссылки.

Для того, чтобы сделать быструю выборку по номеру телефона мы создадим глобал ^EmployeeTelephone, где индексами будут телефонные номера, а значениями индексы глобала ^Employee, указывающими на запись сотрудника:

^EmployeeTelephone(“020 8404 3054) = “MGW`UK`London`1”
^EmployeeTelephone(“01737 371457”) = “MGW`UK`London`2”

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

Пример:
S telNo=”020 8404 3054”
S indexData=^EmployeeTelephone(telNo) S company=$piece(indexData,”`”,1)
S country=$piece(indexData,”`”,2) S office=$piece(indexData,”`”,3)
S employeeNo=$piece(indexData,”`”,4)
S record=^Employee(company,country,office,employeeNo) S employee=$piece(record,”`”,1)

Обратите внимание на использование $piece — функции MUMPS для разделения значения на поля.

Одно из великих свойств MUMPS — вам не нужно ничего объявлять заранее. В SQL-мире изменение структуры данных требует изменения структуры таблиц (ALTER TABLE и т.п.). В MUMPS вы решаете, когда и как создать, изменить и удалять записи в глобале — все это автоматически и динамически контролируется только вами. Вы можете добавить дополнительные индексы и «поля» (pieces) в свои глобалы в любой момент безо всяких объявлений или чего-то подобного. Если вы хотите начать использовать другой глобал, просто начните это делать и он будет создан для вас динамически.

Создание, считывание и удаление записи в глобале

Вкратце, в MUMPS записи в глобалах создаются и извлекаются командой “Set”, и удаляются командой “Kill”.

  1. Создание записи в глобале:

    	Set ^Employee(“MGW”,”UK”,”London”,1)=“Rob Tweed`Director`020 8404 3054”
    	

    Этот код создает индекс в глобале и сохраняет запись на диск.

  2. Считывание записи из глобала

    	Set data=^Employee(“MGW”,”UK”,”London”,1)
    	

    Этот код извлекает элемент из глобала и помещает значение в локальную переменную с названием “data”.

  3. Удаление записи из глобала:

    	kill ^Employee(“MGW”,”UK”,”London”,1)
    	



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

Kill ^Employee(“MGW”,”UK”)

Эта строка удалит все записи всех офисов в Англии

Kill ^Employee

А эта команда удалит весь глобал ^Employee — сразу, навсегда и безвозвратно (если вы не сделали ее бекап).

Обход глобала

Одна из наиболее часто используемых функций — обход нескольких или всех глобалов. Допустим, вам нужно взять все записи сотрудников, чтобы отобразить список, из которого пользователь сможет выбрать одну запись, или сосчитать их. Для этого вам нужно использовать функцию MUMPS $order. Функция $order — это одна из жемчужин MUMPS, позволяющая манипулировать любыми данными, хранящимися в глобалах, с невероятной простотой.

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

Функция $order работает на одном уровне индексации внутри глобала и возвращает значение следующего индекса в выборке, которое существует на этом уровне глобала. Вы можете указать начальное значение, и функция $order найдет следующее значение, которое находится в выбранной последовательности. Чтобы найти первый индекс на указанном уровне, используйте пустое начальное значение (“”). Чтобы найти первый индекс на указанном уровне, который начинается на “C”, используйте начальное значение, которое идет по порядку сразу перед “C”, например, “B~”.
Так, чтобы найти первого сотрудника в глобале:

S company=””
S company=$order(^Employee(company))

Переменная company теперь содержит значение первого индекса company в первой записи глобала ^Employee.

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

S company=$order(^Employee(company))

Тогда переменная company содержала бы пустое значение (“”)
Чтобы получить и обработать все компании в глобале Employee, нужно создать цикл:

S company=””
For  s company=$order(^Employee(company)) quit:company=”” do
. ; сделать что-нибудь с company

Этот код демонстрирует интересные функции лаконичного кодирования MUMPS:
  • Команда For с двумя последующими пробелами устанавливает бесконечную петлю.
  • Quit:company=”” указывает условие выхода из цикла и использует конструкцию, известную как «пост-условие». Эта конструкция говорит «если значение компании пустое, выйти из цикла For». За Quit должно идти два пробела, если после команды идет любая другая команда.
  • “do” в конце строки означает выполнить код, который идет на следующем уровне «точки». “do” будет выполняться на каждой итерации цикла For, пока значение компании не пустое
  • Код, который нужно выполнять в каждом цикле, пишется после одиночной точки. В принципе, любая строка, начинающаяся с точки, формирует подпрограмму, которая выполняется командой “do” в конце второй строки в примере.


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

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

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

s company=””
for  s company=$order(^Employee(company)) quit:company=”” do
. s country=””
.  for  s country=$order(^Employee(company,country)) quit:country=”” do
. . s office=””
. . for  s office=$order(^Employee(company,country,office)) quit:office=”” do
. . . s employeeNo=””
. . . for  s employeeNo=$order(^Employee(company,country,office,employeeNo)) quit:employeeNo=”” do
. . . . s record=^Employee(company,country,office,employeeNo)
. . . . ; сделать что-нибудь с записью

Обратите внимание на то, каким образом мы обозначили уровни «точек», чтобы создать иерархию вложенных подпрограмм. Также, обратите внимание на то, как $order используется для того, чтобы обойти значения всех 4-х индексов глобала.

Прим. переводчика: в Caché для вложенных структур можно использовать фигурные скобки.


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

s company=”B~”
f  s company=$o(^Employee(company)) quit:$e(company,1) ’= ”C” do
. ; сделать что-нибудь с записью

Обратите внимание на функцию $extract (или $e). Она извлекает символ из указанной позиции значения строки: в данном случае первую букву названия компании. Также заметьте способ указания «не равно C»: он использует оператор MUMPS NOT, который записывается одиночной кавычкой (‘).

Этот цикл можно прочесть так:
  • Начальное значение $order — величина перед “C” в последовательной выборке
  • Запустить бесконечный цикл для поиска всех записей компаний в выборке
  • Если первая буква названия компании не “C”, выйти из цикла
  • В противном случае продолжить обрабатывать записи компаний.


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

Проверка существования записи в глобале

Вам часто нужно знать, существует ли конкретная запись в глобале. Для этого вы можете использовать функцию MUMPS $data:

if $data(^Employee(company)) do xxx

Строка читается как «если ^Employee(company) существует, тогда выполнить подпрограмму xxx». Функцию $data можно сокращать до $d.

$data вернет несколько разных значений.
  • Если данные существуют на указанном уровне индекса и нет подузлов, вернется значение 1
  • Если данные существуют на указанном уровне индекса и подузлы есть, вернется значение 11
  • Если данных не существует на указанном уровне индекса, но есть подузлы, вернется значение 10
  • Если данных не существует на указанном уровне индекса, вернется значение 0.


В MUMPS любое ненулевое значение при использовании логического оператора if оценивается как true. Таким образом, первые три значения, возвращенные $data (1, 10 и 11), будут считаться true. Последняя ситуация (нет данных и подузлов) оценивается как false.

В качестве примера рассмотрим следующий глобал:

^test=3
^test(“a”)=1
^test(“a”,”b”,”c”)=2
^test(“a”,”b”,”d”)=3

$data(^test) = 11
$data(^test(“a”,”b”)=10
$data(^test(“a”,”b”,”c”)=1
$data(^test(“b”)=0

Предотвращение ошибок типа «данные не определены»

Если вы попробуете извлечь несуществующую запись из глобала, MUMPS выдаст ошибку этапа выполнения (run-time error), например <UNDEF>. Чтобы избежать этого, вы можете либо использовать функцию $data для проверки существования узла, либо использовать более удобную функцию $get. Это вернет значение глобального узла, если он существует, или пустое значение, если нет. Функцию $get можно сократить до $g

Так, основываясь на примере, который мы использовали в предыдущей секции с $data:

$get(^test) = 3
$get(^test(“a”,”b”)=”” ; поскольку на этом уровне индекса нет данных
$get(^test(“a”,”b”,”c”)=1
$get(^test(“b”)=””
$get(^nonExistentGlobal)=””

Просмотр глобалов

Caché и все остальные системы MUMPS включают в себя способы просмотра глобалов. Самый простой способ — команда ^%G для командной строки, которую вы обнаружите в Caché и некоторых других реализациях MUMPS. Запустите в сессии терминала следующее:

USER> D ^%G

Global ^ Employee

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

Employee()

Перечислит все значения только первого индекса

Employee(“MGW”

Перечислит все записи сотрудников с первым значением индекса MGW

Employee(“MGW”,)


Перечислит все вторые индексы записей сотрудников с первым индексом “MGW”

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

Резюме

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

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

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

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

Продолжение. Часть 2.
Support the author
Share post

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 76

    0
    Опачки! Наконец-то!
    +7
    >в файлах MUMPS на диске практически нет места, которое бы хранило пустые, неиспользуемые пространства.

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

    1й в лоб — создать новую БД — промерджить все глобалы из старой БД в новуюю. Заменить БД. (можно ещё пользоваться встроенным кашевскими средствами — но они как правило способны уменьшать размер только пустых БД)

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

    А вообще — да — MUMPS сила — рад увидеть здесь эту статью, хотя конечно описанные в ней правила — это что-то вроде азбуки или таблицы сложения.

    К читателям вопрос — интересно ли будет посмотреть на реализацию многого описанного в статье — но не из перевода — а из моего личного опыта и кода? То есть могу продолжить и развить тему от своего имени — принципы организации справочников индексов теневого копирования журналирования и прочего…
    0
    В кроме Cache (который стоит непонятных денег — на сайте не указано) реализаций нет?
      +1
      Есть. Можно попробовать open source проект GT.M

      Есть и другие open source, но не такие серьёзные

      С глобалами есть бесплатный качественный продукт с закрытым исходным кодом globalsdb.org/
        0
        Есть GT.M www.fisglobal.com/products-technologyplatforms-gtm Она open source.
        А с Cache и globalsdb не стоит связываться.
        globalsdb — просто key-value. А Cache — мутант: на базе MUMPS прилеплено SQL и ООП.
          +1
          Про globalsdb вы не правы: там не просто key->value, а полноценные глобалы у которых может быть куча индексов.
            –1
            да, я коряво выразился.
            Хотел доести мысль что это «тупое хранилище». без M/MUMPS это как без хранимок и без подзапросов в РСУБД.
              +1
              Оно совсем не тупое. Если бы важные люди из Intersystem меня послушали и прикрутили бы поддержку PHP, то это было бы фантастически круто.

              Иметь многомерное хранилище, выглядящее почти как php-массивы, и работающее почти как оперативная память, но при этом прозрачно всё сохраняющее на винт — это сказка!
                –2
                не тупое было бы — если бы не удалили из него «хранимки». UPD жажда бабла и погубит Cache.

                а со вторым абзацем согласен.
            0
            Вот цитата с сайта globalsdb.org
            Globals DB is a FREE NoSQL Database offering by InterSystems,
            which exposes the powerful multi-dimensional data engine
              –1
              а order и query там оставили? если нет — то это обычный key-value если да — тогда weak multi-dimensional data engine.
                –1
                вы с многомерными разряженными массивами работали хоть раз?
                  0
                  Да order там точно есть реализован методами next и previous в node.js и nextSubscript/previousSubscript в Java и .Net
                0
                вы совсем не знаете что такое каше и за что они берут деньги — так вот деньги берутся только за транзакции, теневое копирование журналирование и технологию ECP (это мультисерверная архитектура — когда вы работаете со многими разбросанными по серверам или миру базами данных в рамках одной среды и синтаксиса не сложнее описанного в этой статье) — без всего этого вы получаете globalsdb — это как mysql в реляционном мире.

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

                  Забыли ещё про сервер приложений с веб-фреймворком и бизнес-аналитикой.

                  То есть получается, за техподдержку и возможность добавлять в приоритетном порядке нужные заказчику фичи тоже нужно платить?
                  А я думал это бесплатно.
                    0
                    Это полезные вещи, но всем ли они нужны?

                    А вот прочитав указанную вами выше книгу становиться ясно что большинству важнее LB и BIT возможности.

                      0
                      Это полезные вещи, но всем ли они нужны?

                      Кому-то не нужна поддержка?
                      Мне, например, не нужен бесплатный продукт (даже со скидкой) без поддержки. Да и поддержка поддержке рознь.
                      А за качество выше уровня «Мы вам перезвоним» и «Приходите завтра» всегда нужно платить.
                        +1
                        Да!
                        «Мне, например, не нужен»
                    0
                    может с терминами ошибаемся (и вы и я) НО:
                    1. транзакции это стандарт языка
                    2. журналирование и так повсеместно
                    3. «Когда вы работаете со многими разбросанными по серверам или миру базами данных в рамках одной среды и синтаксиса не сложнее описанного в этой статье» — тоже есть в стандарте. Но в каше кажется ещё что-то добавили для удобства и скорости.
                    4. Без всего этого получиться просто MUMPS, а globalsdb в SQL мире скорее sqlite

                    Те кто боится глобалов — Каше не выберут они выберут привычный SQL.
                      0
                      А с Cache и globalsdb не стоит связываться.
                      globalsdb — просто key-value.

                      Да если вы боитесь глобалов то с каше и глобалсДБ не стоит связываться.

                      globalsdb — просто key-value. — что вы подразумеваете под «просто key-value»? Ведь так любой SQL-запрос можно обозначить как key а value — это его ответ — тогда любая SQL БД — это просто key — value — по вашей аналогии

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

                        :) Меня тоже сосчитайте.
                          +1
                          мне не совсем понятно что есть хранимая процедура если отвязаться от SQL (по моему субъективному представлению — весь тот код который я пишу это сплошные хранимые процедуры — но могу ошибаться в методологии)

                          А вас посчитаю теперь уже трое! Пора начинать писать:)
                            0
                            В нашем случае — рутины на MUMPS.
                              0
                              кроме них я вообще ничего не пишу (разве что inc-файлы) значит мы сошлись в понимании
                      0
                      > А Cache — мутант: на базе MUMPS прилеплено SQL и ООП.

                      У меня данное сравнение почему-то ассоциируется с ГМО.

                      Простите, а как ещё в рамках единой архитектуры можно прозрачно совместить NoSQL, SQL, ООП, MDX?

                      В Delphi я могу написать так:

                      procedure Fast;
                      begin
                        asm
                          mov eax,1
                          ...
                        end;
                      end;
                      

                      Выходит, Delphi тоже мутант?

                      Многим нынешним реляционным СУБД не хватает такого «ассемблера» внутри себя ради свободы и высоких скоростей, иначе бы движение NoSQL даже и не возникло.
                      Автоматика — это хорошо, но иногда выгоднее перейти и на ручное управление, если есть голова на плечах.
                        0
                        А Cache — мутант: на базе MUMPS прилеплено SQL и ООП.

                        вы так говорите, будто это плохо, знаете ООП там вполне хорошая вещь и постепенно становится еще лучше.
                        в последнем проекте практически не используем SQL хватает своей надстройки над глобалами для быстрых выборок данных.
                        0
                        Есть ещё и MiniM Евгения Каратаева.
                        На изначальную тему могу сказать, что для новичка в области СУБД вообще, не привыкшего втискивать реальность в плоские таблицы со связями, разреженные древовидные структуры, коими являются глобалы, более естественны.
                        +1
                        Еще бы циферки которые расскажут о скорости работы. И сравнение их с парой других продуктов из SQL и NoSQL.
                          0
                          Это ж перевод.
                          А на каком примере вы бы хотели сравнить скорости?
                            +1
                            Цифры есть и на других форумах приводились не раз, например здесь (довольно длинная простыня с примерами вставки и релизации запросов в один и несколько потоков).

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

                            Короткий и элегантный код часто мало коррелирует с высокой скоростью (один из примеров такого сравнения).
                            0
                            Рекомендую ещё и блог автора почитать robtweed.wordpress.com/
                              0
                              Из википедии: Язык MUMPS критики называют провоцирующим ошибки, поскольку:
                              — отсутствует обязательное объявление (декларирование) переменных;
                              — не поддерживаются привычные приоритеты арифметических операций (например, выражение 2+3×10 даёт в MUMPS значение 50);
                              — лишний пробел или разрыв строки может совершенно изменить смысл синтаксической конструкции;
                              — ключевые слова языка не зарезервированы и могут широко использоваться в качестве идентификаторов.
                                0
                                1 — это не только в нём
                                2 — согласен эта особенность но началу сбивает
                                3 — это не только в нём
                                4 — так может не пользоваться такой возможностью

                                  0
                                  какие то странные придирки
                                  — достаточно языков в которых объявление переменных не обязательно и нетипизированных языков так же много
                                  — я работал в нескольких проектах и не часто мне приходилось делать арифиметические операции, и знаете когда вы оформляете все операции в скобках это даже читается лучше, так что никакой проблемы просто не вижу.
                                  — не совсем понятно о чем тут говорится, чаще скорее нехватка пробелов может приводить к проблемам.
                                  — а тут то какие проблемы, и что с того что ключевые слова не зарезервированы из все равно не так много и если бы они были бы зарезервированы это привело бы к большим проблемам вы еще скажите что проблема в том что можно использовать кириллические имена переменных?
                                  –2
                                  You may not realize it, but the majority of us developers have been living a sheltered professional life. Sure, we’ve got that living disaster of a C++ application and that ridiculous interface between PHP and COBOL written by the boss, but I can assure you, that all pales in comparison to what many, less fortunate programmers have to work with each day. These programmers remain mostly forgotten, toiling away at a dead-end career maintaining ancient information systems whose ridiculously shoddy architecture is surpassed only by the tools used to create it. Bryan H lived in such a world for over two years. Specifically, he worked at a “MUMPS shop.”

                                  A Case of the MUMPS — The Daily WTF

                                  P.S. Сам с этим MUMPS ниразу не сталкивался, но после прочтения истории с The Daily WTF даная статья выглядит как троллинг.
                                    0
                                    Сам натыкался на эту статью, и кое что там правильно. Но большая часть это притензии к древнему стандарту MUMPS и, простите, быдлокодерам, которые как известно нагадить могут на любом языке.

                                    Это всё равно что чмырить VB.Net за недостатки Basic в котором не было даже функций.
                                    0
                                    Интересно увидеть вторую часть статьи. Пока действительно не ясно как ЭТО можно использовать, особенно когда один пробел и два пробела это разные конструкции языка =)) (да, работаю с sql)
                                      0
                                      Как это можно использовать я вам напишу — а что такое один пробел и два пробела например вот

                                      s ^P(" ")=«индекс этого значения один пробел а само значение — это строка которую вы сейчас читаете»
                                      s ^P(" ")=«индекс этого значения два пробел а само значение — это строка которую вы сейчас читаете»

                                      строка символов состоящая из одного пробела — это и есть индекс по которому можно получить значение из глобала P
                                      строка символов состоящая из двух пробелов — это и есть индекс по которому можно получить значение из глобала P

                                      про различие пробелов в языковых конструкциях также могу написать но там не сложнее чем в прошлом примере
                                        0
                                        Вышла 2 часть
                                          0
                                          А как это можно использовать посмотреть можно ещё и здесь habrahabr.ru/post/178563/
                                          0
                                          $get(^test) = 3
                                          $get(^test(“a”,”b”)=”” ; поскольку на этом уровне индекса нет данных
                                          $get(^test(“a”,”b”,”c”)=1
                                          $get(^test(“b”)=””
                                          

                                          Похоже, именно из этого языка растаскивают скобочки на смайлики.
                                          А если серьёзно, то в третьей строке не 2 должно быть?
                                            0
                                            Если брать во внимание определение из примера SET ^test(“a”,”b”,”c”) = 2
                                            То $Get(^test(“a”,”b”,”c”)) вернет 2
                                              0
                                              А как бы сделать, чтобы движок форума кавычки не менял по своему усмотрению? Не совать же тег
                                              <pre>
                                              куда надо и не надо.
                                              Напрягает самодеятельность типа той, которая в примере RoiS получилась.
                                              0
                                              В Альфа-Банке достаточно долго эксплуатировалась система частных вкладов и касса, написанные на MUMPS. Поделие фирмы esc/m. Любимая поговорка: «Глобали — глюкали». У мумпс очень хреновая связь с внешним миром, в нашем случае это была отгрузка в DBF
                                                +2
                                                Неужели все банки экономят на специалистах? В сбере оракл роняют, в альфе умудряются глобали сглючивать…
                                                  +1
                                                  В Альфе система полностью обслуживалась специалистами ESC/M и обычным инженерам ИТ залазить в неё запрещалось под страхом анальных кар. С одной стороны правильно, но с другой стороны — иногда она всё-таки падала, в основном, после внедрения разного рода обязательных апдейтов, а круглосуточной поддержки не было. Москва просыпалась, и тогда что-то можно было сделать.

                                                0
                                                Довольно много пишу на Cache (правильней говорить на MUMPS?) по работе. Ощущения, конечно, противоречивые: с одной стороны язык очень лаконичный и глобалы — это, пожалуй, действительно круто! Но отсутствие элементарных вещей (типа приоритета математических операций, о котором тут говорили выше) и IDE из доисторических времен, могут повергнуть в легкий шок человека, привыкшего к современным средам разработки и ЯП.
                                                  0
                                                  > Довольно много пишу на Cache (правильней говорить на MUMPS?) по работе.

                                                  Правильно говорить «много пишу для Caché на COS» так же, как «много пишу для Oracle на PL/SQL».
                                                    0
                                                    А что вас не устраивает в IDE и почему же с доисторических эпох, студия в Cache потихоньку но развивается, большой минус правда есть в том что она только под Windows.
                                                      0
                                                      — отсутствие рефакторинга
                                                      — автодополнение кода, которое вроде бы есть, но реализовано слабо, чисто «для галочки». Во множестве ситуаций не работает и дело тут вовсе не в том, что язык с необязательной типизацией
                                                      — практически нет синтаксического контроля, о подсказках к ошибкам вообще речи не идет
                                                      — нет форматирования кода
                                                      — примитивный отладчик

                                                      Да много чего, я ведь не пытаюсь никого убедить, что «Cache — это плохо!». Я Вас по форуму на sql.ru знаю как фанатика фаната этих технологий, так что все понимаю. Есть вещи в Cache (и в самой Studio, как среде разработки), которые мне тоже нравятся.
                                                        0
                                                        При использовании конструкции вида #Dim var As Type =… автодополнение свойств и методов объекта работает вполне нормально.
                                                          0
                                                          Да, я знаю про конструкцию #dim и стараюсь почаще ее использовать, я специально отметил, что проблема автодополнения не в мягкой типизации, а в том что оно в принципе «не видит» некоторых переменных или отваливается после «do» (до первой точки), к примеру.
                                                          0
                                                          — в 2013 студии есть зачатки рефакторинга, переопределение свойств методов и т.д. существуют уже давно
                                                          — проблема с автодополнением восполнена с помощью #dim, а если не необязательная типизация то что может быть проблемой для этого, особенности самого языка
                                                          — насчет синтаксического контроля это вы зря, он вполне себе нормальный, тем более что ошибок синтаксиса нет так то много для для каше они и объеденнены в одну ошибку SYNTAX, в студии есть проверка на UNDEFINED, (в настройках студии посмотрите как включить)
                                                          — есть некоторое форматирование при вводе, например при открытии фигурных скобок, а то что нет возможности отформатировать любой код как это делает тот же netbeans и другие, да это порой неудобно
                                                          — насчет отладчика сказать мне что то сложно, пользовался пару раз на поиграться, да и не вижу как его можно улучшить потому как приложения разные (консольные, веб, веб-сервисы) и сложно вообще понять как можно отлаживать удобнее сам язык достаточно предлагает средств для отладки кода. Одно время мне нравилось использовать сбор стека в каше через LOG^%ETN, так я мог просмотреть стек вызовов до нужного мне места и просмотреть как шла нужная переменная через эти вызовы. а так я чаще работаю на своем сервере где веду разработку и просто делаю вывод отладочной информации прямо на страницу приложения.
                                                      +1
                                                      Честно говоря не очень проникся. Если отбросить оригинальный синтаксис, то остается по сути обычная бессхемная не реляционная база. Не увидел здесь что-то сильно отличное от MongoDB, к примеру.
                                                        0
                                                        СУБД и не является реляционной ни в коей мере, она по сути многомерная key-value СУБД, отличий возможно и нет, но mumps много старше и проверена годами.
                                                        0
                                                        Вот этот код вызывает вопросы:
                                                        s company=”B~” f s company=$o(^Employee(company)) quit:$e(company,1) ’= ”C” do . ; сделать что-нибудь с записью
                                                        Сначала вы пишите, что стоит задача найти все записи, начинающиеся с «С». А после кода такой комментарий:
                                                        Если первая буква названия компании не “C”, выйти из цикла

                                                        Т.е. при первом же несовпадении происходит выход из цикла (и судя по коду, это верно).
                                                        Я чего-то не понимаю?
                                                          +1
                                                          Поскольку автор англоязычен, то он предполагает, что имена компаний состоят из ASCII символов. Код тильды — 126. 127 код у DEL (это непечатный символ).

                                                          Иными словами для любого англоязычного справочника верно, что после выражения начинающегося с «B~» идёт, буква C или буквы C нет вовсе.

                                                          Таким образом цикл работает до тех пор пока в качестве первой буквы ему не попадётся любая иная буква, чем C.
                                                            –1
                                                            Таким образом цикл работает до тех пор пока в качестве первой буквы ему не попадётся любая иная буква, чем C.

                                                            Именно. Такой цикл завершится при первом же несовпадении и не найдутся ВСЕ записи, начинающиеся с «С».
                                                              0
                                                              там отсортировано, поэтому пойдут все записи, начинающиеся с «С», а как только наткнётся на не начинающуюся — значит больше нужных и нет.
                                                                +1
                                                                Это логично предположить, потому что индекс перед циклом выставляется в «B». Только откуда берется эта сортировка, особенность движка?
                                                                  0
                                                                  да, всё отсортированно по индексам массива.
                                                                    0
                                                                    А, вот нашел ключевую фразу:
                                                                    Эта возможность начинать и прекращать обход глобала с любого конкретного индекса и на любом уровне вложенности индексов является уникальной функцией глобалов MUMPS.

                                                                    Вообще, кто работает с highload sql-базами знает, что сортировка — дорогая операция…
                                                                      0
                                                                      В MUMPS хранение данных так постоено, что бы это было быстро. А вот «медленной» была бы операция вывода с сортировкой не по значениям индексов, а по значениям данных. Если программист не озаботился созданием соответствующего «индекса».

                                                        Only users with full accounts can post comments. Log in, please.