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

MUMPS: Покрывающий индекс

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

Индекс в силу своей структуры есть отображение значений атрибутов на идентификаторы записей. Поэтому содержит как набор значений атрибутов, так и набор отображений. Практически любой индекс в силу своего строения является покрывающим для по крайней мере нескольких задач:
  • Поскольку содержит набор значений атрибутов, может быть использован для выборки списка различных имеющихся значений атрибутов.
  • Поскольку каждое значение атрибута отображается на набор идентификаторов записей, можно найти записи по заданному значению.
  • Если значения атрибута находятся в некотором упорядочении, то можно получить сортировку по значениям атрибутов в этом упорядочении.
  • Возможно определить, существует ли запись с заданным значением, и тогда можно реализовать ограничения различного рода, накладываемые на данные. В частности, запрет иметь значение "синий" более чем 5 записям одновременно.
Каждая возможность применения индекса вызвана некоторым отношением - либо внутри однородного набора, либо между значением и набором. И, чем больше отношений содержится в индексе, тем больше покрытий он обеспечивает. Например, пусть есть таблица с атрибутами Color и Figure. Составной индекс по Color и Figure покрывает уже следующие задачи:
  • Выбрать набор различных значений Color
  • Выбрать по заданному Color идентификаторы записей (применять вместо функции $O функцию $Q)
  • Выбрать по заданному Color и Figure идентификаторы записей (применять функцию $O)
  • Отсортировать идентификаторы по Color и Figure ($O)
  • Выбрать идентификаторы для диапазона Color ($Q)
  • Выбрать идентификаторы для диапазона Figure при задании Color ($O)
  • Выбрать идентификаторы при задании диапазонов Color и Figure ($O по Color + вложенный $O по Figure)
  • \item Для заданного Color отсортировать по Figure.
При этом нужно отметить, что составной индекс по Color и Figure уже не может быть использован, если условие наложено только на атрибут Figure. Поскольку в таком индексе значения Figure находятся в подчиненной, а не независимой иерархии по отношению к Color. Если необходимо использовать значения Figure независимо от значений Color, то необходимо поддерживать второй индекс соответствующей структуры.

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

Приведем демонстрационный пример поддержания структуры данных для записей с атрибутами Color и Figure, после чего приведем примеры использования одного и того же индекса в различных задачах:
CreateRecords()
 k ^Index
 k ^Data
 n i,Figures,Colors,Counts,Figure,Color,Count,id
 s Figures="квадрат~круг~отрезок~треугольник"
 s Colors="красный~зелёный~синий~белый"
 s Counts="2~5~12~8"
 f i=1:1:120 d
 . s Figure=$p(Figures,"~",$r(4)+1)
 . s Color=$p(Colors,"~",$r(4)+1)
 . s Count=$p(Counts,"~",$r(4)+1)
 . s id=$$InsertRecord(Figure_"~"_Color_"~"_Count)
 q
InsertRecord(RecordValues)
 n id s id=$i(^Data)
 l +^Data(id)
 s ^Data(id)=RecordValues
 d InsertIndexRecords(id,RecordValues)
 l -^Data(id)
 q id
DeleteRecord(id)
 q:'$d(^Data(id))
 l +^Data(id)
 n RecordValues s RecordValues=$g(^Data(id))
 d DeleteIndexRecords(id,RecordValues)
 k ^Data(id)
 l -^Data(id)
 q
UpdateRecord(id,RecordValues)
 q:'$d(^Data(id))
 l +^Data(id)
 n OldRecordValues s OldRecordValues=$g(^Data(id))
 d DeleteIndexRecords(id,OldRecordValues)
 s ^Data(id)=RecordValues
 d InsertIndexRecords(id,RecordValues)
 l -^Data(id)
 q
DeleteIndex(IndexName)
 k ^Index(IndexName)
 q
InsertIndexRecords(id,RecordValues)
 d InsertIndexRecord("ColorFigure",id,
   $p((RecordValues),"~",2),$p((RecordValues),"~",1))
 q
DeleteIndexRecords(id,RecordValues)
 d DeleteIndexRecord("ColorFigure",id,
   $p((RecordValues),"~",2),$p((RecordValues),"~",1))
 q
InsertIndexRecord(IndexName,id,ColorValue,FigureValue)
 l +^Index(IndexName,ColorValue,FigureValue,id)
 s ^Index(IndexName,ColorValue,FigureValue,id)=""
 l -^Index(IndexName,ColorValue,FigureValue,id)
 q
DeleteIndexRecord(IndexName,id,ColorValue,FigureValue)
 l +^Index(IndexName,ColorValue,FigureValue,id)
 k ^Index(IndexName,ColorValue,FigureValue,id)
 l -^Index(IndexName,ColorValue,FigureValue,id)
 q
Приведем несколько примеров таких выборок различного назначения по одному и тому же индексу.

Выбрать набор различных значений Color
Select1()
 n Color
 s Color="" 
 f  s Color=$o(^Index("ColorFigure",Color)) q:Color=""  d
 . w Color,!
 q
Выбрать по заданному Color идентификаторы записей (применять вместо функции $O функцию $Q)
Select2(Color="красный")
 n ref
 s ref=$na(^Index("ColorFigure",Color))
 f  s ref=$q(@ref) q:$s(ref="":1,$qs(ref,2)'=Color:1,1:0)  d
 . w $qs(ref,4),!
 q
Выбрать по заданному Color и Figure идентификаторы записей (применять функцию $O)
Select3(Color="синий",Figure="квадрат")
 n id
 s id="" 
 f  s id=$o(^Index("ColorFigure",Color,Figure,id)) q:id=""  d
 . w "Found id: "_id,!
 q
Отсортировать идентификаторы по Color и Figure (\$O)
Select4(COrder=1,FOrder=-1)
 n c,f,id
 s c="" f  s c=$o(^Index("ColorFigure",c),COrder) q:c=""  d
 . s f="" f  s f=$o(^Index("ColorFigure",c,f),FOrder) q:f=""  d
 . . s id="" f  s id=$o(^Index("ColorFigure",c,f,id)) q:id=""  d
 . . . w c_" "_f_" "_id,!
 q
Подробнее о книге "MUMPS СУБД"

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

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