Azure 테이블 저장소 레시피 – StartsWith 구현하기

안녕하세요. Windows Azure MVP 남정현입니다.


Windows Azure Storage는 전통적인 데이터베이스 시스템과는 다르게 대용량 데이터를 처리하기 위한 방향으로 아키텍처가 구성되어있습니다. 이런 이유로, 일상적으로 사용하는 RDBMS의 컨텐츠를 Windows Azure Storage로 로드하거나 덤프를 만드는 것은 가능하지만, Windows Azure Storage 위에 올라온 레코드에 대해서 복잡한 쿼리를 수행하는 것은 어렵습니다. 이런 제약 사항 때문에 LIKE 검색 같은 기능은 사용할 수 없고, 오로지 데이터 정렬 순서에 의존하는 검색 방법만을 사용할 수 있습니다.


http://blogs.microsoft.co.il/blogs/oshvartz/archive/2012/09/19/azure-table-storage-limitations-and-solutions-workarounds-part-2.aspx


위의 글에서 소개하는 Workaround를 프로그래밍 방식으로 만들어 볼 수 있을까 고민하다가 오늘 레시피를 올리게 되었습니다. 이 코드를 사용하면 어떤 문자열이 있으면 해당 문자열을 순차적으로 검색하여 일치하는 모든 문자열을 반환하는 쿼리 식을 완성해줍니다.


코드 살펴보기


public static string CreateStartsWithQuery(string attributeName, string needle) {
 attributeName = String.Concat(attributeName);
 needle = String.Concat(needle).Replace(“‘”, “””);
 if (attributeName.Length < 1 || needle.Length < 1)
  return String.Empty;
 return String.Format(
  “({0} ge ‘{1}’ and {0} lt ‘{2}’)”,
  attributeName, needle,
  String.Concat(needle.Substring(0, needle.Length – 1), (char)(needle[needle.Length – 1] + 1))
 );
}


위와 같은 유틸리티 메서드를 만들었습니다. Windows Azure Storage SDK 최신 버전의 경우 문자열로 직접 Query를 질의하도록 되어있으며 여기에 바로 쓸 수 있는 문자열을 반환합니다.


코드의 내용을 한 줄씩 살펴보면 이렇습니다.



  • 매개 변수로는 attributeName과 needle을 받습니다. attributeName이 검색하려는 테이블 저장소 상의 엔티티 속성 이름입니다. 그리고 needle은 매칭시키려는 앞 부분의 문자열입니다.

  • needle의 경우 작은 따옴표는 두 번 쓰도록 하여 이스케이프 처리하였습니다. 이렇게 만들면 작은 따옴표를 쿼리식 안에서 정확히 지정할 수 있습니다.

  • 안전한 쿼리 수행을 위하여 빈 문자열이 들어오는 경우는 빈 문자열을 반환합니다. String.Concat 정적 메서드의 기본 동작에 의하여 String에 Null 참조가 지정되는 경우 빈 문자열로 변환됩니다.

  • 실제 비교 식의 원리는 이렇습니다. ABC로 시작하는 문자열을 찾기 위하여 문자열을 오름차순으로 정렬했을 때 ABC 그 자체, 혹은 그 이후로 나오는 모든 데이터에 대해, 해당 문자열 바로 다음에 오는 문자열까지로 검색 범위를 한정합니다.

위의 코드에 검색어로 “아무개”를 지정하면 다음과 같은 쿼리 식이 생성됩니다.


(Category ge ‘아무개’ and Category lt ‘아무객’)


즉, 아무개와 아무개로 시작하는 모든 문자열들 중 아무객보다 빨리오는 문자열만을 찾는다는 의미로 쿼리가 완성되는 것입니다. 만약 여러 조건으로 매칭하기를 원한다면 아래와 같이 쿼리식을 쓸 수 있습니다.


(Category ge ‘아무개’ and Category lt ‘아무객’) and (Category ge ‘철수’ and Category lt ‘철숙’) and (Category ge ‘영희’ and Category lt ‘영흭’)


위와 같이 작성함으로서 아무개로 시작하는 Category, 철수로 시작하는 Category, 영희로 시작하는 Category를 가지는 레코드들을 한꺼번에 얻어올 수 있습니다.


Visual Studio 데이터베이스 탐색기에서 테스트하기


위의 코드를 이용하여 만든 쿼리식이 잘 작동하는지 살펴볼까요? 쌀/과일/농수축산물 » 쌀/찹쌀/현미라는 문자열로 시작하는 모든 레코드를 검색하기 위하여 위의 코드로 아래와 같이 쿼리식을 만들었습니다.



(Category ge ‘쌀/과일/농수축산물 » 쌀/찹쌀/현미’ and Category lt ‘쌀/과일/농수축산물 » 쌀/찹쌀/현믹’)

Visual Studio 데이터베이스 탐색기에서 Table 저장소를 직접 쿼리할 수 있습니다. 한 번 살펴볼까요?



잘 작동합니다. 🙂


PartitionKey나 RowKey로 등록한 엔티티가 아니어도 StartsWith에 해당되는 검색 조건을 빠르게 검색하여 가져올 수 있다는 것은 쓰임새가 많을겁니다. 특히 지금과 같이 카테고리 탐색을 하려는 경우에는 유용하게 사용할 수 있습니다.

댓글 남기기