유지 관리 계획을 설정하는 데 도움이 되도록 이 섹션에는 Adobe Campaign에서 지원하는 다양한 RDBMS 엔진에 적용된 몇 가지 권장 사항/우수 사례가 나열됩니다. 하지만 권장 사항일 뿐입니다. 내부 절차와 제약 조건을 준수하면서 필요에 맞게 조정하는 것은 귀하에게 달려 있습니다. 데이터베이스 관리자는 이러한 계획을 작성하고 실행할 책임이 있습니다.
다음 뷰를 데이터베이스에 추가할 수 있습니다.
create or replace view uvSpace
as
SELECT c1.relname AS tablename, c2.relname AS indexname, c2.relpages * 8 / 1024 AS size_mbytes, c2.relfilenode AS filename, 0 AS row_count
FROM pg_class c1, pg_class c2, pg_index i
WHERE c1.oid = i.indrelid AND i.indexrelid = c2.oid
UNION
SELECT pg_class.relname AS tablename, NULL::"unknown" AS indexname, pg_class.relpages * 8 / 1024 AS size_mbytes, pg_class.relfilenode AS filename, cast(pg_class.reltuples as integer) AS row_count
FROM pg_class
WHERE pg_class.relkind = 'r'::"char"
ORDER BY 3 DESC, 1, 2 DESC;
다음 명령을 실행하면 큰 테이블과 인덱스를 찾을 수 있습니다.
select * from uvSpace;
PostgreSQL에서 사용할 수 있는 일반적인 명령은 진공 전체 및 재인덱스입니다.
다음은 SQL 유지 관리 계획을 정기적으로 실행하는 일반적인 예입니다.
vacuum full nmsdelivery;
reindex table nmsdelivery;
vacuum full nmsdeliverystat;
reindex table nmsdeliverystat;
vacuum full xtkworkflow;
reindex table xtkworkflow;
vacuum full xtkworkflowevent;
reindex table xtkworkflowevent;
vacuum full xtkworkflowjob;
reindex table xtkworkflowjob;
vacuum full xtkworkflowlog;
reindex table xtkworkflowlog;
vacuum full xtkworkflowtask;
reindex table xtkworkflowtask;
vacuum full xtkjoblog;
reindex table xtkjoblog;
vacuum full xtkjob;
reindex table xtkjob;
vacuum full nmsaddress;
reindex table nmsaddress;
vacuum full nmsdeliverypart;
reindex table nmsdeliverypart;
vacuum full nmsmirrorpageinfo;
reindex table nmsmirrorpageinfo;
PostgreSQL은 innofull이 테이블을 잠급기 때문에 정규 프로덕션을 방지하므로 온라인 테이블 다시 빌드를 쉽게 수행할 수 있는 방법을 제공하지 않습니다. 즉, 테이블을 사용하지 않을 때 유지 관리를 수행해야 합니다. 다음 중 하나를 수행할 수 있습니다.
다음은 필요한 DDL을 생성하기 위해 특정 함수를 사용하는 테이블 조각 모음의 예입니다. 다음 SQL을 사용하여 두 개의 새 함수를 만들 수 있습니다.GenRebuildTablePart1 및 GenRebuildTablePart2을(를) 사용하여 테이블을 다시 만드는 데 필요한 DDL을 생성할 수 있습니다.
-- --------------------------------------------------------------------------
-- Generate the CREATE TABLE DDL for a table
-- --------------------------------------------------------------------------
create or replace function GenTableDDL(text) returns text as $$
declare
vstrTable text;
vrecFld RECORD;
vstrDDL text;
vstrFields text;
vstrNsTable text;
vstrTableSpace text;
begin
vstrTable = lower($1);
vstrDDL = ;
SELECT
pg_catalog.quote_ident(n.nspname) || '.' || pg_catalog.quote_ident(c.relname),
pg_catalog.quote_ident(t.spcname)
INTO
vstrNsTable, vstrTableSpace
FROM
pg_namespace n, pg_class c left outer join pg_tablespace t on c.reltablespace = t.oid
WHERE
n.oid = c.relnamespace AND
c.relname = vstrTable;
vstrDDL = 'CREATE TABLE ' || vstrNsTable || '_tmp(';
vstrFields = ;
FOR vrecFld IN
SELECT
pg_catalog.quote_ident(a.attname) ||
' ' || t.typname ||
case when t.typname='varchar' then '(' || cast(a.atttypmod-4 as text) || ')'
when t.typname='numeric' then '(' || cast((a.atttypmod-4)/65536 as text) || ',' || cast((a.atttypmod-4)%65536 as text) || ')'
else end ||
case when a.attnotnull then ' not null' else end ||
case when a.atthasdef then ' default '|| d.adsrc else end as DDL
FROM
pg_type t, pg_class c, pg_attribute a LEFT OUTER JOIN pg_attrdef d ON d.adrelid=a.attrelid and d.adnum=a.attnum
WHERE
a.attnum > 0 AND
a.attrelid = c.oid AND
t.oid = a.atttypid AND
c.relname = vstrTable
ORDER BY
a.attnum
LOOP
IF vstrFields <> THEN
vstrFields = vstrFields || ',' || chr(10) || ' ';
ELSE
vstrFields = vstrFields || chr(10) || ' ';
END IF;
vstrFields = vstrFields || vrecFld.DDL;
END LOOP;
vstrDDL = vstrDDL || vstrFields || chr(10) || ')';
if vstrTableSpace <> then
vstrDDL = vstrDDL || ' TABLESPACE ' || vstrTableSpace;
end if;
vstrDDL = vstrDDL || ';' || chr(10);
return vstrDDL;
END;
$$ LANGUAGE plpgsql;
-- --------------------------------------------------------------------------
-- Generate the CREATE INDEX DDL for a table
-- --------------------------------------------------------------------------
create or replace function GenIndexDDL(text) returns text as $$
declare
vstrTable text;
vrecIndex RECORD;
vstrDDL text;
viFld integer;
vstrFld text;
begin
vstrTable = lower($1);
vstrDDL = ;
FOR vrecIndex IN
SELECT
i.indkey, i.indisunique,
pg_catalog.quote_ident(c.relname) as tablename,
pg_catalog.quote_ident(ic.relname) as indexname,
pg_catalog.quote_ident(t.spcname) as tablespace
FROM
pg_class c, pg_index i, pg_class ic left outer join pg_tablespace t on ic.reltablespace = t.oid
WHERE
i.indexrelid = ic.oid AND
i.indrelid = c.oid AND
c.relname = vstrTable
LOOP
vstrDDL = vstrDDL || 'CREATE ';
if vrecIndex.indisunique then
vstrDDL = vstrDDL || 'UNIQUE ';
end if;
vstrDDL = vstrDDL ||
'INDEX ' ||vrecIndex.indexname || '_tmp ON ' ||
vrecIndex.tablename || '_tmp(';
FOR viFld IN array_lower(vrecIndex.indkey, 1) .. array_upper(vrecIndex.indkey, 1) LOOP
SELECT pg_catalog.quote_ident(a.attname) INTO vstrFld
FROM
pg_attribute a, pg_class c
WHERE
a.attnum = vrecIndex.indkey[viFld] AND
a.attrelid = c.oid AND c.relname=vstrTable;
vstrDDL = vstrDDL || vstrFld;
if viFld <> array_upper(vrecIndex.indkey, 1) then
vstrDDL = vstrDDL || ', ';
end if;
END LOOP;
vstrDDL = vstrDDL || ')';
if vrecIndex.tablespace <> then
vstrDDL = vstrDDL || 'TABLESPACE ' || vrecIndex.tablespace;
end if;
vstrDDL = vstrDDL || ';' || chr(10);
END LOOP;
return vstrDDL;
END;
$$ LANGUAGE plpgsql;
-- --------------------------------------------------------------------------
-- Generate the ALTER INDEX RENAME for a table
-- --------------------------------------------------------------------------
create or replace function GenRenameIndexDDL(text) returns text as $$
declare
vstrTable text;
vrecIndex RECORD;
vstrDDL text;
begin
vstrTable = lower($1);
vstrDDL = ;
FOR vrecIndex IN
SELECT
pg_catalog.quote_ident(n.nspname) as namespace,
pg_catalog.quote_ident(ic.relname) as indexname
FROM
pg_namespace n, pg_class c, pg_index i, pg_class ic
WHERE
i.indexrelid = ic.oid AND
n.oid = ic.relnamespace AND
i.indrelid = c.oid AND
c.relname = vstrTable
LOOP
vstrDDL = vstrDDL || 'ALTER INDEX ' || vrecIndex.namespace || '.' || vrecIndex.indexname ||
'_tmp RENAME TO ' || vrecIndex.indexname ||
';' || chr(10);
END LOOP;
return vstrDDL;
END;
$$ LANGUAGE plpgsql;
-- --------------------------------------------------------------------------
-- Build a copy of a table, with index
-- --------------------------------------------------------------------------
create or replace function GenRebuildTablePart1(text) returns text as $$
declare
vstrTable text;
vstrTmp text;
vstrDDL text;
begin
vstrTable = lower($1);
vstrDDL = ;
SELECT GenTableDDL(vstrTable) INTO vstrTmp;
vstrDDL = vstrDDL|| vstrTmp || chr(10);
vstrDDL = vstrDDL|| 'INSERT INTO ' || vstrTable || '_tmp SELECT * FROM ' || vstrTable || ';'||chr(10);
SELECT GenIndexDDL(vstrTable) INTO vstrTmp;
vstrDDL = vstrDDL|| vstrTmp || chr(10);
vstrDDL = vstrDDL|| 'VACUUM ANALYSE '|| vstrTable || '_tmp;' ||chr(10);
return vstrDDL;
end;
$$ LANGUAGE plpgsql;
-- --------------------------------------------------------------------------
-- Drop the original table and rename the copy
-- --------------------------------------------------------------------------
create or replace function GenRebuildTablePart2(text) returns text as $$
declare
vstrTable text;
vstrTmp text;
vstrDDL text;
begin
vstrTable = lower($1);
vstrDDL = 'DROP TABLE ' || vstrTable||';'|| chr(10);
vstrDDL = vstrDDL|| 'ALTER TABLE ' || vstrTable || '_tmp RENAME TO ' || vstrTable ||';'|| chr(10);
SELECT GenRenameIndexDDL(vstrTable) INTO vstrTmp;
vstrDDL = vstrDDL|| vstrTmp || chr(10);
return vstrDDL;
end;
$$ LANGUAGE plpgsql;
다음 예제는 워크플로우에서 진공/rebuild 명령을 사용하는 대신 필요한 테이블을 다시 구성하는 데 사용할 수 있습니다.
function sqlGetMemo(strSql)
{
var res = sqlSelect("s, m:memo", strSql);
return res.s.m.toString();
}
function RebuildTable(strTable)
{
// Rebuild a table_tmp
var strSql = sqlGetMemo("select GenRebuildTablePart1('"+strTable+"')");
logInfo("Rebuilding table '"+strTable+"'...");
// logInfo(strSql);
sqlExec(strSql);
// If fails, there is an exception thrown and so we do not delete the original table
strSql = sqlGetMemo("select GenRebuildTablePart2('"+strTable+"')");
logInfo("Swapping table '"+strTable+"'...");
//logInfo(strSql);
sqlExec(strSql);
}
RebuildTable('nmsrecipient');
RebuildTable('nmsrcpgrlrel');
// ... other tables here
사용 중인 Oracle 버전에 가장 적합한 절차에 대해서는 데이터베이스 관리자에게 문의하십시오.
Microsoft SQL Server의 경우 이 페이지에 대한 유지 관리 계획을 사용할 수 있습니다.
아래 예제는 Microsoft SQL Server 2005와 관련이 있습니다. 다른 버전을 사용하는 경우 데이터베이스 관리자에게 문의하여 유지 관리 절차에 대해 알아보십시오.
먼저 관리자 권한으로 로그인과 함께 Microsoft SQL Server Management Studio에 연결합니다.
Management > Maintenance Plans 폴더로 이동하여 마우스 오른쪽 버튼을 클릭하고 Maintenance Plan Wizard
첫 번째 페이지가 나타나면 Next을 클릭합니다.
만들려는 유지 관리 계획의 유형(각 작업에 대해 별도의 일정 또는 전체 플랜에 대한 단일 일정)을 선택한 다음 Change… 단추를 클릭합니다.
Job schedule properties 창에서 원하는 실행 설정을 선택하고 OK 을 클릭한 다음 Next를 클릭합니다.
수행할 유지 관리 작업을 선택한 다음 Next 을 클릭합니다.
아래에 표시된 유지 관리 작업 이상을 수행하는 것이 좋습니다. 데이터베이스 정리 워크플로우에서 이미 수행되지만 통계 업데이트 작업을 선택할 수도 있습니다.
드롭다운 목록에서 Database Check Integrity 작업을 실행할 데이터베이스를 선택합니다.
데이터베이스를 선택하고 OK 을 클릭한 다음 Next 을 클릭합니다.
데이터베이스에 할당된 최대 크기를 구성한 다음 Next을 클릭합니다.
데이터베이스 크기가 이 임계값을 초과하는 경우 유지 관리 계획은 사용하지 않은 데이터를 삭제하여 공간을 확보합니다.
인덱스를 다시 구성하거나 다시 작성합니다.
인덱스 조각화 비율이 10%에서 40% 사이인 경우 다시 구성하는 것이 좋습니다.
재구성할 데이터베이스 및 개체(표 또는 보기)를 선택한 다음 Next을 클릭합니다.
구성에 따라 이전에 선택한 테이블 또는 데이터베이스의 모든 테이블을 선택할 수 있습니다.
인덱스 조각화 비율이 40% 이상인 경우 다시 구성하는 것이 좋습니다.
인덱스 다시 작성 작업에 적용할 옵션을 선택한 다음 Next 을 클릭합니다.
재구축 인덱스 프로세스는 프로세서 사용 측면에서 더욱 제한적이며 데이터베이스 리소스를 잠급니다. 다시 구성하는 동안 인덱스를 사용할 수 있게 하려면 Keep index online while reindexing 옵션을 클릭합니다.
활동 보고서에 표시할 옵션을 선택한 다음 Next을 클릭합니다.
유지 관리 계획에 대해 구성된 작업 목록을 확인한 다음 Finish 을 클릭합니다.
유지 관리 계획의 요약 및 다양한 단계의 상태가 표시됩니다.
유지 관리 계획이 완료되면 Close 을 클릭합니다.
Microsoft SQL Server 탐색기에서 Management > Maintenance Plans 폴더를 두 번 클릭합니다.
Adobe Campaign 유지 관리 계획을 선택합니다.다양한 단계가 워크플로우에 자세히 설명되어 있습니다.
SQL Server Agent > Jobs 폴더에 개체가 생성되었습니다. 이 개체를 사용하여 유지 관리 계획을 시작할 수 있습니다. 모든 유지 관리 작업이 동일한 계획에 속하므로 이 예에서는 개체가 하나만 있습니다.
이 개체를 실행하려면 Microsoft SQL Server 에이전트를 활성화해야 합니다.
작업 테이블에 대해 별도의 데이터베이스 구성
이 구성은 선택 사항입니다.
WdbcOptions_TempDbName 옵션을 사용하면 Microsoft SQL Server에서 작업 테이블에 대해 별도의 데이터베이스를 구성할 수 있습니다. 백업 및 복제를 최적화합니다.
이 옵션은 작업 테이블(예: 작업 흐름 실행 중에 만들어진 테이블)을 다른 데이터베이스에 만들려는 경우에 사용할 수 있습니다.
옵션을 "tempdb.dbo."로 설정하면 작업 테이블이 Microsoft SQL Server의 기본 임시 데이터베이스에 생성됩니다. 데이터베이스 관리자가 tempdb 데이터베이스에 대한 쓰기 액세스를 허용해야 합니다.
이 옵션을 설정하면 Adobe Campaign에 구성된 모든 Microsoft SQL Server 데이터베이스(기본 데이터베이스 및 외부 계정)에 사용됩니다. 두 개의 외부 계정이 동일한 서버를 공유하는 경우 tempdb가 고유하므로 충돌이 발생할 수 있습니다. 같은 방식으로 두 개의 캠페인 인스턴스가 동일한 MSSQL 서버를 사용하는 경우 동일한 tempdb를 사용할 경우 충돌이 발생할 수 있습니다.