Mengapa Anda mengindeks text_pattern_ops pada kolom teks?

18

Hari ini Seven Databases dalam Seven Weeks memperkenalkan saya ke indeks per operator.

Anda bisa mengindeks string untuk pola yang cocok dengan kueri sebelumnya dengan membuat text_pattern_opsindeks kelas operator, asalkan nilainya diindeks dalam huruf kecil.

CREATE INDEX moves_title_pattern ON movies (
    (lower(title) text_pattern_ops);

Kami menggunakan text_pattern_opskarena judulnya adalah tipe teks. Jika Anda perlu indeks varchars, karakter, atau nama, gunakan ops terkait: varchar_pattern_ops, bpchar_pattern_ops, dan name_pattern_ops.

Saya menemukan contohnya sangat membingungkan. Mengapa bermanfaat untuk melakukan ini?

Jika kolom adalah tipe teks, bukankah tipe lainnya (varchar, char, name) dapat digunakan untuk teks sebelum digunakan sebagai nilai pencarian?

Bagaimana indeks itu berperilaku berbeda dari yang menggunakan operator default?

CREATE INDEX moves_title_pattern ON movies (lower(title));
Iain Samuel McLean Elder
sumber
1
Pertanyaan terkait ini mungkin dapat membantu: dba.stackexchange.com/questions/10694/…
Erwin Brandstetter
Terima kasih, Erwin. Jawaban Anda untuk pertanyaan itu sangat membantu ketika meneliti ide-ide dalam buku ini.
Iain Samuel McLean Penatua

Jawaban:

20

Dokumentasi sering memberi Anda jawaban untuk pertanyaan seperti itu. Seperti dalam kasus ini juga:

Kelas operator text_pattern_ops, varchar_pattern_ops, dan bpchar_pattern_ops mendukung indeks B-tree pada masing-masing jenis teks, varchar, dan char. Perbedaan dari kelas operator default adalah bahwa nilai-nilai dibandingkan secara ketat karakter dengan karakter daripada sesuai dengan aturan pengumpulan lokal-spesifik. Ini membuat kelas operator ini cocok untuk digunakan oleh kueri yang melibatkan ekspresi pencocokan pola (LIKE atau POSIX regular expressions) ketika database tidak menggunakan lokal "C" standar. Sebagai contoh, Anda dapat mengindeks kolom varchar seperti ini:

CREATE INDEX test_index ON test_table (col varchar_pattern_ops);

Perhatikan bahwa Anda juga harus membuat indeks dengan kelas operator default jika Anda ingin kueri yang melibatkan perbandingan <, <=,>, atau> biasa untuk menggunakan indeks. Kueri semacam itu tidak dapat menggunakan kelas operator xxx_pattern_ops . (Namun, perbandingan kesetaraan biasa dapat menggunakan kelas operator ini.) Dimungkinkan untuk membuat beberapa indeks pada kolom yang sama dengan kelas operator yang berbeda.

Dokumentasi selanjutnya mengatakan:

Jika Anda menggunakan C locale, Anda tidak memerlukan kelas operator xxx_pattern_ops, karena indeks dengan kelas operator default dapat digunakan untuk kueri pencocokan pola di C locale.

Anda dapat memeriksa lokal Anda sebagai berikut (cenderung UTF8 daripada "C"):

postgres=> show lc_collate;
 lc_collate
-------------
 en_GB.UTF-8
dezso
sumber
Aha! Saya memang membaca itu, tetapi merasa sulit untuk diikuti sehingga tidak menerimanya. Apakah Anda mengatakan manfaatnya text_pattern_opstergantung pada lokasi? Sepertinya itu akan menguntungkan saya karena lokal saya adalah 'en_US.UTF-8' (bukan 'C'), jadi kueri pola tidak dapat menggunakan indeks default.
Iain Samuel McLean Penatua
Persis. Saya akan menambahkan (tapi ini hanya spekulasi) bahwa dengan data tetap berada di dalam karakter ASCII dasar, kelas operator default sama baiknya - setidaknya saya melihat pertanyaan dengan LIKE 'sesuatu%' menggunakan indeks tersebut.
dezso
5
@dezso: Jika Anda telah melihat LIKEkueri menggunakan indeks b-tree polos, maka db harus menggunakan Clokal. Atau indeks ditentukan dengan COLLATE "POSIX"(atau COLLATE "C") dan kueri menentukan pencocokan COLLATION. Dengan susunan lainnya, urutan indeks tidak cocok dengan aturan lokal dan oleh karena itu tidak dapat digunakan untuk pencocokan pola.
Erwin Brandstetter
1
@ ErwinBrandstetter Saya harus mengkonfirmasi, Anda benar.
dezso
1
@ StopHarmingMonica Anda mendapatkan respons yang benar (dan tidak ada kesalahan), hanya saja permintaan akan lebih lambat, tidak bisa menggunakan indeks.
dezso