필터 및 API 스크립트를 최적화하여 Shotgun 사이트 속도 개선

Shotgun에는 필터 패널 및 정교한 API 기반 통합 스크립트의 개발을 통해 페이지를 커스터마이즈할 수 있는 유연성이 있습니다. 이러한 유연성으로 인해 직관적으로 적정하지만 실제 성능은 떨어지고 시스템 리소스를 많이 사용하는 복잡한 필터 또는 고급 필터를 만들기 쉽습니다.

이 문서의 목적은 Shotgun 사용자가 특히 API 스크립트를 작성하고 복잡하면서도 빠르고 효율적인 필터를 만드는 방법을 이해할 수 있도록 돕는 것입니다. 잘 작성된 대부분의 필터는 아주 짧은 시간에 완료됩니다. 그러나 정확하게 동일한 데이터를 반환하는 비효율적인 필터는 완료하는 데 몇 초 또는 몇 분까지도 걸릴 수 있습니다.

필터 성능을 최적화하려면 다음을 수행하는 것이 좋습니다.

  • 데이터베이스가 로드하고 처리해야 하는 테이블 행의 수를 최소화합니다.
    • 이 방법을 가장 효율적으로 수행하려면 링크된 필드, 다중 엔티티 필드, 태그 및 URL 필드 등 다른 테이블에 속한 필드가 아닌 기본 엔티티의 테이블 열에서 필터를 사용합니다.
  • 텍스트 일치 필터는 느리므로 사용하지 않는 것이 좋으며 이러한 목적으로 단독으로 사용하지 않아야 합니다.

느린 필터의 예

필터 예

위의 버전 페이지 필터 예제는 다음과 같은 이유로 느리게 수행됩니다.

  1. 모든 필터가 "텍스트 일치" 필터입니다. "이름에 포함(name contains)", "포함(contains)", "시작(starts with)" 등의 텍스트 일치 필터는 데이터베이스의 평가 속도가 느립니다.
  2. 이러한 텍스트 일치 필터의 경우 확인해야 할 버전 수가 너무 많습니다. 모든 버전을 확인해야 합니다.
  3. 여러 필터가 링크된 필드에 관한 것이므로 데이터베이스가 필터를 평가하기 위해 다른 테이블의 데이터를 가져와야 합니다.

게다가 버전 테이블은 가장 빨리 커질 수 있는 테이블이기 때문에 이 필터는 시간이 갈수록 점점 더 느려지게 됩니다.

복잡한 필터의 성능을 개선하려면 대부분의 버전을 고려 사항에서 좀 더 효율적으로 제거할 수 있는 필터를 추가합니다. 이렇게 하면 많은 버전에서 느린 텍스트 일치 쿼리를 평가할 필요가 없습니다.

무엇이 적합한지는 워크플로우에 따라 다릅니다. 워크플로우가 텍스트 일치 필터나 링크된 필드 필터에 크게 의존하는 경우 버전 또는 다른 엔티티를 보다 효율적으로 필터링할 수 있도록 워크플로우를 수정해야 할 수 있습니다. 효과적인 워크플로우 변경의 한 가지 예는 상태 필드를 더 잘 사용할 수 있도록 하는 것입니다.

필터 개선의 예

개선된 필터 예

이제 보다 효율적인 세 개의 새 필터 그룹을 추가했습니다. 이러한 세 개의 필터는 스튜디오의 대다수 버전을 제거하여 이 복잡한 필터를 개선하므로 느린 패턴 일치 필터 및 링크된 필드 필터가 훨씬 적은 버전에서 평가됩니다.

  • 프로젝트(Project): "일치함(is)" 필터를 사용하여 프로젝트를 명시적으로 제한했습니다. 이렇게 하면 다른 모든 과거 및 현재 프로젝트의 모든 버전을 효과적으로 제거하며 스튜디오에 많은 프로젝트가 있을 경우 큰 차이를 만듭니다. 이 경우 프로젝트 필터를 최신으로 유지하려면 워크플로우를 변경해야 할 수 있습니다. 이 페이지의 사용자가 프로젝트에 관계없이 모든 VFX 편집 버전을 수집하는 데 사용되었기 때문입니다.
  • 상태(Status): 각 버전을 리뷰한 후에는 상태를 "보류 중인 리뷰(Pending Review)"에서 "보았음(Viewed)"으로 업데이트하는 것이 적절한 "모범 사례"입니다. 이렇게 하면 버전 페이지를 적은 수의 관련 새 버전으로 쉽게 필터링할 수 있습니다.
  • 만든 날짜(Date Created)(또는 업데이트 날짜(Date Updated)): 모든 엔티티에 있는 이 필드는 효율적으로 페이지 컨텐츠를 줄여서 필터링하는 데 유용합니다.

필터 성능 상세 정보

1. 텍스트 일치 필터는 느립니다.

텍스트 일치 필터가 느린 이유는 데이터베이스가 결과의 일부가 될 수 있는 모든 테이블 행에 대해 복잡한 테스트를 수행해야 하기 때문입니다. 이러한 필터 유형에 사용할 수 있는 최적화 전략은 없습니다.

이 지침은 텍스트 일치 필터를 절대 사용하지 않아야 한다는 의미는 아닙니다. 텍스트 일치 필터만이 아니라 그 외에도 보다 효율적인 다른 종류의 필터를 사용하여 결과를 줄여야 합니다(두 번째 지침에 있으며 아래에서 자세히 설명합니다). 이러한 다른 필터는 텍스트 일치 필터가 더 적은 테이블 행에 적용되도록 하므로 더 적은 리소스를 사용합니다.

다음은 본질적으로 느린 텍스트 일치 필터 유형입니다.

  • contains
  • does not contain (not_contains)
  • starts with (starts_with)
  • ends with (ends_with)
  • name contains (name_contains)
  • name doesn't contain (name_not_contains)

텍스트 일치 쿼리는 다음 경우에 특히 느립니다.

  • 엔티티 검색의 유일한 필터인 경우
  • "or"("하나 이상") 필터 그룹의 일부 필터인 경우

이 경우, 또 다른 효율적인 필터 유형을 사용하여 결과의 수를 줄이는 복잡한 필터보다 수백 또는 수천 배 더 느릴 수 있습니다.

현재 성능이 낮은 API 스크립트용 텍스트 일치 필터에 의존하는 경우 '텍스트 일치를 피하도록 통합 방법 변경' 섹션을 확인할 수 있습니다.

2. 엔티티 고유 필드에서 작동하는 간단하고 효율적인 필터를 사용하여 반환되는 엔티티 수를 줄입니다.

이것이 복잡한 필터가 잘 수행되도록 하는 가장 중요한 원칙입니다.

엔티티 고유 필드에 대한 효율적인 필터를 사용하면 데이터베이스에서 즉각적으로 신속하게 대부분의 엔티티 테이블 행을 고려 사항에서 제거할 수 있습니다. 따라서 데이터베이스가 후속 단계에서는 더 적은 데이터를 처리합니다. 다른 필터, 정렬 또는 그룹 지정 등 복잡한 필터의 나머지 모든 부분은 이점이 가중되어 결과적으로 더 빨라집니다.

최종 결과를 더 작게 설정하면 데이터 형식 지정 및 API 스크립트 또는 Shotgun 페이지에 응답하기 위한 네트워크 리소스 사용이 줄어들어 성능이 더 향상됩니다.

어떤 종류의 필터가 이렇게 효율적으로 성능을 향상시킬 수 있습니까?

  1. 효율적인 "축소" 필터는 고려 대상인 엔티티 수를 대폭 줄여야 합니다.
    100만 개의 버전이 있을 경우 버전이 8000개뿐인 프로젝트에 대한 필터링은 도움이 됩니다. 반면, 80만 개의 버전을 포함하고 "보았음(viewed)"과 같은 상태에 대한 필터링은 성능이 개선되지 않습니다.
  2. 필터는 AND('모두') 필터 그룹 내에 있어야 합니다.
    Python API에서 필터의 최상위 배열 조건은 AND 그룹입니다. 다음 예에서 "entity"에 대한 필터는 행을 대폭 감소시킵니다.
    EFFICIENT_filters = [[ "entity", "is", { "type": "Asset", "id": 9 } ]]

    그러나 필터가 다른 필터 그룹 내의 하위 그룹에 있는 경우 그 위 수준에서 OR('하나 이상') 필터 그룹 내에 있지 않아야 합니다. 다음 예에서는 "entity"에 대한 필터가 성능을 향상시키지 않습니다.
    SLOW_filters = [ 
      {
        "filter_operator":"or",
        "filters":[
          [ "code", "contains", "e" ],
          [ "entity", "is", { "type": "Asset", "id": 9 } ]
        ]
      }
    ]

    모든 수준에서 OR 그룹 내에 있는 필터는 모든 테이블 행에 적용할 필요가 없으므로 고려 대상인 행 수가 줄어들지 않습니다. 예외를 보려면 아래의 고급 성능 섹션을 참조하십시오.
  3. 필터 필드가 링크된 필드가 아닙니다.
    링크된 필드에 대한 필터는 데이터베이스가 다른 엔티티의 테이블에서 행을 찾아 평가해야 하기 때문에 행을 제거하는 빠른 방법이 아닙니다. 링크된 필드에 대한 필터가 필요할 수 있지만 효율적으로 행을 제거하려면 엔티티 자체에 속하는 필드에 대한 추가 필터도 사용합니다. 예외를 보려면 아래의 고급 성능 섹션을 참조하십시오.
  4. 필터 필드의 데이터 유형이 다중 엔티티 또는 태그 목록이 아닙니다.
    다중 엔티티 및 태그 필드는 링크된 필드와 유사하므로 빠르지 않습니다. 이러한 필드에 대한 필터는 데이터베이스가 다른 테이블의 행을 평가해야 하므로 기본 테이블에서 행을 제거하는 효율적인 방법이 아닙니다.
    다중 엔티티 필드 또는 태그 필드에 대한 필터링이 잘못된 것은 아니지만 최상의 성능을 위해 보다 효율적으로 엔티티 수를 줄일 수 있는 추가 필터가 필요합니다.
    다중 엔티티 필드와 달리 단일 엔티티 필드는 빠르고 좋은 "축소" 필터가 될 수 있습니다. 왜냐하면 기본 엔티티 테이블에 속하기 때문입니다.
  5. 필터가 텍스트 일치 필터 유형이 아닙니다.
    텍스트 일치 필터는 느리고 데이터베이스가 최적화할 수 없습니다.
    "is", "is_not", "greater than", "is after", "in the next __ weeks" 등 다른 모든 필터 유형은 필터가 행 수를 대폭 제거하는 한 비교적 효율적입니다.

다음은 많은 버전을 가진 사이트에 대해 느리게 수행하는 필터입니다.

SLOW_filters = [
  {
    "filter_operator":"or",
    "filters":[
      [ "code", "contains", "_rev_" ],
      [ "code", "contains", "_redo_" ]
    ]
  }
]

확실하게 행을 제거할 수 있는 방법은 프로젝트나 날짜 범위에 대한 제한입니다. 이 두 제한을 모두 시도한 예가 아래에 나와 있습니다.

최상위 수준 필터는 OR("하나 이상") 필터입니다. 새 축소 필터는 OR 필터 그룹 외에 있어야 합니다.

EFFICIENT_filters = [
  [ "project", "is", { "type": "Project", "id": 49 } ],
  [ "updated_at", "in_last", [ 1, "WEEK" ] ],
  {
    "filter_operator":"or",
    "filters":[
      [ "code", "contains", "_rev_" ],
      [ "code", "contains", "_redo_" ]
    ]
  }
]

데이터베이스 인덱스의 이점

일부 필드는 데이터베이스에서 인덱스되어 있으므로 특히 효율적인 필터링을 제공할 수 있습니다. 인덱스된 필드에 대한 필터를 사용하면 데이터베이스가 인덱스된 필드 값의 효율적인 해시 인덱스를 참조하여 고려할 행을 결정할 수 있습니다.

참고: 인덱스된 필드를 사용하면 제공된 다른 필터 지침을 수행하지 않는 한 큰 이점이 없습니다. 목표는 처리되는 행 수를 효율적으로 줄이는 것이며 인덱스된 필드를 사용하는 것이 도움이 됩니다.

데이터베이스 인덱스는 데이터베이스에서 읽기 성능을 일부 개선할 수 있지만 데이터베이스에 쓰기 속도는 느려질 수 있습니다. 쓸 때마다 인덱스를 업데이트해야 하기 때문입니다. 따라서 Shotgun은 모든 테이블의 모든 필드를 인덱싱하지는 않습니다.

각 엔티티 유형에 대해 기본적으로 Shotgun은 다음 공통 필드를 인덱싱합니다.

  • Id(id)
  • 프로젝트(Project)(project)
  • 상태(Status)(sg_status_list)
  • 만든 날짜(Date Created)(created_at)
  • 업데이트 날짜(Date Updated)(updated_at)

이러한 필드 중 하나를 사용하는 긍정 필터(예: 'is' 또는 'greater than')는 인덱스되지 않은 필드에 대한 필터보다 훨씬 빠르게 고려 대상에서 행을 제거하여 근본적으로 성능을 개선할 수 있습니다.

'is not'과 같은 부정 필터를 사용하면 일반적으로 데이터베이스가 인덱스를 사용할 수 없습니다. 그러나 부정 필터는 처리해야 할 행 수를 대폭 줄이는 한 여전히 성능 개선에 유용합니다.

인덱스 효과의 한 예로, API 이벤트 폴링 스크립트는 이벤트 로그 항목(Event Log Entry) id 필드에 대한 필터를 사용하여 이벤트 로그 항목(Event Log Entry) 테이블 행을 적은 수의 새 행으로만 제한합니다(예: "Id is greater than N"). 이벤트 로그 항목(Event Log Entry) 테이블이 가장 큰 테이블임에도 불구하고 이 필터는 매우 큰 클라이언트 데이터베이스에 대해 매우 신속하게 수행합니다.

그러나 데이터베이스는 언제 인덱스를 사용할지 또는 어떤 인덱스를 사용할지 결정하기 위해 각 인덱스별로 관리하는 복잡한 추론과 통계를 사용합니다. 결과적으로 이러한 인덱스된 필드 중 하나에 대한 필터를 사용하여 성능 개선 효과를 얻을 수 있는 경우를 예측하기가 어렵습니다.

따라서 인덱스된 필드에 대해 필터링할 필요 없이 고려 대상에서 행 수를 대폭 줄이는 효율적인 필터를 제공하는 것이 중요합니다. 일반적인 경우에 실제로 적합하지 않을 수도 있는 인덱스된 필드를 사용하기 위해 많은 노력을 기울이지 마십시오.

3. 링크된 필드는 필터당 및 필터링된 행당 누적 비용이 추가됩니다.

링크된 필드는 추가 테이블에서 행을 평가하기 때문에 오버헤드가 증가되지만 특별히 느리지는 않습니다.

기본 엔티티 테이블에서 대부분의 행을 제거하는 효율적인 필터가 존재할 경우에는 성능에 크게 부정적인 영향을 주지 않고도 링크된 필드에 대한 다른 필터가 복잡한 필터에 있을 수 있습니다.

반면, 평가할 테이블 행 수가 많은 경우에는 링크된 필드에 대한 각 필터링, 정렬 또는 그룹 지정마다 훨씬 더 큰 비용을 복잡한 필터에 소요하게 됩니다. 또한 "이중 홉" 링크된 필드는 더 많은 테이블의 행을 평가해야 하므로 더 큰 영향을 미칩니다.

텍스트 일치를 피하도록 통합 방법 변경

두 번째 지침에 따라 더 빠른 필터를 적용하지 않고 API 통합이 텍스트 일치 필터나 링크된 필드 필터에 크게 의존하는 경우에는 프로덕션 액티비티가 증가하는 만큼 통합이 잘 확장되지 않을 수 있습니다. 엔티티 자체에 속하는 필드의 정확한 일치 항목에 의존하는 접근 방법을 찾아야 합니다. 일부 작업이 필요하더라도 비용이 줄어듭니다. 예를 들어 자동으로 상태를 업데이트하거나 정확한 일치 값을 사용할 수 있는 새 목록이나 텍스트 필드를 추가하고 입력해야 할 수 있습니다.

다음은 가상 애니메이션 워크플로우에서 텍스트 일치에 의존하여 보고서용 PublishedFile 애니메이션 파일 형식을 식별하는 예제 API 요약 필터입니다.

filters = [
  {
    "filter_operator":"or","filters":[
      [ "path_cache", "contains", "/anim_face" ],
      [ "path_cache", "contains", "/anim_fine" ]
    ]
  }
]
summaries = sg.summarize(entity_type='PublishedFile', filters, summary_fields=[{'field':'id', 'type':'count'}])

프로젝트, 날짜 범위 또는 PublishedFileType 제한 등 여러 가지로 이 필터를 추가로 제한할 수 있습니다.

그러나 특정 애니메이션 파일 형식을 식별하는 것이 워크플로우에 대해 수용할 수 있는 유일한 수단인 경우에는 리소스 유형(커스텀 게시 스크립트 또는 일부 다른 방법으로 설정)에 대해 새 커스텀 목록 열을 추가하면 성능이 개선됩니다. 다음은 "My Resource Subtype"이라는 필드를 사용하는 필터입니다.

filters = [
  {
    "filter_operator":"or",
    "filters":[
      [ "sg_my_resource_subtype", "is", "anim_face" ],
      [ "sg_my_resource_subtype", "is", "anim_fine" ]
    ]
  }
]
summaries = sg.summarize(entity_type='PublishedFile', filters, summary_fields=[{'field':'id', 'type':'count'}])

이 필터는 'anim_face' 및 'anim_fine' PublishedFiles가 매우 많을 경우 여전히 느리지만 이전의 텍스트 일치 버전보다는 더 빠릅니다. 이 OR("하나 이상") 필터가 어떻게 성능을 개선할 수 있는지에 대한 자세한 정보는 아래의 고급 성능 섹션을 참조하십시오.

고급 성능 정보

OR("하나 이상") 그룹 사용

실제로 OR 그룹에서 일부 필터 조합은 테이블 행을 계속 효율적으로 제거하여 복잡한 필터 성능을 향상시킬 수 있습니다. 물론 특정 필터 및 테이블 행을 제거하는 정도에 따라 다릅니다. 통합 방법 변경 섹션에 있는 위 예제를 참조하십시오.

링크된 필드 사용

실제로, 엔티티 필드를 통해 링크된 필드를 필터링하면 계속해서 좋은 결과를 얻을 수 있습니다. 링크된 필드가 링크된 필드 값에 대한 엔티티 유형을 지정하기 때문입니다. 엔티티 필드를 통해 링크된 필터는 링크된 엔티티 유형에 해당하는 엔티티 필드 값이 거의 없는 경우 상위 엔티티 테이블의 행을 대부분 제거할 수 있습니다. 이 필터는 다중 엔티티 필드에 적용하지 않습니다.

다음은 태스크에 대한 필터의 예입니다.

filters = [[ "entity.Sequence.sg_status_list", "is", "hld" ]]

예를 들어 태스크에 대한 위 필터는 "엔티티" 필드에 시퀀스가 있는 태스크가 거의 없는 경우에 실제로 잘 수행할 수 있습니다. entity 열에 Sequence가 있는 적은 수의 태스크 행만 처리되기 때문입니다.

반면, 이러한 필터는 수백만 개의 태스크가 시퀀스에 링크된 경우 이 수백만 개의 태스크 행을 처리해야 하므로 성능이 떨어집니다.

Shotgun을 최대한 활용할 수 있는 방법에 대한 자세한 정보는 모범 사례 체크리스트를 참조하십시오.

팔로우

0 댓글

댓글을 남기려면 로그인하세요.