|
|
|||||||||||||||||||||||||||||
|
Алгоритмы удаления данных: как эффективно удалять терабайтные объемы информации из базы данных DB2 for Linux, UNIX, and WindowsИсточник: ibm
ПредысторияВ нашей среде DB2 имелась база данных для лаборатории производительности. В этой базе данных содержались сведения по 2,5 млн. пользователей приложения, а ее размеры составляли 1,8 ТБ. Однако нашему клиенту потребовались результаты теста производительности при работе с базой данных, размеры которой соответствовали бы 1,2 млн. пользователей. С этой целью мы решили "вычистить" из этой, уже существующей базы данных пользователей сведения об 1,3 млн. пользователей. ОбзорМы опробовали несколько методик для удаления столь большого объема данных из базы данных. В конечном итоге мы выбрали наилучший метод и разработали алгоритм для его реализации. Вместо того чтобы удалять ненужные данные, мы экспортируем нужные данные и перезагружаем их в родительскую таблицу (корневой узел табличной иерархии). После этого мы с помощью команды АлгоритмПрежде чем переходить к выполнению алгоритма удаления, может быть целесообразно изменить ряд конфигурационных параметров DB2. Не забывайте, что мы настраиваем эти параметры с целью достижения оптимальной производительности алгоритма удаления. После завершения удаления данных значения этих параметров можно вернуть к исходным значениям, чтобы обеспечить оптимальную производительность приложения. Показанные ниже значения параметров обеспечили наилучшую производительность в нашей среде. Вы можете попытаться подстроить их в соответствии с особенностями своей среды. КонфигурацияТаблица 1. Настройка параметров реестра профиля для достижения оптимальной производительности
Таблица 2. Настройка параметров конфигурации СУБД для достижения оптимальной производительности
Таблица 3. Настройка параметров конфигурации базы данных для достижения оптимальной производительности
Число строкПосле завершения конфигурирования подсчитайте количество строк во всех таблицах базы данных и запомните ее первоначальный размер - это будет ваш исходный уровень. В каждом из показанных ниже запросов замените выделенный жирным шрифтом параметр соответствующими значениями для своей базы данных. Листинг 1. Показатели базы данных (исходный уровень)db2 -x "select 'runstats on table '//trim(tabschema)//'.'//trim(tabname)//';' from syscat.tables where tabschema = 'SCHEMANAME' and type='T'" >runstats.sql db2 -tvf runstats.sql -z runstats.out db2 "select substr(tabname,1,30) tabname,card from syscat.tables where tabschema = 'SCHEMANAME' and type='T'" >initialCount.out db2 "call get_dbsize_info(?,?,?,-1)" >initialDBSize.out db2look -d DBNAME -a -e -l -x -c > initialDB2Look.ddl Большие дочерние таблицыКоманда Листинг 2. Изоляция больших дочерних таблицdb2 "select substr(tabname,1,30) tabname,card from syscat.tables where tabschema = 'SCHEMANAME' and type='T' and card > 300000000" >isolatedTables.out db2 -x "select 'alter table '//trim(a.tabschema)//'.'//trim(a.tabname)//' drop constraint ' // a.constname//';' from syscat.references a,syscat.tables b where a.tabschema=b.tabschema and a.tabschema='SCHEMANAME' and b.type='T' and a.tabname=b.tabname and b.card> 300000000" >alterTable.sql db2 -tvf alterTable.sql -z alterTable.out Каждая изолированная таблица представляет собой псевдокорневой узел. Мы будем рекурсивно применять один и тот же алгоритм очистки, рассматривая одну изолированную таблицу в качестве корневого узла на каждой итерации рекурсивного исполнения. После успешного удаления данных из исходной и псевдокорневой табличных иерархий мы заново свяжем изолированные дочерние таблицы с их родительскими таблицами, чтобы восстановить первоначальную структуру базы данных. Экспорт данныхВместо того чтобы удалять ненужные данные, экспортируйте полезные данные из корневого узла. Чтобы повысить производительность ввода/вывода, обеспечьте размещение результатов экспорта в файловой системе, отдельной от контейнеров табличного пространства затрагиваемой таблицы. Прежде чем перезагружать полезные данные, удалите все индексы затрагиваемой таблицы и воссоздайте их после успешной перезагрузки данных (этот технический прием повысит производительность). Примечание. Ограничение первичного ключа необходимо убрать до удаления индекса, который используется для принудительного применения первичного ключа. Листинг 3. Экспорт полезных данных и удаление индексовdb2 export to EXPORT-PATH ROOT-TABNAME.csv of del select * from ROOT-TABNAME where WHERE-CLAUSE-CONDITIONS db2look -d DBNAME -t ROOT-TABNAME-OR-TABLIST -e -o OUTPUT_FILE_NAME db2 -x "select 'alter table '//trim(st.tabschema)//'.'//trim(st.tabname)//' drop constraint '//st.constname//';' from syscat.keycoluse sk inner join syscat.tabconst st on sk.tabname = st.tabname and sk.tabschema=st.tabschema and st.tabschema='SCHEMANAME' where st.type in ('P','U') and st.constname =sk.constname and exists (select 1 from syscat.tables a where a.tabname=st.tabname and st.tabschema=a.tabschema and a.tabname in (ROOT-TABNAME))" >dropPK.sql db2 -tvf dropPK.sql -z dropPK.out db2 -x "select 'drop index '//trim(indname)//';' from syscat.indexes where tabname in(ROOT-TABNAME) and tabschema='SCHEMANAME'" >dropIndexes.sql db2 -tvf dropIndexes.sql -z dropIndexes.out Загрузка данныхПосле удаления индексов можно перезагрузить полезные данные, используя опцию Листинг 4. Перезагрузка полезных данныхdb2 "load from export file.csv of del modified by fastparse replace into TABNAME data buffer VALUE sort buffer VALUE cpu_parallelism VALUE disk_parallelism VALUE" db2 "set integrity for TABSCHEMA.TABNAME immediate checked" Создание таблиц исключенийСоздайте таблицы исключений с двумя дополнительными столбцами типа Листинг 5. Создание таблиц исключенийdb2 -x "select 'create table '//trim(tabname)//'_exp '// 'like ' // tabname //';' from syscat.tables where status='c' and type='t' and tabschema='SCHEMANAME'" >createExceptionTab.sql db2 -x "select 'drop table '//trim(tabname)//'_exp;' from syscat.tables where status='c' and type='t' and tabschema='SCHEMANAME'" >dropExceptionTab.sql db2 -x "select 'alter table '//trim(tabname)//'_exp '// ' add column c1 timestamp add column c2 clob; ' from syscat.tables where status='c' and type='t' and tabschema ='SCHEMANAME'" >>createExceptionTab.sql db2 -tvf createExceptionTab.sql -z createExceptionTab.out Рекурсивное применение операции set integrity к таблицамПримените команду set integrity ко всем таблицам, находящимся в состоянии integrity pending, используя для этого соответствующие таблицы исключений. В результате этого ненужные данные будут вычищены из базовых таблиц и перемещены в таблицы исключений. Сохраните показанные ниже команды оболочки в виде скрипта оболочки (setIntegrity.sh) и примените его рекурсивно к таблицам, находящимся в состоянии integrity pending. Листинг 6. Рекурсивное применение операции set integrity к дочерним таблицам#!/bin/ksh before="$(date +%s)" DBName=$1 DBSchema=$2 echo "Checking and removing tables from set integrity pending state" / tee -a SetIntegrity.log db2 activate db $DBName>>output.out db2 connect to $DBName>>output.out db2 set schema $DBSchema>>output.out db2 -x "select 'SET INTEGRITY FOR '// TABSCHEMA //'.'//TABNAME // ' IMMEDIATE CHECKED FOR EXCEPTION IN ' //TABNAME // ' USE ' //TABNAME//'_exp ;' from SYSCAT.TABLES where STATUS='C' and type='T' and TABSCHEMA='$DBSchema' order by card " >chkset_integrity.sql tabcnt=$(wc -l chkset_integrity.sql) while [[ ${tabcnt} -gt 0 ]]; do echo "**************************************************" / tee -a SetIntegrity.log echo "Number of tables in set integrity pending state : $tabcnt" / tee -a SetIntegrity.log echo "Setting integrity of table in set integrity pending state" / tee -a SetIntegrity.log echo "**************************************************" / tee -a SetIntegrity.log db2 connect to $DBName>>output.out db2 set schema $DBSchema>>output.out db2 -tvfchkset_integrity.sql>>output.out db2 "commit" >>output.out db2 -x "select 'SET INTEGRITY FOR '// TABSCHEMA //'.'//TABNAME // ' IMMEDIATE CHECKED FOR EXCEPTION IN ' //TABNAME // ' USE ' //TABNAME//'_exp ;' from SYSCAT.TABLES where STATUS='C' and type='T' and TABSCHEMA='$DBSchema' order by card " >chkset_integrity.sql tabcnt=$(wc -l chkset_integrity.sql) done echo "No table in set integrity pending state" / tee -a SetIntegrity.log after="$(date +%s)" elapsed_seconds="$(expr $after - $before)" timediff=`echo - / awk -v "S=$elapsed_seconds" '{printf"%dh:%dm:%ds",S/(60*60),S%(60*60)/60,S%60}'` echo "Time Taken to set Integrity: $timediff" / tee -a SetIntegrity.log Выполните следующую команду: Воссоздание внешних ключейРекурсивным образом примените такой же процесс экспорта и перезагрузки полезных данных для всех псевдоузлов. После того как данные будут удалены из всех таблиц, воссоздайте отброшенные ограничения внешних ключей (посредством обращения к intitialDB2Look.ddl и alterTable.sql), чтобы снова связать псевдокорневые табличные иерархии с корневой таблицей и восстановить первоначальную структуру базы данных. Кроме того, удалите таблицы исключений, поскольку они нам больше не нужны. Листинг 7. Удаление таблиц исключенийdb2 -tvf dropExceptionTab.sql -z dropExceptionTab.out
Итоговые показателиПоскольку из таблиц было удалено значительное количество данных, выполните операцию reorg (по возможности используйте для операции reorg временное табличное пространство). Чтобы обновить статистические сведения, выполните утилиту runstats для всех таблиц. После этого зафиксируйте обновленные сведения по количеству строк, по размерам базы данных и по результатам работы утилиты DB2look с целью их сравнения с первоначальными сведениями (исходный уровень). Листинг 8. Получение итоговых показателей для таблицы и базы данныхdb2 -x "select 'reorg table '//trim(tabname)//';' from syscat.tables where type='T' and tabschema='SCHEMANAME'">reorg.sql db2 -tvf reorg.sql -z reorg.out db2 -x "select 'runstats on table '//trim(tabschema)//'.'//trim(tabname)//';' from syscat.tables where tabschema = 'SCHEMANAME' and type='T'" >runstats.sql db2 -tvf runstats.sql -z runstats.out db2 "select substr(tabname,1,30) tabname,card from syscat.tables where tabschema = 'SCHEMANAME' and type='T'" >finalCount.out db2 "call get_dbsize_info(?,?,?,-1)" >finalDBSize.out db2look -d DBNAME -a -e -l -x -c > finalDB2look.ddl С помощью операции reorg мы сократили количество используемых страниц в табличном пространстве, однако верхняя отметка для размера табличного пространства может по-прежнему превышать количество реально используемых страниц, поэтому нам следует снизить эту отметку. Листинг 9. Снижение верхней отметки размера табличного пространстваdb2 -x "select 'alter tablespace '//trim(tbspace)//' lower high water mark ;' from syscat.tablespaces where tbspacetype='D'">highWatermark.sql db2 -tvf highWatermark.sql -z highWatermark.out Если после снижения верхней отметки размер табличного пространства окажется больше, чем эта верхняя отметка, а вы выполняете резервное копирование/восстановление базы данных, эта база данных будет по-прежнему потреблять больше дискового пространства, чем требуется используемым в ней страницам. Чтобы свести к минимуму эти потребности к дисковому пространству, рассмотрите возможность изменения размеров табличного пространства и уменьшите эти размеры. Мониторинг процесса удаленияПри использовании описываемого алгоритма мы удаляем данные из дочерних таблиц с помощью команды Что следует запомнить
db2 "select substr(a.tabname,1,20)tabname,substr(a.reftabname,1,20)reftabname,substr(a.constname,1,20)constname from syscat.references a where exists (select 1 from syscat.references b where a.reftabname=b.tabname and a.tabname=b.reftabname)" ЗаключениеКак показано ниже, описываемый в этой статье алгоритм функционирует лучше, чем традиционные методы удаления данных, с минимальным количеством проблем с блокировками и с транзакционными журналами или вообще без таковых проблем. Он требует минимального времени и предоставляет пользователю улучшенные возможности контроля над процессом очистки. При использовании этого метода общая продолжительность работы состоит в большей степени из фазы Рисунок 1. Сравнение методов удаления данных
|
|