데이터 정렬 및 대/소문자 구분

데이터베이스의 텍스트 처리는 복잡할 수 있으며 의심할 수 있는 것보다 더 많은 사용자 주의가 필요합니다. 한 가지, 데이터베이스는 텍스트를 처리하는 방법에 따라 상당히 다릅니다. 예를 들어 일부 데이터베이스는 기본적으로 대/소문자를 구분하지만(예: Sqlite, PostgreSQL), 대/소문자를 구분하지 않는 데이터베이스도 있습니다(SQL Server, MySQL). 또한 인덱스 사용으로 인해 대/소문자 구분 및 유사한 측면은 쿼리 성능에 광범위한 영향을 미칠 수 있습니다. 대/소문자를 구분하는 데이터베이스에서 대/소문자를 구분하지 않는 비교를 강제하는 데 string.ToLower를 사용할 수 있지만 이렇게 하면 애플리케이션에서 인덱스를 사용하지 못할 수 있습니다. 이 페이지에서는 대/소문자 구분 또는 보다 일반적으로 데이터 정렬을 구성하는 방법과 쿼리 성능을 손상시키지 않고 효율적인 방식으로 데이터 정렬을 구성하는 방법을 자세히 설명합니다.

데이터 정렬 소개

텍스트 처리의 기본 개념은 텍스트 값의 순서를 지정하고 같음과 비교하는 방법을 결정하는 규칙 집합인 데이터 정렬입니다. 예를 들어 대/소문자를 구분하지 않는 데이터 정렬은 같음 비교를 위해 대/소문자와 소문자 간의 차이를 무시하지만 대/소문자 구분 데이터 정렬은 무시하지 않습니다. 그러나 대/소문자 구분은 문화권을 구분하므로(예: iI는 터키어로 다른 문자를 나타냄) 각각 고유한 규칙 집합이 있는 여러 대/소문자를 구분하지 않는 데이터 정렬이 있습니다. 데이터 정렬 범위는 대/소문자 구분을 넘어 문자 데이터의 다른 측면까지 확장됩니다. 예를 들어 독일어에서는 äae를 동일하게 처리하는 것이 바람직한 경우가 있습니다. 마지막으로 데이터 정렬은 텍스트 값의 순서도 정의합니다. 독일어는 äa 후에 오지만 스웨덴어에서는 알파벳 끝에 배치합니다.

데이터베이스의 모든 텍스트 작업은 명시적으로 또는 암시적으로 데이터 정렬을 사용하여 작업이 문자열을 비교하고 정렬하는 방법을 결정합니다. 사용 가능한 데이터 정렬 및 해당 명명 체계의 실제 목록은 데이터베이스별로 다릅니다. 다양한 데이터베이스의 관련 설명서 페이지에 대한 링크는 아래 섹션을 참조하세요. 다행히 데이터베이스는 일반적으로 데이터베이스 또는 열 수준에서 기본 데이터 정렬을 정의하고 쿼리의 특정 작업에 사용해야 하는 데이터 정렬을 명시적으로 지정할 수 있습니다.

데이터베이스 정렬

대부분의 데이터베이스 시스템에서 기본 데이터 정렬은 데이터베이스 수준에서 정의됩니다. 재정의되지 않는 한 해당 데이터 정렬은 해당 데이터베이스 내에서 발생하는 모든 텍스트 작업에 암시적으로 적용됩니다. 데이터베이스 데이터 정렬은 일반적으로 CREATE DATABASE DDL 문을 통해 데이터베이스를 만들 때 설정되며, 지정하지 않으면 기본적으로 설정 시 결정되는 일부 서버 수준 값으로 설정됩니다. 예를 들어 "영어(미국)" 컴퓨터 로캘에 대한 SQL Server 기본 서버 수준 데이터 정렬은 대/소문자를 구분하지 않는 악센트 구분 데이터 정렬인 SQL_Latin1_General_CP1_CI_AS입니다. 데이터베이스 시스템은 일반적으로 기존 데이터베이스의 데이터 정렬을 변경하는 것을 허용하지만 이렇게 하면 복잡성이 발생할 수 있습니다. 데이터베이스를 만들기 전에 데이터 정렬을 선택하는 것이 좋습니다.

EF Core 마이그레이션을 사용하여 데이터베이스 스키마를 관리하는 경우 모델의 OnModelCreating 메서드에서 다음 항목은 대/소문자를 구분하는 데이터 정렬을 사용하도록 SQL Server 데이터베이스를 구성합니다.

modelBuilder.UseCollation("SQL_Latin1_General_CP1_CS_AS");

열 데이터 정렬

데이터 정렬은 텍스트 열에 정의되어 데이터베이스 기본값을 재정의할 수도 있습니다. 이 기능은 특정 열이 대/소문자를 구분하지 않는 반면 나머지 데이터베이스는 대/소문자를 구분해야 하는 경우에 유용할 수 있습니다.

EF Core 마이그레이션을 사용하여 데이터베이스 스키마를 관리하는 경우 다음에서는 대/소문자를 구분하도록 구성된 데이터베이스에서 Name 속성의 열을 대/소문자를 구분하지 않는 열로 구성합니다.

modelBuilder.Entity<Customer>().Property(c => c.Name)
    .UseCollation("SQL_Latin1_General_CP1_CI_AS");

쿼리의 명시적 데이터 정렬

경우에 따라 서로 다른 쿼리에 의해 서로 다른 데이터 정렬을 사용하여 동일한 열을 쿼리해야 합니다. 예를 들어 한 쿼리는 열에서 대/소문자를 구분하는 비교를 수행해야 하는 반면, 다른 쿼리는 동일한 열에서 대/소문자를 구분하지 않는 비교를 수행해야 할 수 있습니다. 쿼리 자체 내에서 데이터 정렬을 명시적으로 지정하여 이 작업을 수행할 수 있습니다.

var customers = context.Customers
    .Where(c => EF.Functions.Collate(c.Name, "SQL_Latin1_General_CP1_CS_AS") == "John")
    .ToList();

이렇게 하면 열 또는 데이터베이스 수준에서 정의된 데이터 정렬에 관계없이 대/소문자 구분 데이터 정렬을 적용하는 COLLATE 절이 SQL 쿼리에 생성됩니다.

SELECT [c].[Id], [c].[Name]
FROM [Customers] AS [c]
WHERE [c].[Name] COLLATE SQL_Latin1_General_CP1_CS_AS = N'John'

명시적 데이터 정렬 및 인덱스

인덱스는 데이터베이스 성능에서 가장 중요한 요소 중 하나입니다. 인덱스를 사용하여 효율적으로 실행되는 쿼리는 해당 인덱스 없이 중단됩니다. 인덱스는 열의 데이터 정렬을 암시적으로 상속합니다. 즉, 쿼리가 다른 데이터 정렬을 지정하지 않는 경우 열의 모든 쿼리가 해당 열에 정의된 인덱스를 자동으로 사용할 수 있습니다. 쿼리에서 명시적 데이터 정렬을 지정하면 일반적으로 데이터 정렬이 더 이상 일치하지 않으므로 해당 쿼리가 해당 열에 정의된 인덱스를 사용하지 못하게 됩니다. 따라서 이 기능을 사용할 때는 주의해야 합니다. 모든 쿼리가 해당 데이터 정렬을 암시적으로 사용하고 인덱스를 활용할 수 있도록 열(또는 데이터베이스) 수준에서 데이터 정렬을 정의하는 것이 항상 좋습니다.

일부 데이터베이스에서는 인덱스를 만들 때 데이터 정렬을 정의할 수 있습니다(예: PostgreSQL, Sqlite). 이렇게 하면 동일한 열에 여러 인덱스를 정의하여 서로 다른 데이터 정렬을 사용하여 작업 속도를 높일 수 있습니다(예: 대/소문자를 구분하고 대/소문자를 구분하지 않는 비교 모두). 자세한 내용은 데이터베이스 공급자의 설명서를 참조하세요.

Warning

항상 쿼리의 쿼리 계획을 검사하고 많은 양의 데이터를 실행하는 성능에 중요한 쿼리에 적절한 인덱스가 사용되고 있는지 확인합니다. EF.Functions.Collate를 통해(또는 string.ToLower를 호출하여) 쿼리에서 대/소문자 구분을 재정의하면 애플리케이션 성능에 매우 큰 영향을 미칠 수 있습니다.

기본 제공 .NET 문자열 작업 변환

.NET에서 문자열 같음은 기본적으로 s1 == s2는 대/소문자를 구분합니다. 문자열이 동일해야 하는 서수 비교를 수행합니다. 데이터베이스의 기본 데이터 정렬은 다르며 단순 같음이 인덱스를 사용하는 것이 바람직하기 때문에 EF Core는 단순 같음을 데이터베이스 대/소문자 구분 작업으로 변환하지 않습니다. C# 같음은 사용 중인 특정 데이터베이스 및 데이터 정렬 구성에 따라 대/소문자를 구분하지 않을 수 있는 SQL 같음으로 직접 변환됩니다.

또한 .NET은 string.EqualsStringComparison 열거형을 수락하는 오버로드를 제공하므로 대/소문자 구분 및 비교를 위한 문화권을 지정할 수 있습니다. 기본적으로 EF Core는 이러한 오버로드를 SQL로 변환하지 않으며 이를 사용하려고 하면 예외가 발생합니다. 한 가지, EF Core는 어떤 대/소문자를 구분하거나 대/소문자를 구분하지 않는 데이터 정렬을 사용해야 하는지 알지 못합니다. 더 중요한 것은 데이터 정렬을 적용하면 대부분의 경우 인덱스 사용이 방지되어 매우 기본적이고 일반적으로 사용되는 .NET 구문의 성능에 크게 영향을 줍니다. 쿼리가 대/소문자를 구분하거나 대/소문자를 구분하지 않는 비교를 사용하도록 강제하려면 위에 설명된 대로EF.Functions.Collate를 통해 명시적으로 데이터 정렬을 지정합니다.

추가 리소스

데이터베이스 관련 정보

기타 리소스