воскресенье, 29 мая 2016 г.

MUMPS: Выборки по индексу

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

По своему строению индексные структуры дают возможность тем или иным способом указав искомое значение атрибута получить ноль, одно или несколько идентификаторов записей или значения других атрибутов записей. Индексные записи отображают индексируемое значение на один или несколько идентификаторов. Поэтому операции выборки могут быть нескольких видов:
  • Проверка существования в индексе заданного значения атрибута.
  • Выборка значений атрибутов для заданного диапазона значений атрибута.
  • Выборка значений идентификаторов для заданного значения атрибута.
  • Выборка значений идентификаторов для заданного диапазона значений атрибута.
Структурно строение индексных записей схематично выглядит как:
^Ind("IndName",IndValue,id)=""
При этом первой задаче соответствует применение операции $d() для проверки существования узла, второй соответствует применение $o() для выборки значений IndValue, третьей - операция $o() для выборки набора id при фиксировании значения IndValue и для четвертой - либо операция $q() либо два вложенных друг в друга цикла - один по IndValue, второй - по id.

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

Выборка диапазона значений атрибута
SelectFigures(from="",to="")
 i from'="" s from=$o(^Index("Figure",from),-1)
 i to'="" s to=$o(^Index("Figure",to))
 f  s from=$o(^Index("Figure",from)) q:(from=to)!(from="") d
 . w from,!
 q
Здесь функция SelectFigures выбирает различные значения атрибута Figure от from до to включительно. Если аргумент опущен, то считается пустой строкой и производится выборка с открытым концом: если from не указан, то выдаются все с начала, если to не указан, то выдаются все до конца. В реализации функция корректирует значения from и to для того чтобы цикл for был применим к всем комбинациям.

Выборка идентификаторов по значению атрибута
SelectByFigure(Figure)
 n id s id=""
 f  s id=$o(^Index("Figure",Figure,id)) q:id=""  d
 . w id,!
 q
Выборка значений идентификаторов для заданного диапазона значений атрибута с использованием вложенного цикла:
SelectByFigures1(from="",to="")
 n id
 i from'="" s from=$o(^Index("Figure",from),-1)
 i to'="" s to=$o(^Index("Figure",to))
 f  s from=$o(^Index("Figure",from)) q:from=to  d
 . s id="" f  s id=$o(^Index("Figure",from,id)) q:id=""  d
 . . w id,!
 q
Выборка значений идентификаторов для заданного диапазона значений атрибута с использованием итераций по $q:
SelectByFigures2(from="",to="")
 n ref
 s ref=$na(^Index("Figure",from))
 f  s ref=$q(@ref) q:$s(to="":ref="",1:$qs(ref,2)]]to)  d
 . w $qs(ref,3),!
 q
Здесь в качестве условия прекращения цикла стоит сложное условие: в зависимости от непустоты хвоста to либо продолжать пока ссылка не станет пустой, либо учитывать порядок индексной сортировки.

Во всех приведенных случаях есть возможность указывать направление выдачи результата - по возрастанию или убыванию значений атрибутов и / или идентификаторов. Для этого можно либо явно указать в необязательном аргументе функций $o и $q направление траверса либо передавать его из необязательного параметра функций SelectBy... Приведенные функции выдают в направлении возрастания значений в отношении индексной сортировки. Для полноты и строгости изложения также следует отметить, что возможность задать направление выборки для функции $query может поддерживаться не всеми MUMPS системами, для которых разрабатывается программа, и такую возможность необходимо проверить по документации. В частности, система GT.M такой параметр не поддерживает.

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

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

Примечание - в англоязычной литературе и справочниках описанные выборки могут называться так: 2, 4 - range scan, 1, 3 - index scan.

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

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

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

Для демонстрации примера выборки в указанную переменную:
indselect ;
 n Search
 s Search=$na(^TempResult($j))
 d SelectByFigure("квадрат",Search)
 w "Результат поиска:",!
 zw @Search
 k @Search
 q
SelectByFigure(Figure,Result)
 n id s id=""
 k @Result
 f  s id=$o(^Index("Figure",Figure,id)) q:id=""  d
 . s @Result@(id)=""
 q
В некоторых из примеров используется первый способ, для простой демонстрации, а в более сложных случаях, или для выполнения операций над результатами поиска, используется второй вариант.

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

Подробнее о книге "MUMPS СУБД"

Комментариев нет:

Отправить комментарий