효율적인 쿼리 작성
학습 목표
이 유닛을 완료하면 다음을 이해할 수 있습니다.
- Force.com 쿼리 Optimizer가 쿼리 성능을 최적화하는 방법
- 선택적 쿼리의 사용이 쿼리 성능에 미치는 영향
- 쿼리 계획 도구를 사용하여 검색 쿼리를 평가하는 방법
제한
효율적인 쿼리는 성능을 향상할 뿐만 아니라, 거버너 제한에 문제가 발생하지 않도록 방지합니다. 단, 모두가 공간을 공유해야 하는 다중 테넌트 플랫폼이라는 점에 유의하세요. 또한 시스템 충돌 문제를 빠르게 유발하는 주 원인은 낮은 성능의 쿼리입니다. 이때 거버너 제한을 이용할 수 있습니다.
거버너 제한은 일종의 리소스 심판이라고 할 수 있으며, 모두가 규칙에 따라 플레이하고 리소스 파이의 평등한 몫을 받도록 보장합니다.
이 유닛에서는 제한의 제한을 받는 문제를 피하기 위해 검색 쿼리를 최적화하는 방법에 대해 알아보겠습니다.
Force.com 쿼리 Optimizer
Salesforce의 백엔드 데이터베이스는 Oracle을 사용하지만, Force.com은 자체 버전의 쿼리 Optimizer를 사용하여 비용 기반 쿼리를 평가합니다. 대부분의 비용 기반 쿼리 Optimizer와 마찬가지로, Salesforce가 사용하는 쿼리 Optimizer도 데이터에 대해 수집된 통계를 기반으로 합니다. 대부분의 통계는 매주 수집되지만, 시스템은 매시간 캐싱되는 사전 쿼리도 생성합니다.
쿼리 Optimizer는 SOQL 쿼리와 SOSL 검색을 평가합니다. 쿼리를 적절한 색인으로 라우팅하는 일종의 교통경찰 역할을 합니다. 또한 들어오는 모든 쿼리를 살펴보고, 식별되는 각 잠재 쿼리 경로에 대한 비용 값을 할당합니다. 그런 다음, 이 비용을 사용하여 사용할 실행 계획을 결정합니다.
솔직히 말씀드리자면, 쿼리 Optimizer가 실행 계획을 선택하고 임계값으로 작업하는 방식은 다소 복잡해질 수 있습니다. 하지만 .NET 개발자로서 여러분은 도전을 극복할 능력이 있습니다. 완료하면, 리소스 섹션의 링크를 통해 원하는 만큼 자세히 알아볼 수 있습니다.
모범 사례
.NET 개발자는 모범 사례에 대해 생각하는 것을 좋아합니다. 또한 도전을 즐기고, 항상 최선의 방식을 찾습니다. 이해합니다. 따라서 빠르고 효율적인 검색 쿼리를 작성하는 데 사용할 모범 사례를 배우고 싶을 것입니다.
선택적 쿼리 작성
첫 번째 유닛에서는 WHERE 절을 사용하여 필터를 적용하는 방법과 SOQL 문에 대해 다루었습니다. 이제 여러분은 AND 및 OR 절을 사용하여 여러 필드를 결합할 수도 있습니다.
따라서 WHERE 절에 필드가 많을수록 좋다는 얘기를 들어도 별로 놀라지 않으실 것입니다. 분명히 쿼리가 반환하는 데이터가 적을수록 더 좋습니다. 하지만 모든 필드가 동일하지 않다는 사실을 모르실 수 있습니다. 일부 필드는 '파워' 필드로 생각할 수 있습니다. WHERE 절에서 파워 필드를 사용하면 쿼리가 매우 빠르게 수행됩니다.
그렇다면 이러한 파워 필드가 강력한 이유는 무엇일까요? 바로 색인 때문입니다.
모든 표준 및 사용자 정의 테이블의 경우 특정 필드는 인덱싱되도록 플래그가 자동으로 지정됩니다. 이러한 필드에는 다음이 포함됩니다.
인덱싱된 필드 | 설명 |
---|---|
Id | 시스템에서 생성된 고유한 18자 필드입니다. 개체의 기본 키입니다. |
이름 | 텍스트 기반 필드입니다. |
OwnerId | 개체의 소유자에 대한 참조입니다. |
CreatedDate | 레코드가 생성된 날짜 및 시간입니다. |
SystemModStamp | 레코드의 마지막 업데이트 날짜가 포함된 읽기 전용 필드입니다. 이 필드는 유사한 LastModifiedDate가 없는 곳에서 인덱싱됩니다. 따라서 쿼리에서 이 필드를 사용하는 것이 좋습니다. |
RecordType | RecordType의 ID입니다. RecordType은 특정 사용자에게 다른 UI 결과를 제공하는 데 사용됩니다. |
마스터-세부 사항 필드 | 마스터-세부 사항 관계를 나타내는 데 사용되는 외부 키 필드입니다. |
조회 필드 | 조회 관계를 나타내는 데 사용되는 외부 키 필드입니다. |
고유 필드 | 사용자 정의 필드는 생성될 때 고유한 필드로 표시될 수 있으며, 이를 통해 사용자 정의 필드가 자동으로 인덱싱됩니다. |
외부 ID 필드 | 고유 필드와 마찬가지로 이러한 사용자 정의 필드는 외부 ID로 표시될 수 있으며, 주로 통합 목적으로 사용됩니다. |
쿼리의 WHERE 절에 이러한 인덱싱된 필드 중 하나를 사용할 때마다, 쿼리가 선택적인 것으로 간주되고 색인이 전체 테이블 스캔과 반대로 사용될 가능성이 높아집니다. 대규모 데이터베이스를 다루는 경우 이러한 점은 아무리 강조해도 지나치지 않습니다.
참고: Salesforce 고객은 지원 사례를 만들고 인덱싱된 필드가 있는 SOQL 쿼리를 포함함으로써 Salesforce 지원에 사용자 정의 색인을 요청할 수 있습니다.
색인 선택성 예외
쿼리에서 인덱싱된 필드를 사용한다고 해서 항상 올바른 것은 아닙니다. 쿼리에서 작업을 수행하여 비선택적으로 만들 수 있으므로 원치 않는 전체 테이블 스캔이 발생하기 쉽습니다. 선택적 쿼리를 작성할 때는 항상 다음과 같은 사항을 피해야 합니다.
- null 행에 대한 쿼리—필드가 비어 있거나 null인 레코드를 찾는 쿼리. 예:
SELECT Id, Name FROM Account WHERE Custom_Field__c = null
- 네거티브 필터 연산자—쿼리에 !=, NOT LIKE 또는 EXCLUDES 같은 연산자 사용. 예:
SELECT CaseNumber FROM Case WHERE Status != ‘New’
- 선행 와일드카드—다음과 같이 선행 와일드카드를 사용하는 쿼리
SELECT Id, LastName, FirstName FROM Contact WHERE LastName LIKE ‘%smi%’
- 비교 연산자가 포함된 텍스트 필드—텍스트 기반 필드에 >, <, >= 또는 <= 같은 비교 연산자 사용. 예:
SELECT AccountId, Amount FROM Opportunity WHERE Order_Number__c > 10
쿼리 계획 도구
Developer Console에는 쿼리 속도를 높일 수 있는 간단한 도구가 포함되어 있습니다. 이를 통해 쿼리 Optimizer가 동작하는 방식의 이면을 엿볼 수 있습니다. 쿼리 계획 도구는 기본적으로 활성화되지 않습니다. 다음 단계에 따라 활성화하세요.
- Setup(설정) 메뉴에서 Developer Console을 선택하여 Developer Console을 엽니다.
- Developer Console에서 Help(도움말) > Preferences(환경설정)를 선택합니다.
- Enable Query Plan(쿼리 계획 활성화)을 선택하고 true로 설정되었는지 확인합니다.
- Save(저장)를 클릭합니다.
- Query Editor(쿼리 편집기) 탭에서 Query Plan(쿼리 계획) 버튼이 Execute(실행) 버튼 옆에 있는지 확인합니다.
이제 쿼리 계획 도구가 활성화되어 쿼리를 평가하는 데 사용할 수 있습니다. 쿼리 계획 도구를 사용하여 낮은 성능의 쿼리를 평가해보겠습니다.
- Developer Console의 하단 창에서 Query Editor(쿼리 편집기) 탭을 클릭합니다.
- 기존 코드를 삭제하고 다음 코드조각을 삽입합니다.
SELECT Id, CaseNumber FROM Case WHERE Status != 'New'
- Query Plan(쿼리 계획)을 클릭합니다.
쿼리 계획 대화 상자에 쿼리 비용을 나열하고 TableScan을 수행할 테이블이 표시됩니다. 이는 올바르지 않습니다. 하단 창의 메모를 확인하세요. 결과에 대해 자세히 설명되어 있습니다.
이제 첫 번째 쿼리와 동일한 결과를 얻는 또 다른 쿼리를 살펴보겠습니다.
- 하단 창에서 Query Editor(쿼리 편집기) 탭을 클릭합니다.
- 기존 코드를 삭제하고 다음 코드조각을 삽입합니다.
SELECT Id, CaseNumber FROM Case WHERE IsClosed = true
- Query Plan(쿼리 계획)을 클릭합니다.
쿼리 계획 대화 상자에 쿼리 비용을 나열하는 테이블이 표시되지만, 이번에는 색인을 사용할 수 있음을 나타내는 또 다른 행이 표시됩니다.
쿼리 계획을 통해 실행한 두 쿼리는 모두 동일한 수의 행을 검색했지만, 실행 계획은 선택된 필드와 연산자에 따라 크게 달랐습니다. 이러한 차이는 개발 조직에 있는 데이터 양이 적기 때문에 사소해보이지만, 수백만 개의 레코드가 있는 조직의 쿼리를 비교해보면 이러한 차이는 엄청난 영향을 미칠 수 있습니다.
쿼리 계획 도구의 각 열이 표시하는 항목에 대한 자세한 내용은 리소스 섹션에서 쿼리 계획 도구에 대한 링크를 참조하세요.
추가 정보
비결정적 수식 필드가 포함된 쿼리를 생성하지 않도록 항상 유의하세요. 수식 필드는 런타임 시 필드 값을 동적으로 계산할 수 있는 사용자 정의 필드입니다. 이러한 유형의 필드는 대부분의 조직에서 애용되므로, 쉽게 남용될 수 있습니다. 시간에 따라 값이 변하는 수식 필드는 비결정적 필드로 간주됩니다. 자세한 내용은 리소스 섹션에서 'SOQL 모범 사례: Null 및 수식 필드' 링크를 참조하세요.
안타깝게도 쿼리 계획 도구를 사용하여 SOSL 쿼리를 평가할 수는 없지만, 그렇다고 해서 사용자가 이런 유형의 쿼리와 관련된 성능을 고려하지 않는 것은 아닙니다. 리소스 섹션에 있는 '모범 사례 및 성능 팁' 링크를 참조하여 SOSL 쿼리 작성 시 피해야 할 사항에 대해 자세히 알아보세요.