Почему удаление записей в таблице приводит к фрагментации индексов?
Когда происходит удаление записей, дерево индексов не перестраивается. Таким образом, всё B-дерево остается не поврежденным. Это было введено в версии Progress 9.x, где элементы индексной блокировки не удалялись в конце транзакции.
Во время транзакции, когда удаляются записи, если существует уникальный индекс, признак удаления записи помещается вместо RECID удаляемой записи. А в конце транзакции эти признаки преобразуются в отрицательное число и помещаются вместо RECID в индексе, т.е. Progress обрабатывает такие элементы указателя индекса во время последующих операций чтения. Конечно же, блоки, на которые указывают такие элементы указателя индекса, не могут быть прочитаны, так как эти RECID выше, чем любое возможное значение High Water Mark (HWM) в области. Но всё равно это всё еще логический запрос. Таким образом, со временем удаление большого количества записей может привести к ситуации, когда возникнет высокая индексная фрагментация, что в свою очередь может значительно повлиять на производительность. Поэтому, после удаления большого количества данных, для того чтобы сократить количество индексных блоков и увеличить производительность, необходимо выполнить одно из следующих действий: idxbuild или idxcompact.
В идеале конечно лучше выполнить перестройку индексов с помощью PROUTIL IDXBUILD. Но эта операция может быть выполнена только в offline. Поэтому с другой стороны можно использовать PROUTIL IDXCOMPACT, которая может выполняться как в offline, так и в online, и позволяет сократить количество блоков в B-дереве и даже количество его уровней. Здесь хотелось бы особенно отметить, что не рекомендуется использование этой утилиты до версии Progress 10.1С04 или 10.2A01, поскольку в более ранних версиях имели место некоторые проблемы в работе этой утилиты, например, её использование приводило к чрезмерному росту BI файла из-за области видимости транзакции, т.е. уплотнение выполнялось в одной большой транзакции.
Что же даст нам уплотнение индексов:
- Если индекс уникальный, то сканируется цепочка удалений, и индексные блоки очищаются путем удаления таких указателей.
- Не листовые уровни B-дерева уплотняются, начиная от корня до листового уровня.
- Уплотняется листовой уровень.
Иными словами, помимо уплотнения индекса, эта утилита выполняет чистку мертвых указателей, оставленных после того как они были удалены из уникального индекса. Но помните, что имелись проблемы с работой IDXCOMPACT в online, которые были устранены в более поздних версиях. И строго рекомендуется, прежде чем запускать утилиту, обновить свою версию Progress до 10.1С04/10.2A01 или позже.
Командная строка для уплотнения индекса выглядит следующим образом:
$ proutil dbname-C idxcompact tablename.indexname
Скрипт уплотнения индексов по всем таблицам базы данных может быть создан с помощью следующего просто ABL кода:
DEF VAR mydb AS CHAR FORMAT "X(10)" INITIAL "./sports".
OUTPUT TO VALUE("all-idxcompact.sh").
For each _file where _file-number > 0 AND NOT _file-name BEGINS "SYS":
for each _index OF _file:
PUT UNFORMATTED
"proutil " mydb " -C idxcompact "
_file._file-nam "."
_index._index-Name " 80" SKIP.
End.
END.
OUTPUT CLOSE.
Внимание! Перед выполнением уплотнения индексов убедитесь, что у вас имеется работоспособная резервная копия базы данных, т.к. в случае возникновения сбоя во время работы утилиты, работоспособность базы данных не гарантированна.
В результате вы получите скрипт, в котором будет содержаться примерно следующий код:
proutil ./sports -C idxcompact Invoice.Cust-Num 80
proutil ./sports -C idxcompact Invoice.Invoice-Date 80
proutil ./sports -C idxcompact Invoice.Invoice-Num 80
proutil ./sports -C idxcompact Invoice.Order-Num 80
proutil ./sports -C idxcompact Customer.Comments 80
proutil ./sports -C idxcompact Customer.Country-Post 80
proutil ./sports -C idxcompact Customer.Cust-Num 80
proutil ./sports -C idxcompact Customer.Name 80
proutil ./sports -C idxcompact Customer.Sales-Rep 80
proutil ./sports -C idxcompact Item.Cat-Description 80
proutil ./sports -C idxcompact Item.Item-Name 80
proutil ./sports -C idxcompact Item.Item-Num 80
proutil ./sports -C idxcompact Order.Cust-Order 80
proutil ./sports -C idxcompact Order.Order-Date 80
proutil ./sports -C idxcompact Order.Order-Num 80
proutil ./sports -C idxcompact Order.Sales-Rep 80
proutil ./sports -C idxcompact Order-Line.item-num 80
proutil ./sports -C idxcompact Order-Line.order-line 80
proutil ./sports -C idxcompact Salesrep.Sales-Rep 80
proutil ./sports -C idxcompact State.State 80
proutil ./sports -C idxcompact Local-Default.default 80
proutil ./sports -C idxcompact Ref-Call.Call-Num 80
proutil ./sports -C idxcompact Ref-Call.Cust-Num 80
proutil ./sports -C idxcompact Ref-Call.Sibling 80
proutil ./sports -C idxcompact Ref-Call.Txt 80
proutil ./sports -C idxcompact TBLB2.IDX1 80
proutil ./sports -C idxcompact TBLB2.IDX3 80
proutil ./sports -C idxcompact TBLBLOB2.default 80
proutil ./sports -C idxcompact TBLB4.default 80
proutil ./sports -C idxcompact ENCTAB1.default 80
Если процедура удаления данных из таблицы, это характерная черта приложения, требующего полной очистки таблицы, например, в конце рабочего дня, то вместо выполнения IDXCOMPACT, в качестве альтернативного метода рекомендуется переместить такую таблицу вместе со всеми ее индексами в отдельную область хранения. После чего к этой области можно применять команду усечения области PROUTIL TRANCATE AREA, синтаксис которой выглядит следующим образом:
$ proutil dbname -C truncate area <area name>
Этот способ более эффективен, чем обычное удаление таблицы и последующее уплотнение индексов.
|