Bagikan melalui


Kolatasi dan Sensitivitas Kasus

Pemrosesan teks dalam database bisa kompleks, dan membutuhkan lebih banyak perhatian pengguna daripada yang akan dicurigai. Untuk satu hal, database sangat bervariasi dalam cara mereka menangani teks; misalnya, sementara beberapa database peka huruf besar/kecil secara default (misalnya Sqlite, PostgreSQL), yang lain tidak peka huruf besar/kecil (SQL Server, MySQL). Selain itu, karena penggunaan indeks, sensitivitas huruf besar/kecil, dan aspek serupa dapat berdampak jauh pada performa kueri: meskipun mungkin menggoda untuk digunakan string.ToLower untuk memaksa perbandingan yang tidak peka huruf besar/kecil dalam database peka huruf besar/kecil, melakukannya dapat mencegah aplikasi Anda menggunakan indeks. Halaman ini merinci cara mengonfigurasi sensitivitas kasus, atau lebih umum, kolase, dan cara melakukannya dengan cara yang efisien tanpa mengorbankan performa kueri.

Pengantar kolate

Konsep dasar dalam pemrosesan teks adalah kolase, yang merupakan sekumpulan aturan yang menentukan bagaimana nilai teks diurutkan dan dibandingkan untuk kesetaraan. Misalnya, sementara kolase yang tidak sensitif huruf besar/kecil mengacuhkan perbedaan antara huruf besar dan kecil untuk tujuan perbandingan kesetaraan, kolase peka huruf besar/kecil tidak. Namun, karena sensitivitas huruf besar/kecil peka terhadap budaya (misalnya i dan I mewakili huruf yang berbeda dalam bahasa Turki), ada beberapa kolase yang tidak peka huruf besar/kecil, masing-masing dengan seperangkat aturannya sendiri. Cakupan kolatasi juga meluas di luar sensitivitas huruf besar/kecil, hingga aspek data karakter lainnya; dalam bahasa Jerman, misalnya, kadang-kadang (tetapi tidak selalu) diinginkan untuk memperlakukan ä dan ae identik. Akhirnya, kolase juga menentukan bagaimana nilai teks diurutkan: sementara Jerman menempatkan ä setelah a, Swedia menempatkannya di akhir alfabet.

Semua operasi teks dalam database menggunakan kolatasi - baik secara eksplisit maupun implisit - untuk menentukan bagaimana operasi membandingkan dan mengurutkan string. Daftar aktual kolatasi yang tersedia dan skema penamaannya khusus untuk database; lihat bagian di bawah ini untuk tautan ke halaman dokumentasi yang relevan dari berbagai database. Untungnya, database umumnya memungkinkan kolase default ditentukan di tingkat database atau kolom, dan untuk secara eksplisit menentukan kolase mana yang harus digunakan untuk operasi tertentu dalam kueri.

Kolase database

Di sebagian besar sistem database, kolatasi default didefinisikan pada tingkat database; kecuali ditimpa, kolas itu secara implisit berlaku untuk semua operasi teks yang terjadi dalam database tersebut. Kolase database biasanya diatur pada waktu pembuatan database (melalui CREATE DATABASE pernyataan DDL), dan jika tidak ditentukan, default ke beberapa nilai tingkat server yang ditentukan pada waktu penyiapan. Misalnya, kolase tingkat server default di SQL Server untuk lokal komputer "Inggris (Amerika Serikat)" adalah SQL_Latin1_General_CP1_CI_AS, yang merupakan kolase peka huruf besar/kecil dan peka aksen. Meskipun sistem database biasanya mengizinkan mengubah kolase database yang ada, melakukannya dapat menyebabkan komplikasi; disarankan untuk memilih kolase sebelum pembuatan database.

Saat menggunakan migrasi EF Core untuk mengelola skema database Anda, berikut ini dalam metode model OnModelCreating Anda mengonfigurasi database SQL Server untuk menggunakan kolase peka huruf besar/kecil:

modelBuilder.UseCollation("SQL_Latin1_General_CP1_CS_AS");

Kolatasi kolom

Kolase juga dapat ditentukan pada kolom teks, mengesampingkan default database. Ini dapat berguna jika kolom tertentu harus tidak peka huruf besar/kecil, sementara database lainnya harus peka huruf besar/kecil.

Saat menggunakan migrasi EF Core untuk mengelola skema database Anda, berikut ini mengonfigurasi kolom agar Name properti tidak peka huruf besar/kecil dalam database yang dikonfigurasi agar peka huruf besar/kecil:

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

Kolatasi eksplisit dalam kueri

Dalam beberapa kasus, kolom yang sama perlu dikueri menggunakan kolase yang berbeda oleh kueri yang berbeda. Misalnya, satu kueri mungkin perlu melakukan perbandingan peka huruf besar/kecil pada kolom, sementara kueri lain mungkin perlu melakukan perbandingan yang tidak peka huruf besar/kecil pada kolom yang sama. Ini dapat dicapai dengan secara eksplisit menentukan kolase dalam kueri itu sendiri:

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

Ini menghasilkan klausa COLLATE dalam kueri SQL, yang menerapkan kolase peka huruf besar/kecil terlepas dari kolase yang ditentukan di tingkat kolom atau database:

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

Kolatasi dan indeks eksplisit

Indeks adalah salah satu faktor terpenting dalam performa database - kueri yang berjalan secara efisien dengan indeks dapat menggiling hingga berhenti tanpa indeks tersebut. Indeks secara implisit mewarisi kolase kolomnya; ini berarti bahwa semua kueri pada kolom secara otomatis memenuhi syarat untuk menggunakan indeks yang ditentukan pada kolom tersebut - asalkan kueri tidak menentukan kolase yang berbeda. Menentukan kolatasi eksplisit dalam kueri umumnya akan mencegah kueri tersebut menggunakan indeks yang ditentukan pada kolom tersebut, karena kolacek tidak akan lagi cocok; Oleh karena itu disarankan untuk berhati-hati saat menggunakan fitur ini. Selalu lebih disukai untuk menentukan kolase pada tingkat kolom (atau database), memungkinkan semua kueri untuk secara implisit menggunakan kolase tersebut dan mendapat manfaat dari indeks apa pun.

Perhatikan bahwa beberapa database memungkinkan kolase ditentukan saat membuat indeks (misalnya PostgreSQL, Sqlite). Ini memungkinkan beberapa indeks didefinisikan pada kolom yang sama, mempercepat operasi dengan kolase yang berbeda (misalnya perbandingan peka huruf besar/kecil dan tidak peka huruf besar/kecil). Lihat dokumentasi penyedia database Anda untuk detail selengkapnya.

Peringatan

Selalu periksa rencana kueri kueri Anda, dan pastikan indeks yang tepat digunakan dalam kueri kritis performa yang dijalankan melalui sejumlah besar data. Mengesampingkan sensitivitas huruf besar/kecil dalam kueri melalui EF.Functions.Collate (atau dengan memanggil string.ToLower) dapat berdampak sangat signifikan pada performa aplikasi Anda.

Terjemahan operasi string .NET bawaan

Di .NET, kesetaraan string peka huruf besar/kecil secara default: s1 == s2 melakukan perbandingan ordinal yang mengharuskan string identik. Karena kolase default database bervariasi, dan karena diinginkan agar kesetaraan sederhana menggunakan indeks, EF Core tidak mencoba menerjemahkan kesetaraan sederhana ke operasi peka huruf besar/kecil database: Kesetaraan C# diterjemahkan langsung ke kesetaraan SQL, yang mungkin atau mungkin tidak peka huruf besar/kecil, tergantung pada database tertentu yang digunakan dan konfigurasi kolasenya.

Selain itu, .NET menyediakan kelebihan beban string.Equals menerima enum, yang memungkinkan menentukan sensitivitas huruf besar/kecil dan budaya untuk perbandingan StringComparison . Secara desain, EF Core menahan diri untuk menerjemahkan kelebihan beban ini ke SQL, dan mencoba menggunakannya akan menghasilkan pengecualian. Untuk satu hal, EF Core tidak tahu kolase peka huruf besar/kecil atau tidak peka huruf besar/kecil mana yang harus digunakan. Lebih penting lagi, menerapkan kolaterasi dalam banyak kasus akan mencegah penggunaan indeks, secara signifikan berdampak pada performa untuk konstruksi .NET yang sangat mendasar dan umum digunakan. Untuk memaksa kueri menggunakan perbandingan peka huruf besar/kecil atau tidak peka huruf besar/kecil, tentukan kolase secara eksplisit melalui EF.Functions.Collate seperti yang dijelaskan di atas.

Sumber Daya Tambahan:

Informasi khusus database

Sumber daya lainnya

  • Sesi Standup Komunitas Data .NET, memperkenalkan kolase dan menjelajahi aspek perf dan pengindeksan.