1. Konsep dan Aplikasi Indeks

1.1 Apa itu Indeks

Sebuah indeks adalah struktur data yang digunakan dalam sistem manajemen basis data untuk mempercepat operasi pengambilan data. Indeks dapat dianggap sebagai "direktori" dalam basis data yang memungkinkan untuk dengan cepat menemukan data dalam tabel data, menghindari pemindaian tabel lengkap, dan secara signifikan meningkatkan efisiensi kueri. Dalam aplikasi praktis, penggunaan indeks yang tepat dapat sangat meningkatkan kinerja sebuah basis data.

1.2 Jenis-Jenis Indeks

Terdapat berbagai jenis indeks, masing-masing dengan desain dan optimasi sendiri untuk berbagai skenario aplikasi:

  • Indeks Satu Kolom: Indeks yang hanya mencakup satu kolom, cocok untuk skenario yang bergantung pada satu kondisi untuk kueri cepat.
  • Indeks Gabungan: Indeks yang mencakup beberapa kolom, memberikan optimasi untuk kueri yang mengandung kolom-kolom tersebut.
  • Indeks Unik: Memastikan keunikan dari kolom-kolom indeks, tidak memperbolehkan adanya nilai-nilai duplikat. Indeks unik dapat berupa satu kolom atau gabungan.

2. Definisi Indeks

2.1 Definisi Indeks Kolom

Membuat indeks satu kolom melibatkan pembentukan indeks pada kolom tertentu dari tabel data, yang dapat dicapai dengan menggunakan metode Fields. Contoh berikut menunjukkan bagaimana membuat indeks pada kolom phone dari entitas User.

func (User) Fields() []ent.Field {
    return []ent.Field{
        field.String("phone"),
    }
}
func (User) Indexes() []ent.Index {
    // Membuat indeks satu kolom.
    return []ent.Index{
        index.Fields("phone"),
    }
}

Dalam potongan kode ini, kolom phone diindeks. Hal ini memungkinkan sistem untuk menggunakan indeks untuk pencarian lebih cepat saat melakukan kueri pada kolom phone.

2.2 Definisi Indeks Unik

Indeks unik memastikan keunikan data pada kolom-kolom yang diindeks. Hal ini dapat dicapai dengan menambahkan metode Unique pada kolom. Contoh berikut menggambarkan pembuatan indeks unik untuk satu dan beberapa kolom.

Membuat indeks unik untuk satu kolom:

func (User) Fields() []ent.Field {
    return []ent.Field{
        field.String("email").Unique(),
    }
}

Pada contoh ini, kolom email ditentukan sebagai unik, memastikan bahwa setiap email pengguna unik dalam basis data.

Membuat indeks unik untuk kombinasi beberapa kolom:

func (User) Indexes() []ent.Index {
    return []ent.Index{
        // Membuat indeks unik untuk beberapa kolom.
        index.Fields("first_name", "last_name").Unique(),
    }
}

Potongan kode ini mendefinisikan indeks unik gabungan untuk kombinasi kolom first_name dan last_name, mencegah terjadinya catatan dengan nilai yang sama pada kedua kolom.

2.3 Definisi Indeks Gabungan

Ketika kondisi kueri melibatkan beberapa kolom, indeks gabungan dapat digunakan. Indeks gabungan menyimpan data sesuai dengan urutan yang ditentukan dalam indeks. Urutan indeks memiliki dampak signifikan pada kinerja kueri, sehingga saat mendefinisikan indeks gabungan, urutan kolom perlu ditentukan berdasarkan pola kueri.

Berikut adalah contoh pembuatan indeks gabungan:

func (User) Indexes() []ent.Index {
    return []ent.Index{
        // Membuat indeks gabungan dengan beberapa kolom.
        index.Fields("country", "city"),
    }
}

Pada contoh ini, indeks gabungan dibuat pada kolom country dan city. Ini berarti saat melakukan operasi kueri yang melibatkan kedua kolom ini, basis data dapat dengan cepat menemukan data yang memenuhi kondisi-kondisi.

Indeks gabungan tidak hanya mempercepat kinerja kueri tetapi juga mendukung operasi pengurutan berbasis indeks, memberikan kinerja pengambilan data yang lebih efisien. Saat merancang indeks gabungan, umumnya menempatkan kolom-kolom dengan selektivitas yang lebih tinggi di bagian depan indeks agar optimizer basis data dapat lebih baik memanfaatkan indeks.

3. Indeks Edge

Dalam framework ent, indeks edge adalah cara untuk mendefinisikan indeks melalui edge (hubungan). Mekanisme ini biasanya digunakan untuk memastikan keunikan bidang di bawah hubungan tertentu. Sebagai contoh, jika model basis data Anda mencakup kota dan jalan, dan setiap nama jalan di bawah kota perlu unik, indeks edge dapat digunakan untuk mencapai hal ini.

// File ent/schema/street.go mendefinisikan skema entitas Street.
type Street struct {
    ent.Schema
}

func (Street) Fields() []ent.Field {
    // Tentukan bidang
    return []ent.Field{
        field.String("name"),
    }
}

func (Street) Edges() []ent.Edge {
    // Tentukan hubungan edge dengan City, di mana Street milik ke sebuah City.
    return []ent.Edge{
        edge.From("city", City.Type).
            Ref("streets").
            Unique(),
    }
}

func (Street) Indexes() []ent.Index {
    // Buat indeks unik melalui edge untuk memastikan keunikan nama jalan dalam kota yang sama.
    return []ent.Index{
        index.Fields("name").
            Edges("city").
            Unique(),
    }
}

Dalam contoh ini, kita membuat entitas Street dan mengaitkannya dengan entitas City. Dengan mendefinisikan indeks edge di metode Indexes dari entitas Street, kita memastikan bahwa nama setiap jalan di bawah kota adalah unik.

Bab 5: Opsi Indeks Lanjutan

5.1 Indeks Teks Penuh dan Indeks Hash

Indeks teks penuh dan indeks hash adalah dua jenis indeks unik dalam MySQL dan PostgreSQL, dan digunakan untuk skenario optimisasi kueri yang berbeda.

Indeks teks penuh umumnya digunakan untuk mencari data teks, terutama ketika Anda perlu melakukan pencarian kompleks, seperti pencarian kecocokan kata. Baik basis data MySQL maupun PostgreSQL mendukung indeks teks penuh. Sebagai contoh, dalam MySQL, Anda dapat mendefinisikan indeks teks penuh seperti ini:

// File ent/schema/user.go mendefinisikan skema entitas User.
func (User) Indexes() []ent.Index {
    // Buat indeks teks penuh menggunakan kategori FULLTEXT di MySQL
    return []ent.Index{
        index.Fields("description").
            Annotations(entsql.IndexTypes(map[string]string{
                dialect.MySQL: "FULLTEXT",
            })),
    }
}

Indeks hash sangat cocok untuk kueri kesetaraan dan tidak mendukung pengurutan serta kueri rentang. Di PostgreSQL, Anda dapat menggunakan indeks hash seperti ini:

func (User) Indexes() []ent.Index {
    // Tentukan indeks tipe HASH
    return []ent.Index{
        index.Fields("c4").
            Annotations(entsql.IndexType("HASH")),
    }
}

5.2 Indeks Parsial dan Awalan Indeks

Indeks parsial adalah jenis indeks yang hanya mengindeks baris-baris dalam tabel yang memenuhi kondisi-kondisi khusus. Di SQLite dan PostgreSQL, Anda dapat menggunakan klausa WHERE untuk membuat indeks parsial.

Sebagai contoh, mendefinisikan indeks parsial di PostgreSQL:

func (User) Indexes() []ent.Index {
    // Buat indeks parsial pada bidang "nickname", hanya berisi baris-baris di mana "active" bernilai true.
    return []ent.Index{
        index.Fields("nickname").
            Annotations(
                entsql.IndexWhere("active"),
            ),
    }
}

Awalan indeks sangat berguna untuk bidang teks, terutama di MySQL. Ini dapat mempersingkat waktu pembuatan indeks, mengurangi ruang yang diisi oleh indeks, dan juga memberikan kinerja yang baik. Seperti yang ditunjukkan di bawah ini, untuk MySQL, Anda dapat mendefinisikan indeks dengan awalan:

func (User) Indexes() []ent.Index {
    // Buat indeks menggunakan awalan indeks
    return []ent.Index{
        index.Fields("description").
            Annotations(entsql.Prefix(128)),
    }
}

5.3 Anotasi Indeks dan Kustomisasi

Dalam ent, Anotasi adalah fitur yang memungkinkan pengembang untuk menyesuaikan indeks. Anda dapat mendefinisikan tipe indeks, mengatur aturan pengurutan, dan lain-lain.

Sebagai contoh, kode berikut menunjukkan bagaimana menentukan aturan pengurutan kolom dalam sebuah indeks:

func (User) Indexes() []ent.Index {
    return []ent.Index{
        // Gunakan anotasi untuk menentukan aturan pengurutan kolom dari indeks
        index.Fields("c1", "c2", "c3").
            Annotations(entsql.DescColumns("c1", "c2")),
    }
}

Dengan fitur anotasi, para pengembang dapat secara fleksibel menyesuaikan indeks untuk mengoptimalkan kinerja dan struktur basis data.