Kolace a citlivost malých a malých písmen

Zpracování textu v databázích může být složité a vyžaduje více pozornosti uživatelů, než by bylo podezřelé. U jedné věci se databáze výrazně liší v tom, jak zpracovávají text; Zatímco některé databáze ve výchozím nastavení rozlišují malá a velká písmena (např. Sqlite, PostgreSQL), jiné nerozlišují malá a velká písmena (SQL Server, MySQL). Vzhledem k použití indexů může mít navíc dalekosáhlý dopad na výkon dotazů citlivost a podobné aspekty: i když může být lákavé vynutit string.ToLower porovnávání malých a malých písmen v databázi, může to zabránit tomu, aby vaše aplikace používala indexy. Tato stránka podrobně popisuje, jak nakonfigurovat citlivost na malá a malá písmena nebo obecněji kolace a jak to provést efektivním způsobem, aniž by došlo k ohrožení výkonu dotazů.

Úvod do kolací

Základním konceptem zpracování textu je kolace, což je sada pravidel určující, jak se textové hodnoty řadí a porovnávají s rovností. Zatímco kolace nerozlišující malá a velká písmena například ignoruje rozdíly mezi velkými a malých písmeny pro účely porovnání rovnosti, kolace citlivá na malá a velká písmena ne. Vzhledem k tomu, že citlivost na malá a velká písmena je citlivá na jazykovou verzi (např. i I a představují různá písmena v turečtině), existuje několik kolací nerozlišující malá a velká písmena, přičemž každá z nich má vlastní sadu pravidel. Rozsah kolací se také rozšiřuje nad rámec citlivosti malých a malých písmen na další aspekty dat znaků; například v němčině je někdy (ale ne vždy) žádoucí považovat a ä ae považovat za identické. Kolace také definují, jak jsou textové hodnoty seřazeny: zatímco německé místa ä po a, švédština je umístí na konec abecedy.

Všechny textové operace v databázi používají kolaci (ať už explicitně nebo implicitně) k určení, jak operace porovnává a objednává řetězce. Skutečný seznam dostupných kolací a jejich schémat pojmenování je specifický pro databázi; Odkazy na příslušné stránky dokumentace různých databází najdete v následující části. Databáze naštěstí obecně umožňují definovat výchozí kolaci na úrovni databáze nebo sloupce a explicitně určit, která kolace se má použít pro konkrétní operace v dotazu.

Kolace databáze

Ve většině databázových systémů je výchozí kolace definována na úrovni databáze; pokud není přepsáno, tato kolace implicitně platí pro všechny textové operace, ke kterým dochází v této databázi. Kolace databáze se obvykle nastavuje při vytváření databáze (prostřednictvím CREATE DATABASE příkazu DDL) a pokud není zadána, výchozí hodnota je nastavená na hodnotu na úrovni serveru určenou v době instalace. Například výchozí kolace na úrovni serveru v SQL Serveru pro národní prostředí počítače "Angličtina (USA)" je SQL_Latin1_General_CP1_CI_AS, což je malá a malá písmena nerozlišující kolace s diakritikou. I když databázové systémy obvykle umožňují měnit kolaci existující databáze, může to vést ke komplikacím; Před vytvořením databáze doporučujeme vybrat kolaci.

Při použití migrací EF Core ke správě schématu databáze se v metodě modelu OnModelCreating nakonfiguruje databáze SQL Serveru tak, aby používala kolaci s rozlišováním velkých a malých písmen:

modelBuilder.UseCollation("SQL_Latin1_General_CP1_CS_AS");

Kolace sloupců

Kolace lze také definovat u textových sloupců a přepisovat výchozí nastavení databáze. To může být užitečné, pokud některé sloupce potřebují nerozlišovat malá a velká písmena, zatímco zbytek databáze musí rozlišovat malá a velká písmena.

Při použití migrací EF Core ke správě schématu databáze nakonfiguruje následující sloupec pro Name vlastnost tak, aby nerozlišovala malá a velká písmena v databázi, která je jinak nakonfigurovaná tak, aby rozlišovala malá a velká písmena:

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

Explicitní kolace v dotazu

V některých případech musí být stejný sloupec dotazován pomocí různých kolací podle různých dotazů. Jeden dotaz může například potřebovat provést porovnání s rozlišováním velkých a malých písmen ve sloupci, zatímco druhý může potřebovat provést porovnání nerozlišující malá a velká písmena ve stejném sloupci. Toho lze dosáhnout explicitním zadáním kolace v samotném dotazu:

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

Tím se COLLATE vygeneruje klauzule v dotazu SQL, která použije kolaci s rozlišováním velkých a malých písmen bez ohledu na kolaci definovanou na úrovni sloupce nebo databáze:

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

Explicitní kolace a indexy

Indexy jsou jedním z nejdůležitějších faktorů výkonu databáze – dotaz, který funguje efektivně s indexem, se může zastavit bez tohoto indexu. Indexy implicitně dědí kolaci jejich sloupce; to znamená, že všechny dotazy ve sloupci mají automaticky nárok na použití indexů definovaných v tomto sloupci za předpokladu, že dotaz neurčí jinou kolaci. Určení explicitní kolace v dotazu obecně zabrání použití indexu definovaného v daném sloupci, protože kolace se už neshodují; Proto se doporučuje při použití této funkce postupovat opatrně. Vždy je vhodnější definovat kolaci na úrovni sloupce (nebo databáze), což umožňuje všem dotazům implicitně používat tuto kolaci a těžit z jakéhokoli indexu.

Všimněte si, že některé databáze umožňují definovat kolaci při vytváření indexu (např. PostgreSQL, Sqlite). To umožňuje definovat více indexů ve stejném sloupci a zrychlit operace s různými kolacemi (například rozlišovat malá a velká a malá písmena). Další podrobnosti najdete v dokumentaci poskytovatele databáze.

Upozorňující

Vždy zkontrolujte plány dotazů vašich dotazů a ujistěte se, že se v důležitých dotazech s výkonem, které provádějí velké objemy dat, používají správné indexy. Přepsání citlivosti na malá a velká písmena v dotazu prostřednictvím EF.Functions.Collate (nebo voláním string.ToLower) může mít velmi významný dopad na výkon vaší aplikace.

Překlad předdefinovaných operací řetězců .NET

V rozhraní .NET se ve výchozím nastavení rozlišují malá a velká písmena: s1 == s2 provádí řadové porovnání, které vyžaduje, aby byly řetězce identické. Vzhledem k tomu, že se výchozí kolace databází liší a protože je žádoucí, aby bylo možné používat indexy jednoduché rovnosti, EF Core se nepokouší přeložit jednoduchou rovnost na operaci citlivou na malá a velká písmena: Rovnost jazyka C#se přeloží přímo na rovnost SQL, která může nebo nemusí být citlivá na malá a velká písmena v závislosti na používané databázi a konfiguraci kolace.

Rozhraní .NET navíc poskytuje přetížení string.Equals přijetí StringComparison výčtu, které umožňuje určit citlivost na malá a velká písmena a jazykovou verzi pro porovnání. EF Core záměrně zdrží překlad těchto přetížení do SQL a pokus o jejich použití způsobí výjimku. Ef Core neví, která kolace nerozlišují malá a velká a malá a velká písmena. Důležitější je, že použití kolace ve většině případů zabrání použití indexu, výrazně ovlivňuje výkon velmi základní a běžně používané konstrukce .NET. Pokud chcete vynutit, aby dotaz používal porovnání nerozlišující malá a velká a malá a velká písmena, zadejte kolaci explicitně, EF.Functions.Collate jak je podrobně popsáno výše.

Další prostředky

Informace specifické pro databázi

Další prostředky

  • Relace .NET Data Community Standup, představuje kolace a prozkoumání aspektů výkonu a indexování.