понедельник, 23 мая 2016 г.

MUMPS: Дифференциальное индексирование

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

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

На примере ведения простого индекса покажем изменения кода, которые нужно сделать для введения дифференциального перестроения индекса.
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:12 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))
 n Figure,Color,Count,FigureOld,ColorOld,CountOld
 ; check Figure
 s FigureOld=$p((OldRecordValues),"~",1)
 s Figure=$p((RecordValues),"~",1)
 i Figure'=FigureOld d
 . d DeleteIndexRecord("Figure",id,FigureOld)
 . d InsertIndexRecord("Figure",id,Figure)
 ; check Color
 s ColorOld=$p((OldRecordValues),"~",2)
 s Color=$p((RecordValues),"~",2)
 i Color'=ColorOld d
 . d DeleteIndexRecord("Color",id,ColorOld)
 . d InsertIndexRecord("Color",id,Color)
 ; check Count
 s CountOld=$p((OldRecordValues),"~",3)
 s Count=$p((RecordValues),"~",3)
 i Count'=CountOld d
 . d DeleteIndexRecord("Count",id,CountOld)
 . d InsertIndexRecord("Count",id,Count)
 s ^Data(id)=RecordValues
 l -^Data(id)
 q
DeleteIndex(IndexName)
 k ^Index(IndexName)
 q
InsertIndexRecords(id,RecordValues)
 d InsertIndexRecord("Figure",id,$p((RecordValues),"~",1))
 d InsertIndexRecord("Color",id,$p((RecordValues),"~",2))
 d InsertIndexRecord("Count",id,$p((RecordValues),"~",3))
 q
DeleteIndexRecords(id,RecordValues)
 d DeleteIndexRecord("Figure",id,$p((RecordValues),"~",1))
 d DeleteIndexRecord("Color",id,$p((RecordValues),"~",2))
 d DeleteIndexRecord("Count",id,$p((RecordValues),"~",3))
 q
InsertIndexRecord(IndexName,id,Value)
 l +^Index(IndexName,Value,id)
 s ^Index(IndexName,Value,id)=""
 l -^Index(IndexName,Value,id)
 q
DeleteIndexRecord(IndexName,id,Value)
 l +^Index(IndexName,Value,id)
 k ^Index(IndexName,Value,id)
 l -^Index(IndexName,Value,id)
 q
В приведенном примере код UpdateRecord явно содержит перечень имен всех свойств и способ получения их значений. В структуре алгоритма дифференциального перестроения индексов явно просматривается возможность написания более обобщенного кода. В более общем случае имеет смысл применять обобщенные функции вроде
GetAttrCount(rectype)
GetAttrName(rectype,attrnumber)
GetAttrValue(rec,attrnumber)
GetRecType(rec)
IsIndexed(rectype,attrnumber)
То есть тем или иным образом ввести а-ля объектный подход и информацию о метаданных. Это позволит реализовать код индексирования для общего случая и применять его для множества различных структур.

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

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

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

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