데이터 정렬 및 대/소문자 구분Collations and Case Sensitivity

참고

이 기능은 EF Core 5.0에서 도입되었습니다.This feature is introduced in EF Core 5.0.

데이터베이스에서 텍스트를 처리 하는 작업은 복잡할 수 있으며, 그 중 하나에 주의를 기울여야 하는 사용자 주의가 필요 합니다.Text processing in databases can be a complex, and requires more user attention that one would suspect. 데이터베이스는 텍스트를 처리 하는 방법에 따라 크게 달라 집니다. 예를 들어 일부 데이터베이스는 기본적으로 대/소문자를 구분 하지만 (예: Sqlite, PostgreSQL) 다른 데이터베이스는 대/소문자를 구분 하지 않습니다 (SQL Server, MySQL).For one thing, databases vary considerably in how they handle text; for example, while some databases are case-sensitive by default (e.g. Sqlite, PostgreSQL), others are case-insensitive (SQL Server, MySQL). 또한 인덱스를 사용 하는 경우 대/소문자 구분 및 유사한 측면에서 쿼리 성능에 거의 영향을 줄 수 있습니다. 대/소문자를 구분 하는 데이터베이스에서 대/소문자를 구분 하지 않는 비교를 수행 하는 데를 사용 하는 것은 쉽지만 string.Lower 응용 프로그램에서 인덱스를 사용 하지 못할 수 있습니다.In addition, because of index usage, case-sensitivity and similar aspects can have a far-reaching impact on query performance: while it may be tempting to use string.Lower to force a case-insensitive comparison in a case-sensitive database, doing so may prevent your application from using indexes. 이 페이지에서는 쿼리 성능을 손상 시 키 지 않고 대/소문자 구분을 구성 하는 방법, 더 일반적으로 데이터 정렬을 수행 하는 방법 및 효율적으로 작업을 수행 하는 방법을 자세히 설명 합니다This page details how to configure case sensitivity, or more generally, collations, and how to do so in an efficient way without compromising query performance.

데이터 정렬 소개Introduction to collations

텍스트 처리의 기본 개념은 데이터 정렬이며, 텍스트 값이 같은지 여부를 결정 하는 규칙 집합입니다.A fundamental concept in text processing is the collation, which is a set of rules determining how text values are ordered and compared for equality. 예를 들어 대/소문자를 구분 하지 않는 데이터 정렬은 같음 비교의 목적에 대해 대문자 및 소문자 간의 차이를 무시 하지만 대/소문자를 구분 하는 데이터 정렬은 그렇지 않습니다.For example, while a case-insensitive collation disregards differences between upper- and lower-case letters for the purposes of equality comparison, a case-sensitive collation does not. 하지만 대/소문자 구분은 문화권을 구분 하기 때문에 (예: i I 터키어에서 다른 문자를 나타냄) 각각 고유한 규칙 집합을 포함 하는 대/소문자를 구분 하지 않는 여러 개의 데이터 정렬이 있습니다.However, since case-sensitivity is culture-sensitive (e.g. i and I represent different letter in Turkish), there exist multiple case-insensitive collations, each with its own set of rules. 데이터 정렬의 범위는 대/소문자를 구분 하는 것 외에도 문자 데이터의 다른 측면으로 확장 됩니다. 예를 들어 독일어에서는와를 동일 하 게 처리 하는 것이 좋습니다 ä ae .The scope of collations also extends beyond case-sensitivity, to other aspects of character data; in German, for example, it is sometimes (but not always) desirable to treat ä and ae as identical. 마지막으로, 데이터 정렬은 텍스트 값의 정렬방법을 정의 합니다. 반면에 독일어 위치는 ä a 문자 끝에 배치 합니다.Finally, collations also define how text values are ordered: while German places ä after a, Swedish places it at the end of the alphabet.

데이터베이스의 모든 텍스트 작업은 데이터 정렬을 사용 하 여 명시적 또는 암시적으로 작업에서 문자열을 비교 하 고 정렬 하는 방법을 결정 합니다.All text operations in a database use a collation - whether explicitly or implicitly - to determine how the operation compares and orders strings. 사용 가능한 데이터 정렬 및 해당 명명 스키마의 실제 목록은 데이터베이스 전용입니다. 다양 한 데이터베이스의 관련 설명서 페이지에 대 한 링크는 아래 섹션 을 참조 하세요.The actual list of available collations and their naming schemes is database-specific; consult the section below for links to relevant documentation pages of various databases. 다행히 데이터베이스는 일반적으로 데이터베이스 또는 열 수준에서 기본 데이터 정렬을 정의 하 고 쿼리에서 특정 작업에 사용할 데이터 정렬을 명시적으로 지정 하는 것을 허용 합니다.Fortunately, database do generally allow a default collation to be defined at the database or column level, and to explicitly specify which collation should be use for specific operations in a query.

데이터베이스 데이터 정렬Database collation

대부분의 데이터베이스 시스템에서 기본 데이터 정렬은 데이터베이스 수준에서 정의 됩니다. 재정의 되지 않는 한 해당 데이터 정렬은 해당 데이터베이스 내에서 발생 하는 모든 텍스트 작업에 암시적으로 적용 됩니다.In most database systems, a default collation is defined at the database level; unless overridden, that collation implicitly applies to all text operations occurring within that database. 데이터베이스 데이터 정렬은 일반적으로 DDL 문을 통해 데이터베이스를 만들 때 설정 되며 CREATE DATABASE , 지정 되지 않은 경우 기본적으로 설치 시 결정 되는 서버 수준 값으로 설정 됩니다.The database collation is typically set at database creation time (via the CREATE DATABASE DDL statement), and if not specified, defaults to a some server-level value determined at setup time. 예를 들어 SQL Server의 기본 서버 수준 데이터 정렬은 SQL_Latin1_General_CP1_CI_AS 대/소문자를 구분 하지 않고 악센트를 구분 하는 데이터 정렬입니다.For example, the default server-level collation in SQL Server is SQL_Latin1_General_CP1_CI_AS, which is a case-insensitive, accent-sensitive collation. 일반적으로 데이터베이스 시스템은 기존 데이터베이스의 데이터 정렬을 변경 하는 것을 허용 하지만 이렇게 하면 복잡 해질 수 있습니다. 데이터베이스를 만들기 전에 데이터 정렬을 선택 하는 것이 좋습니다.Although database systems usually do permit altering the collation of an existing database, doing so can lead to complications; it is recommended to pick a collation before database creation.

EF Core 마이그레이션을 사용 하 여 데이터베이스 스키마를 관리 하는 경우 모델의 메서드에서 다음과 OnModelCreating 같이 대/소문자 구분 데이터 정렬을 사용 하도록 SQL Server 데이터베이스를 구성 합니다.When using EF Core migrations to manage your database schema, the following in your model's OnModelCreating method configures a SQL Server database to use a case-sensitive collation:

modelBuilder.UseCollation("SQL_Latin1_General_CP1_CS_AS");

열 데이터 정렬Column collation

데이터 정렬은 텍스트 열에 정의 되어 데이터베이스 기본값을 재정의할 수도 있습니다.Collations can also be defined on text columns, overriding the database default. 이는 특정 열에서 대/소문자를 구분 하지 않아야 하는 반면 나머지 데이터베이스는 대/소문자를 구분 해야 하는 경우에 유용할 수 있습니다.This can be useful if certain columns need to be case-insensitive, while the rest of the database needs to be case-sensitive.

EF Core 마이그레이션을 사용 하 여 데이터베이스 스키마를 관리 하는 경우 다음은 Name 대/소문자를 구분 하도록 구성 된 데이터베이스에서 속성의 열을 대/소문자를 구분 하지 않도록 구성 합니다.When using EF Core migrations to manage your database schema, the following configures the column for the Name property to be case-insensitive in a database that is otherwise configured to be case-sensitive:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.UseCollation("SQL_Latin1_General_CP1_CS_AS");

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

쿼리의 명시적 데이터 정렬Explicit collation in a query

경우에 따라 다른 쿼리를 통해 서로 다른 데이터 정렬을 사용 하 여 동일한 열을 쿼리해야 합니다.In some cases, the same column needs to be queried using different collations by different queries. 예를 들어 한 쿼리는 열에 대 한 대/소문자를 구분 하는 비교를 수행 해야 하는 반면 다른 쿼리는 동일한 열에 대 한 대/소문자를 구분 하지 않는 비교를 수행 해야 할 수 있습니다For example, one query may need to perform a case-sensitive comparison on a column, while another may need to perform a case-insensitive comparison on the same column. 쿼리 자체 내에서 데이터 정렬을 명시적으로 지정 하 여이 작업을 수행할 수 있습니다.This can be accomplished by explicitly specifying a collation within the query itself:

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

이렇게 하면 COLLATE SQL 쿼리에서 절이 생성 되며,이는 열 또는 데이터베이스 수준에서 정의 된 데이터 정렬에 관계 없이 대/소문자를 구분 하는 데이터 정렬을 적용 합니다.This generates a COLLATE clause in the SQL query, which applies a case-sensitive collation regardless of the collation defined at the column or database level:

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

명시적 데이터 정렬 및 인덱스Explicit collations and indexes

인덱스는 데이터베이스 성능에서 가장 중요 한 요소 중 하나입니다. 인덱스를 사용 하 여 효율적으로 실행 되는 쿼리는 해당 인덱스 없이 중지 표 수 있습니다.Indexes are one of the most important factors in database performance - a query that runs efficiently with an index can grind to a halt without that index. 인덱스는 열의 데이터 정렬을 암시적으로 상속 합니다. 즉, 쿼리에서 다른 데이터 정렬을 지정 하지 않은 경우 해당 열에 정의 된 인덱스를 열에 대해 자동으로 사용할 수 있습니다.Indexes implicitly inherit the collation of their column; this means that all queries on the column are automatically eligible to use indexes defined on that column - provided that the query doesn't specify a different collation. 쿼리에서 명시적 데이터 정렬을 지정 하면 데이터 정렬이 더 이상 일치 하지 않기 때문에 일반적으로 해당 열에 정의 된 인덱스를 쿼리에서 사용할 수 없습니다. 따라서이 기능을 사용 하는 경우에는 주의를 기울여야 합니다.Specifying an explicit collation in a query will generally prevent that query from using an index defined on that column, since the collations would no longer match; it is therefore recommended to exercise caution when using this feature. 열 (또는 데이터베이스) 수준에서 데이터 정렬을 정의 하 여 모든 쿼리에서 암시적으로 해당 데이터 정렬을 사용 하 고 인덱스의 이점을 활용할 수 있도록 하는 것이 항상 좋습니다.It is always preferable to define the collation at the column (or database) level, allowing all queries to implicitly use that collation and benefit from any index.

일부 데이터베이스에서는 인덱스를 만들 때 데이터 정렬을 정의할 수 있습니다 (예: PostgreSQL, Sqlite).Note that some databases allow the collation to be defined when creating an index (e.g. PostgreSQL, Sqlite). 이를 통해 동일한 열에 여러 인덱스를 정의 하 여 다른 데이터 정렬로 작업 속도를 향상 시킬 수 있습니다 (예: 대/소문자 구분 및 대/소문자 구분 비교).This allows multiple indexes to be defined on the same column, speeding up operations with different collations (e.g. both case-sensitive and case-insensitive comparisons). 자세한 내용은 데이터베이스 공급자 설명서를 참조 하세요.Consult your database provider's documentation for more details.

경고

항상 쿼리의 쿼리 계획을 검사 하 고, 대량의 데이터를 실행 하는 성능이 중요 한 쿼리에서 적절 한 인덱스를 사용 하 고 있는지 확인 합니다.Always inspect the query plans of your queries, and make sure the proper indexes are being used in performance-critical queries executing over large amounts of data. 을 (를) 통해 또는를 호출 하 여 쿼리에서 대/소문자 구분 EF.Functions.Collate string.ToLower 을 재정의 하면 응용 프로그램의 성능에 매우 심각한 영향을 줄 수 있습니다.Overriding case-sensitivity in a query via EF.Functions.Collate (or by calling string.ToLower) can have a very significant impact on your application's performance.

기본 제공 .NET 문자열 작업의 변환Translation of built-in .NET string operations

.NET에서 문자열 같음은 기본적으로 대/소문자를 구분 s1 == s2 합니다 .는 문자열이 동일 해야 하는 서 수 비교를 수행 합니다.In .NET, string equality is case-sensitive by default: s1 == s2 performs an ordinal comparison that requires the strings to be identical. 데이터베이스의 기본 데이터 정렬은 다양 하며 단순 일치에서 인덱스를 사용 하는 것이 바람직합니다. EF Core는 데이터베이스의 대/소문자를 구분 하는 작업으로의 단순 일치를 변환 하려고 시도 하지 않습니다. c # 일치는 사용 중인 특정 데이터베이스와 해당 데이터 정렬 구성에 따라 대/소문자를 구분 하는 SQL 동등으로 직접 변환 됩니다.Because the default collation of databases varies, and because it is desirable for simple equality to use indexes, EF Core makes no attempt to translate simple equality to a database case-sensitive operation: C# equality is translated directly to SQL equality, which may or may not be case-sensitive, depending on the specific database in use and its collation configuration.

또한 .NET에서는 string.Equals StringComparison 비교에 대 한 대/소문자 구분 및 문화권을 지정할 수 있는 열거형을 허용 하는 오버 로드를 제공 합니다.In addition, .NET provides overloads of string.Equals accepting a StringComparison enum, which allows specifying case-sensitivity and culture for the comparison. 기본적으로 refrains는 이러한 오버 로드를 SQL로 변환 하지 않으며 EF Core,이를 사용 하려고 시도 하면 예외가 발생 합니다.By design, EF Core refrains from translating these overloads to SQL, and attempting to use them will result in an exception. 한 가지 경우 EF Core는 대/소문자를 구분 하거나 구분 하지 않는 데이터 정렬을 사용 하지 않는 것을 알 수 있습니다.For one thing, EF Core does know not which case-sensitive or case-insensitive collation should be used. 무엇 보다도 데이터 정렬을 적용 하면 대부분의 경우 인덱스를 사용 하는 것이 매우 간단 하 고 일반적으로 사용 되는 .NET 구문의 성능에 크게 영향을 주지 않습니다.More importantly, applying a collation would in most cases prevent index usage, significantly impacting performance for a very basic and commonly-used .NET construct. 쿼리에서 대/소문자를 구분 하거나 대/소문자를 구분 하지 않는 비교를 사용 하도록 강제 하려면 위에서 설명한 대로를 통해 데이터 정렬을 명시적으로 지정 합니다 EF.Functions.Collate . detailed aboveTo force a query to use case-sensitive or case-insensitive comparison, specify a collation explicitly via EF.Functions.Collate as detailed above.

데이터베이스 관련 정보Database-specific information