다음을 통해 공유


사용자 정의 필드에 대한 보고 데이터 서비스 최적화

업데이트 날짜: 2009년 12월

 

마지막으로 수정된 항목: 2015-02-27

이 문서에서는 Microsoft Office Project Server 2007의 RDB(보고 데이터베이스)용으로 작성된 사용자 지정 보고 솔루션을 최적화하는 방법에 대해 설명합니다. 사용자 지정 보기를 작성하거나 RDB의 보기에 사용자 지정 인덱스를 적용하는 데 관심이 있으면 솔루션과 함께 사용할 수 있는 일부 도우미 저장 프로시저에 대한 이 문서를 읽으십시오.

RDB의 일반적인 메커니즘을 잘 모르는 경우 다음과 같은 배경 문서를 참조하십시오.

먼저 사용자 정의 필드 데이터가 RDB에서 저장되는 방식을 살펴보겠습니다. Office Project Server 2007에는 몇 가지 미리 정의된 사용자 정의 필드가 있습니다. 인스턴스가 커지면서 새로운 Enterprise 사용자 정의 필드를 추가할 수 있으며 기존 필드를 정기 유지 관리 중에 삭제할 수 있습니다. RDB의 사용자 정의 필드 저장 방식은 새로운 필드의 추가와 이전 필드의 제거를 동적으로 처리하도록 설계되었으며 더욱 효율적인 큐브 작성 및 보고 작업에 최적화되도록 정규화 해제되었습니다. 사용자 정의 필드는 프로젝트, 자원, 작업 및 배정 데이터에 대한 여러 열 그룹으로 구성된 테이블인 MSP_EpmCPPrj*, MSP_EpmCPRes*, MSP_EpmCPTask* 및 MSP_EpmCPAssn*에 각각 저장됩니다. 새로운 사용자 정의 필드가 만들어지면 새로운 열이 해당 엔터티 형식의 열 그룹 테이블에 추가되고 기존 테이블이 특정 수의 열에 도달하면 새로운 테이블이 만들어집니다. 사용자 정의 필드가 RDB에 저장되는 방식에 대한 자세한 내용은 MSDN Library Online의 로컬 및 Enterprise 사용자 정의 필드 (영문)(https://go.microsoft.com/fwlink/?linkid=123368\&clcid=0x412)를 참조하십시오.

Microsoft Office Servers 인프라 업데이트에는 네 가지 핵심 엔터티 각각에 대한 RDB 사용자 정의 필드 데이터를 집계하는 다음과 같은 보기가 포함되어 있습니다.

  • MSP_EpmProject_UserView

  • MSP_EpmTask_UserView

  • MSP_EpmAssignment_UserView

  • MSP_EpmResource_UserView

이러한 사용자 보기는 Office Project Server에서 유지 관리되며 해당 엔터티에 대해 정의된 모든 사용자 정의 필드를 포함합니다. 사용자 정의 필드가 추가될 때마다 새로운 열이 해당 보기에 자동으로 추가됩니다. 또한 사용자 정의 필드가 삭제될 때마다 해당 열이 보기에서 제거됩니다.

조직의 요구 사항에 맞게 사용자 지정된 보기를 직접 작성할 수도 있습니다. 예를 들어 기본 보기를 사용하는 대신 필드의 작은 부분 집합을 사용하는 보고서가 하나 있는 경우 관련 데이터만 포함된 사용자 지정 보기를 직접 만들도록 선택할 수 있습니다.

사용자 지정 보기 만들기

사용자 지정 보기를 직접 만들려면 먼저 필드 값이 저장된 곳을 찾아야 합니다. 해당 필드를 가리키는 열 그룹 테이블과 열 번호를 아는 경우 Join 문을 사용하여 값을 보기에 끌어올 수 있습니다. 모든 열 그룹 테이블에는 지정된 데이터-행이 참조하는 엔터티의 고유 식별자가 포함된 EntityUID 열이 있습니다.

도우미 함수

다음 함수는 모든 사용자 정의 필드에 대한 흥미로운 정보를 반환합니다.

FUNCTION MFN_Epm_GetAllCustomFieldsInformation();

반환값

이 함수는 사용자 정의 필드 정보가 포함된 데이터 집합을 반환합니다(사용자 정의 필드마다 한 행). 사용자 정의 필드가 없으면 이 함수는 빈 데이터 집합을 반환합니다.

반환된 데이터 집합에는 사용자 정의 필드마다 다음 열이 포함된 행이 하나 있습니다.

설명

EntityTypeUID

각 사용자 정의 필드에 대한 부모 엔터티의 고유 식별자입니다. 예를 들어 프로젝트 사용자 정의 필드의 경우 이 열에는 'Projects'에 해당하는 값이 표시됩니다.

EntityName

각 사용자 정의 필드에 대한 부모 엔터티의 이름입니다. 위의 예에서 이 이름은 'Projects'입니다.

CustomFieldTypeUID

사용자 정의 필드의 고유 식별자입니다.

CustomFieldName

사용자 정의 필드의 이름입니다.

SecondaryCustomFieldTypeUID

해당 사용자 정의 필드의 ID입니다.

DataType

사용자 정의 필드의 데이터 형식입니다.

IsMultiValueEnabled

사용자 정의 필드에 여러 값이 포함될 수 있는 경우 이 열에 1이 표시됩니다.

IsRollDown

사용자 정의 필드 값이 겹쳐서 표시되는 경우 이 열에 1이 표시됩니다.

LookupTableUID

사용자 정의 필드에서 코드 체계표를 사용하면 이 열에 해당 고유 식별자가 표시되고, 그렇지 않으면 이 열은 null입니다.

LookupTableName

사용자 정의 필드에서 코드 체계표를 사용하면 이 열에 해당 이름이 표시되고, 그렇지 않으면 이 열은 null입니다.

LookupTableMembersViewName

Project Server에서는 정의된 각 코드 체계표에 대한 보기를 만듭니다. 모든 멤버를 선택하는 보기가 있습니다. 이 열에는 사용자 정의 필드에서 사용하는 코드 체계표의 멤버가 포함된 보기의 이름이 표시됩니다.

LookupTableHasMultipleLevels

코드 체계표에 둘 이상의 수준에서 정의된 값이 있는 경우 이 열에 1이 표시됩니다.

ColumnPoolColumnName

사용자 정의 필드 값을 저장하는 열의 이름입니다.

ColumnPoolTableName

사용자 정의 필드 값을 저장하는 테이블입니다.

EntityNonTimephasedTableName

사용자 정의 필드의 부모 엔터티에 대한 시간대별이 아닌 데이터를 저장하는 테이블입니다. 예를 들어 프로젝트 사용자 정의 필드의 경우 이 열에 'MSP_EpmProject'가 표시됩니다.

CreatedDate

사용자 정의 필드를 만든 날짜입니다.

ModificationDate

사용자 정의 필드를 마지막으로 수정한 날짜입니다.

예제

두 가지 프로젝트 사용자 정의 필드 값을 표시하는 간단한 사용자 지정 보기를 만드는 방법을 보여 주는 예제는 다음과 같습니다.

이 예제에서는 자원 이름, 자원 ID, 자원 표준 작업 시간 급여, 자원 초과 작업 시간 급여 및 자원 Windows NT 계정 이름과 함께 보기에 표시할 두 가지 미리 정의된 자원 사용자 정의 필드(RBS 및 비용 종류)가 있다고 가정합니다. 사용자 정의 필드 이름이 고유하고 변경되지 않는 것이 확실한 경우 CustomFieldName 열을 사용하여 필터링할 수 있습니다. 그러나 먼저 다음과 같은 SELECT 작업을 수행하는 것이 좋습니다.

SELECT * FROM MFN_EpmGetAllCustomFieldsInformation() WHERE EntityName='Resource'

결과에서 원하는 사용자 정의 필드를 확인한 다음 CustomFieldTypeUID 값(사용자 정의 필드의 고유 ID)을 기록해 두어야 합니다.

이 예제에서는 발견하는 두 가지 고유 식별자가 다음과 같다고 가정합니다.

  • RBS의 경우 {0000783FDE84434B9564284E5B7B3F49}

  • 비용 종류의 경우 {000039B78BBE4CEB82C4FA8C0C400284}

위의 예제에서 RBS와 비용 종류에 대한 두 가지 고유 식별자를 사용하여 다음과 같은 스크립트를 작성할 수 있습니다.

--Declare the variables used
DECLARE @CommandTextnvarchar(4000)-- This is the buffer where 
--  the command will be created

-- Declare the variables used 
DECLARE
-- This is the information necessary about each custom field:
DECLARE @TableNameForCF1 nvarchar(100) 
DECLARE @ColumnNameForCF1 nvarchar(100) 
DECLARE @TableNameForCF2 nvarchar(100) 
DECLARE @ColumnNameForCF2 nvarchar(100) 
-- Get the information about RBS custom field: 
SELECT
@TableNameForCF1  = ColumnPoolTableName,
@ColumnNameForCF1 = ColumnPoolColumnName
FROMMFN_Epm_GetAllCustomFieldsInformation()
WHERE
CustomFieldTypeUID = '{0000783F-DE84-434B-9564-284E5B7B3F49}'--RBS ID
-- Get the information about Cost Type custom field: 
SELECT
@TableNameForCF2 = ColumnPoolTableName, 
@ColumnNameForCF2 = ColumnPoolColumnName
FROMMFN_Epm_GetAllCustomFieldsInformation()
WHERE 
CustomFieldTypeUID = '{000039B7-8BBE-4CEB-82C4-FA8C0C400284}'-- Cost Type ID
--Now we can build the SELECT command that will get the data in the view
SET @CommandText = 'SELECT ResourceUID, ResourceName, ResourceNTAccount, '  +
'ResourceStandardRate, ResourceOvertimeRate,'
--If both custom fields are allocated in the same column pool table, 
--  we just need to join with it once 
IF @TableNameForCF1 = @TableNameForCF2 
SET @CommandText = @CommandText + ' RCFV.' + @ColumnNameForCF1 + ', ' +
'RCFV.'+ @ColumnNameForCF2 + '' +
'FROM MSP_EpmResource' +
'INNER JOIN ' + @TableNameForCF1 + ' AS RCFV' +
'  ON MSP_EpmResource.ResourceUID = RCFV.EntityUID'
ELSE 
SET @CommandText = @CommandText + ' RCF1V.' + @ColumnNameForCF1 + ', ' +
'RCF2V.'+ @ColumnNameForCF2 + '' +
'FROM MSP_EpmResource' +
'INNER JOIN ' + @TableNameForCF1 + ' AS RCFV1' +
'  ON MSP_EpmResource.ResourceUID = RCFV1.EntityUID' +
'INNER JOIN ' + @TableNameForCF2 + ' AS RCFV2' +
'ON MSP_EpmResource.ResourceUID = RCFV2.EntityUID'
--Now we have the command, we can execute it 
SET @CommandText = 'CREATE VIEW MySampleView AS ' + @CommandText 
EXECsp_executesql @CommandText

사용자 정의 필드 인덱스 만들기

특정 사용자 정의 필드의 값이 저장된 테이블의 열을 찾는 것은 복잡할 수 있습니다. 따라서 Project Server에는 사용자 정의 필드와 인덱스 매개 변수를 입력으로 사용하여 적절한 열에 대한 인덱스를 만드는 두 가지 저장 프로시저가 있습니다.

도우미 저장 프로시저

일부 보고서에서 사용하는 쿼리의 성능을 높이기 위해 사용자 정의 필드에 인덱스가 필요한 경우 다음 메서드를 사용할 수 있습니다.

메서드 1:

PROCEDURE MSP_CreateCustomFieldIndexByUID(@CustomFieldTypeUIDuniqueidentifier, @PadIndex bit= NULL,@FillFactorsmallint= NULL,@NoRecomputeStatistics bit= NULL,@SortInTempDB bit= NULL,@FileGroupnvarchar(400)= NULL);

메서드 2:

PROCEDURE MSP_CreateCustomFieldIndexByName(@customFieldName [NAME], @customFieldEntityName [NAME] = NULL,@PadIndex bit= NULL,@FillFactorsmallint= NULL,@NoRecomputeStatistics bit= NULL,@SortInTempDB bit= NULL,@FileGroupnvarchar(400)= NULL);

MSP_Epm_CreateCustomFieldIndexByUID의 매개 변수

다음 매개 변수는 사용자 정의 필드를 식별합니다.

매개 변수 설명

@CustomFieldTypeUID

인덱스가 만들어질 사용자 정의 필드의 고유 ID입니다.

인덱스를 정의하는 매개 변수는 다음과 같습니다.

매개 변수 설명

@PadIndex

선택 요소로서 인덱스의 중간 수준에서 각 페이지에 열어 둘 공백을 지정합니다.

@FillFactor

선택 요소로서 Microsoft SQL Server에서 인덱스 작성 중 만들어야 하는 각 인덱스 페이지의 리프 수준을 나타내는 비율을 지정합니다. 이 매개 변수에는 1에서 100 사이의 값이 있어야 합니다.

@NoRecomputeStatistics

선택 요소로서 값이 1이면 기한이 지난 인덱스 통계가 자동으로 다시 계산되지 않습니다.

@SortInTempDB

선택 요소로서 값이 1이면 인덱스를 작성하는 데 사용되는 중간 정렬 결과가 tempdb 데이터베이스에 저장됩니다.

@FileGroup

선택 요소로서 지정된 파일 그룹에 대한 인덱스가 만들어집니다.

MSP_Epm_CreateCustomFieldIndexByName의 매개 변수

다음 매개 변수는 사용자 정의 필드를 식별합니다.

매개 변수 설명

@CustomFieldName

인덱스가 만들어질 사용자 정의 필드의 이름입니다.

@CustomFieldEntityName

선택 요소로서 사용자 정의 필드가 정의된 엔터티의 이름입니다. 예를 들어 프로젝트 사용자 정의 필드의 경우 Project이고 자원 사용자 정의 필드의 경우 Resource입니다.

인덱스를 정의하는 매개 변수는 다음과 같습니다.

매개 변수 설명

@PadIndex

선택 요소로서 인덱스의 중간 수준에서 각 페이지에 열어 둘 공백을 지정합니다.

@FillFactor

선택 요소로서 SQL Server에서 인덱스 작성 중 만들어야 하는 각 인덱스 페이지의 리프 수준을 나타내는 비율을 지정합니다. 이 매개 변수에는 1에서 100 사이의 값이 있어야 합니다.

@NoRecomputeStatistics

선택 요소로서 값이 1이면 기한이 지난 인덱스 통계가 자동으로 다시 계산되지 않습니다.

@SortInTempDB

선택 요소로서 값이 1이면 인덱스를 작성하는 데 사용되는 중간 정렬 결과가 tempdb 데이터베이스에 저장됩니다.

@FileGroup

선택 요소로서 지정된 파일 그룹에 대한 인덱스가 만들어집니다.

인덱스 작성을 정의하는 매개 변수에 대한 자세한 내용은 MSDN Library에서 CREATE INDEX 명령에 대해 설명하는 CREATE INDEX(Transact-SQL)(https://go.microsoft.com/fwlink/?linkid=94749\&clcid=0x412)를 참조하십시오.

두 프로시저의 반환값

이전 프로시저의 반환값은 다음과 같습니다.

설명

0

성공. 인덱스가 성공적으로 만들어졌습니다.

-1

요청된 사용자 정의 필드를 찾지 못했기 때문에 인덱스가 만들어지지 않았습니다.

-2

인덱스가 이미 있습니다.

-3

인덱스가 만들어지지 않았습니다. CREATE INDEX 문 실행이 실패했습니다.

-4

CREATE INDEX 문을 생성하지 못했습니다. 이 문은 텍스트 변수에서 생성된 다음 동적으로 실행됩니다. 이 오류는 명령 문자열 작성이 실패하는 경우 반환됩니다.

-5

지정된 사용자 정의 필드를 이 메서드로 인덱싱할 수 없습니다. 제공된 저장 프로시저를 통해 인덱싱할 수 없는 사용자 정의 필드의 유형(예: 다중값 사용자 정의 필드)이 있습니다.

-6

둘 이상의 사용자 정의 필드가 지정된 기준과 일치하기 때문에 인덱스를 만들 수 없습니다. 서로 다른 엔터티에서 이름이 동일한 사용자 정의 필드가 두 개 이상 있고 이름을 통해 사용자 정의 필드를 인덱싱하는 메서드가 엔터티 이름을 제공하지 않고 사용자 정의 필드 이름만 사용하여 호출됩니다.

예제

다음 예제에서는 두 가지 미리 정의된 자원 사용자 정의 필드 중 하나인 비용 종류를 사용합니다. 사용자 정의 필드를 식별하는 두 가지 메서드(ID 또는 이름으로 식별)도 있습니다. 두 메서드의 사용 예제가 아래에 있지만 ID를 사용하여 사용자 정의 필드를 식별하는 것이 좋습니다.

자원 사용자 정의 필드 “비용 종류"에 대한 인덱스를 이름을 통해 만들려면 다음을 호출합니다.

EXECMSP_Epm_CreateCustomFieldIndexByName'Cost Type', 'Resource'

이 사용자 정의 필드의 인덱스를 ID를 통해 만들려면 다음을 호출합니다. MFN_EpmGetAllCustomFieldsInformation 함수를 사용하여 사용자 정의 필드 UID를 가져오는 방법에 대한 자세한 내용은 이전 섹션을 참조하십시오.

EXECMSP_Epm_CreateCustomFieldIndexByUID'{000039B7-8BBE-4CEB-82C4-FA8C0C400284}'

보기와 인덱스 연결

위의 메서드를 통해 이전 섹션에서 설명한 대로 사용자 정의 필드에 인덱스를 적용하고 대상이 지정되거나 잘린 보기를 만들어 보고서 생성을 최적화할 수 있습니다. 그러나 RDB를 새로 고치는 동안 사용자 정의 필드를 사용하는 사용자 지정된 보기와 인덱스가 무효화될 수 있습니다.

이러한 현상은 새로 고치는 동안 모든 사용자 정의 필드 열 그룹 테이블이 지워지고 모든 사용자 정의 필드가 RDB에서 삭제되기 때문에 발생합니다. 다시 동기화하는 프로세스 중에 사용자 정의 필드 할당 순서가 변경될 수도 있습니다. 이는 사용자 정의 필드 값이 다른 열이나 심지어는 다른 테이블에 저장될 수 있음을 의미합니다.

예를 들어 두 가지 텍스트 사용자 정의 필드인 CF1과 CF2가 있고 먼저 CF1이 만들어진 다음 CF2가 만들어진 경우, CF1은 테이블의 CFVal0 열을 가져오고 CF2는 CFVal1을 가져옵니다. 열 그룹 테이블은 다음과 유사합니다.

EntityUID CFVal0 CFVal1 CFVal2 CFVal3 …

AF129A8C-DCB5-4FB0- 9E30-406458614A31

Under budget

On schedule

15

NULL

4D607B14-E40C-4549- 8E92-45A3A96D6892

No baseline

No baseline

NULL

NULL

8496EA23-4B25-4DBE- B68A-755A27246842

Over budget

On schedule

15

NULL

CF1이 삭제되면 테이블은 다음과 유사합니다.

EntityUID CFVal0 CFVal1 CFVal2 CFVal3 …

AF129A8C-DCB5-4FB0- 9E30-406458614A31

NULL

On schedule

15

NULL

4D607B14-E40C-4549- 8E92-45A3A96D6892

NULL

No baseline

NULL

NULL

8496EA23-4B25-4DBE- B68A-755A27246842

NULL

On schedule

15

NULL

그러나 새로 고친 후 열 풀의 열이 처음부터 다시 채워지고 CF1은 더 이상 존재하지 않으며 CF2가 이제 CFVal0 열을 차지합니다. 테이블은 다음과 유사합니다.

EntityUID CFVal0 CFVal1 CFVal2

AF129A8C-DCB5-4FB0- 9E30-406458614A31

On schedule

15

NULL

4D607B14-E40C-4549- 8E92-45A3A96D6892

On schedule

NULL

NULL

8496EA23-4B25-4DBE- B68A-755A27246842

On schedule

15

NULL

RDB를 새로 고친 후 CF2를 가리키는 대신 CFVal1을 가리키는 사용자 지정된 보기나 인덱스를 이전에 만든 경우 이러한 보기나 인덱스가 지금은 다른 사용자 정의 필드를 가리키고 있습니다. 즉, 이 경우에 인덱스는 잘못된 열에 있게 되며 이로 인해 문제가 발생합니다. 이 문제를 해결하려면 보고 성능을 높이기 위해 사용자 지정된 보기나 인덱스를 만드는 경우 저장 프로시저를 만드는 것도 고려해야 합니다.

PROCEDURE MSP_OnRefreshCompleted();

이 저장 프로시저가 있으면 RDB를 성공적으로 새로 고친 후 자동으로 호출됩니다. 이 저장 프로시저는 사용자 정의 필드 인덱스 및/또는 사용자 지정된 보기를 다시 만듭니다.

예제

위의 두 예제의 변경 사항이 RDB를 새로 고친 후 유효하게 유지되도록 하려면 두 스크립트를 저장 프로시저로 변환하고 이름을 MSP_OnRefreshCompleted로 지정해야 합니다. 또한 이 저장 프로시저를 재진입셩으로 만들어야 합니다. 즉, 여러 번 연속적으로 호출하는 경우 제대로 실행되도록 만들어야 합니다.

CREATE PROCEDUREMSP_OnRefreshCompleted 
AS 
BEGIN
-- Declare the variables used
DECLARE @CommandTextnvarchar(4000)-- This is the buffer where the commandwill be created
-- This is the information necessary about each custom field: 
DECLARE @TableNameForCF1 nvarchar(100)
DECLARE @ColumnNameForCF1 nvarchar(100)
DECLARE @TableNameForCF2 nvarchar(100)
DECLARE @ColumnNameForCF2 nvarchar(100) 
DECLARE@ViewNamenvarchar(100)SET @ViewName ='MySampleView'
--Drop the old view, if one exists 
IFEXISTS(SELECT*FROMdbo.sysobjects WHEREid =OBJECT_ID('[dbo].['+@ViewName +']') AND 
OBJECTPROPERTY(id,'IsView')= 1) 
BEGIN 
SET@CommandText ='DROP VIEW [dbo].['+ @ViewName +']' 
EXECsp_executesql@CommandText 
END
-- Get the information about RBS custom field: 
SELECT
@TableNameForCF1  = ColumnPoolTableName,    
@ColumnNameForCF1 = ColumnPoolColumnName
FROMMFN_Epm_GetAllCustomFieldsInformation()
WHERE 
CustomFieldTypeUID = '{0000783F-DE84-434B-9564-284E5B7B3F49}'--RBS ID
-- Get the information about Cost Type custom field:
SELECT
@TableNameForCF2 = ColumnPoolTableNam
@ColumnNameForCF2 = ColumnPoolColumnName e, 
FROMMFN_Epm_GetAllCustomFieldsInformation()
WHERE
CustomFieldTypeUID = '{000039B7-8BBE-4CEB-82C4-FA8C0C400284}'-- Cost Type ID
--Now we can build the SELECT command that will get the data in the view
SET @CommandText = 'SELECT ResourceUID, ResourceName, ResourceNTAccount, '  +
'ResourceStandardRate, ResourceOvertimeRate,'
--If both custom fields are allocated in the same column pool table, we just need to join with it once 
IF @TableNameForCF1 = @TableNameForCF2 
SET @CommandText = @CommandText + ' RCFV.' + @ColumnNameForCF1 + ', ' +
'RCFV.'+ @ColumnNameForCF2 + '' +
'FROM MSP_EpmResource' +
'INNER JOIN ' + @TableNameForCF1 + ' AS RCFV' +
'  ON MSP_EpmResource.ResourceUID = RCFV.EntityUID' 
ELSE 
SET @CommandText = @CommandText + ' RCF1V.' + @ColumnNameForCF1 + ', ' +
'RCF2V.'+ @ColumnNameForCF2 + '' +
'FROM MSP_EpmResource' +
'INNER JOIN ' + @TableNameForCF1 + ' AS RCFV1' +
'  ON MSP_EpmResource.ResourceUID = RCFV1.EntityUID' +
'INNER JOIN ' + @TableNameForCF2 + ' AS RCFV2' +
'ON MSP_EpmResource.ResourceUID = RCFV2.EntityUID'
--Now we have the command, we can execute it 
SET @CommandText = 'CREATE VIEW MySampleView AS ' + @CommandText 
EXECsp_executesql @CommandText
-- Clear all the custom field indexes
EXECMSP_Epm_ClearAllCustomFieldIndexes
-- Re-Create all the indexes
EXECMSP_Epm_CreateCustomFieldIndexByUID'{000039B7-8BBE-4CEB-82C4-FA8C0C400284}' 
END 
GO 
GRANTEXECONdbo.MSP_OnRefreshCompleted_TestTOProjectServerRole 
GO

이제 사용자 지정된 보기 "MySampleView" 및 "비용 종류"에 대한 사용자 정의 필드 인덱스는 RDB를 새로 고친 후 자동으로 다시 적용됩니다.