- PVSM.RU - https://www.pvsm.ru -
Предположим, что у вас есть таблица с большим количеством записей и в неё нужно добавить один или несколько индексов со следующими условиями:
Для этого можно было бы воспользоваться уже известным методом %BuildIndices() [1], но в таком случае это не будет удовлетворять нашим условиям.
Каков же выход?
В версию СУБД Caché 2013.1 был добавлен новый класс %Library.IndexBuilder с одним, но мощным методом %ConstructIndicesParallel().
Из названия уже становится понятно, что генерация будет происходить параллельно с привлечением всех ядер процессоров.
Итак, рассмотрим параметры этого метода подробнее:
ClassMethod %ConstructIndicesParallel(pTaskId="", pStartId As %Integer = 0, pEndId As %Integer = -1, pSortBegin As %Integer = 1, pDroneCount As %Integer = 0, pLockFlag As %Integer = 1, pJournalFlag As %Boolean = 1) as %Status
Теперь рассмотрим пример применения нового класса.
Для начала создадим в области USER учебный класс, заполним его 1М записей строками переменной длины [1-100] и построим индекс с использованием классического %BuildIndices(), чтобы было с чем сравнивать:
Class demo.test Extends %Persistent
{Index idxn On n As SQLUPPER(6);
Property n As %String(MAXLEN = 100);
ClassMethod Fill(n As %Integer = 10000000)
{
set data=$Replace($Justify("",100)," ","a")
set time=$ZHorolog
do DISABLE^%NOJRN
do ..%KillExtent()
set ^demo.testD=n
set ^demo.testD(1)=$ListBuild("",$Extract(data,1,$Random(100)+1))
for i=2:1:n set ^(i)=$ListBuild("",$Extract(data,1,$Random(100)+1))
do ENABLE^%NOJRN
write "вставка= ",$ZHorolog-time," сек.",!
}ClassMethod BIndex()
{
set time=$ZHorolog
do ..%BuildIndices(,1,1)
write "переиндексация= ",$ZHorolog-time," сек.",!
}}
Мои результаты:
USER>do ##class(demo.test).Fill()
вставка= 9.706935 сек.
USER>do ##class(demo.test).BIndex()
переиндексация= 71.966953 сек.
Теперь задействуем новый класс %IndexBuilder. Для этого выполним следующие действия:
ClassMethod SetMapSelectability(pTablename As %Library.String = "", pMapname As %Library.String = "", pValue As %Boolean = "") as %Library.String
Описание аргументов:
Примечание: можно cделать индекс невидимым задолго до его добавления в класс.
В итоге наш класс приобретёт следующий вид:
Class demo.test Extends (%Persistent, %IndexBuilder)
{Parameter INDEXBUILDERFILTER = "idxn";
Parameter BITMAPCHUNKINMEMORY = 0;
Index idxn On n As SQLUPPER(6);
Property n As %String(MAXLEN = 100);
…
ClassMethod FastBIndex()
{
do ..%PurgeIndices($ListBuild("idxn"))
do $SYSTEM.SQL.SetMapSelectability($classname(),"idxn",$$$NO)
do ..%ConstructIndicesParallel(,,,1,,2,0)
do $SYSTEM.SQL.SetMapSelectability($classname(),"idxn",$$$YES)
}
}
Мои результаты:
USER>do ##class(demo.test).FastBIndex()
Building 157 chunks and will use parallel build algorithm with 4 drone processes.
SortBegin is requested.
Started drone process: 3812
Started drone process: 4284
Started drone process: 7004
Started drone process: 7224
Expected time to complete is 43 secs to build 157 chunks of 64,000 objects using 4 processes.
Waiting for processes to complete....done.
Elapsed time using 4 processes was 34.906643.
Как видим, скорость возросла в два раза.
На вашем железе и на ваших данных результаты могут получиться ещё лучше.
Но есть ли возможность ещё больше ускорить перегенерацию индексов?
Если у вас есть в запасе много RAM, то да.
В процессе генерации индексов конструктором для внутренних нужд временно формируются так называемые bitmap-блоки. По умолчанию они записываются в приватные глобалы, но с помощью булева параметра BITMAPCHUNKINMEMORY можно указать, чтобы они формировались в оперативной памяти. Для этого нужно параметру присвоить 1.
Заметьте, что если RAM выделено мало, а индексы большие, то вы можете получить ошибку <STORE>.
По умолчанию BITMAPCHUNKINMEMORY равен 0.
Автор: servitRM
Источник [4]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/cache/30107
Ссылки в тексте:
[1] %BuildIndices(): http://docs.intersystems.com/cache20122/csp/documatic/%25CSP.Documatic.cls?PAGE=CLASS&LIBRARY=%25SYS&CLASSNAME=%25Library.Persistent#%BuildIndices
[2] $SortBegin: http://docs.intersystems.com/cache20122/csp/docbook/DocBook.UI.Page.cls?KEY=RCOS_fsortbegin
[3] %PurgeIndices(): http://docs.intersystems.com/cache20122/csp/documatic/%25CSP.Documatic.cls?PAGE=CLASS&LIBRARY=%25SYS&CLASSNAME=%25Library.Persistent#%PurgeIndices
[4] Источник: http://habrahabr.ru/post/173739/
Нажмите здесь для печати.