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
- Dokumentace k SQL Serveru pro kolace
- Dokumentace k Microsoft.Data.Sqlite týkající se kolací
- Dokumentace k PostgreSQL týkající se kolací
- Dokumentace k MySQL ke kolaci
Další prostředky
- Relace .NET Data Community Standup, představuje kolace a prozkoumání aspektů výkonu a indexování.