Memecahkan Kemacetan Dengan Indeks dan Partisi SQL
Diterbitkan: 2022-03-11Dalam pelajaran pertama Penjelasan Indeks SQL, kita mempelajari bahwa kueri SELECT lebih cepat ketika data sudah diurutkan berdasarkan nilai kolom tertentu.
Pada pelajaran kedua, kita mempelajari struktur dasar indeks B-tree dan cara menggunakannya untuk mengurangi volume data yang kita akses saat menjalankan kueri. Kami juga menemukan cara menerapkan kueri yang menggabungkan beberapa tabel dan bagaimana indeks dapat mempercepat kueri tersebut.
Kami juga menyoroti dua skenario di mana penggunaan indeks dalam SQL sangat membantu. Saat indeks mencakup indeks, yang berisi semua kolom dari kueri—dari kondisi WHERE , kondisi JOIN , dan daftar SELECT —kita menghindari membaca tabel yang sesuai sepenuhnya. Atau, indeks dapat membantu ketika mereka mengurangi jumlah blok data yang diakses ke sebagian kecil dari ukuran tabel.
Jika tidak, akan lebih efisien untuk memindai seluruh tabel daripada membaca dari indeks dan melompat bolak-balik secara acak ke baris tabel yang sesuai.
Kueri Rentang SQL
Kueri yang dapat memanfaatkan indeks biasanya menyertakan kondisi yang secara signifikan mengurangi rentang kemungkinan nilai yang dapat diambil oleh satu atau beberapa kolom. Kueri rentang membatasi data berdasarkan kondisi seperti "nilai Kolom A harus antara X dan Y."
Sebuah contoh yang baik dari ini adalah query dari Latihan 4 dari pelajaran kedua:
SELECT c.ClientName FROM Reservations r JOIN Clients c ON r.ClientID = c.ClientID WHERE r.DateFrom BETWEEN ( TO_DATE('2020-08-13', 'YYYY-MM-DD') AND TO_DATE('2020-08-14', 'YYYY-MM-DD') ) AND r.HotelID = 3; Di sini kita memiliki dua rentang. Yang pertama adalah rentang tanggal, periode antara 13 Agustus 2020, dan 14 Agustus 2020. Yang kedua adalah rentang numerik sekecil mungkin. Kondisi tersebut setara dengan r.HotelID BETWEEN 3 AND 3 .
Latihan 1: Periode (Kueri Rentang Tanggal dan Waktu)
Mari tambahkan kolom bernama CheckInTime ke tabel Reservations . Anda dapat melihat contoh data di spreadsheet ini. Perhatikan ada satu indeks yang mencakup CheckInTime dan ClientId .
Tulis kueri yang akan menampilkan nama klien yang check in pada 15 Agustus 2020.
Pengembang SQL yang tidak berpengalaman biasanya menulis kueri berikut:
SELECT c.ClientName FROM Reservations r JOIN Clients c ON r.ClientID = c.ClientID WHERE TO_DATE(r.CheckInTime, 'YYYY-MM-DD') = '2020-08-15';Mereka berasumsi bahwa eksekusi kueri akan terlihat seperti ini:
Get first row from IX_CheckInTime_ClientID where TO_DATE(CheckInTime, 'YYYY-MM-DD') = '2020-08-15' While found and TO_DATE(CheckInTime, 'YYYY-MM-DD') = '2020-08-15' Fetch Clients.* where ClientID = IX_CheckInTime_ClientID.ClientID Write down Clients.ClientName Get next row from IX_CheckInTime_ClientID Masalahnya adalah tidak satu pun RDBMS pada saat penulisan ini mampu menghasilkan rencana eksekusi seperti itu. Mereka melihat TO_DATE (Sintaksis Oracle) sebagai fungsi yang mengubah nilai kolom CheckInTime menjadi sesuatu yang tidak terindeks. Jadi, rencana eksekusi yang cenderung mereka hasilkan terlihat seperti ini:
For each row from IX_CheckInTime_ClientID If TO_DATE(CheckInTime, 'YYYY-MM-DD') = '2020-08-15' then Fetch Clients.* where ClientID = IX_CheckInTime_ClientID.ClientID Write down Clients.ClientName Menjalankan ini akan lebih cepat daripada membaca semua baris dari tabel Reservations karena baris indeks lebih sempit daripada baris tabel. Baris yang lebih kecil berarti lebih sedikit blok yang perlu diakses dari disk.
Namun, kita tahu bahwa rencana eksekusi pertama akan jauh lebih efisien. Untuk meyakinkan RDBMS kami untuk menggunakan pendekatan itu, kami perlu menulis ulang kueri:
SELECT c.ClientName FROM Reservations r JOIN Clients c ON r.ClientID = c.ClientID WHERE r.CheckInTime >= TO_DATE('2020-08-15 00:00:00', 'YYYY-MM-DD HH:MI:SS') AND r.CheckInTime < TO_DATE('2020-08-16 00:00:00', 'YYYY-MM-DD HH:MI:SS'); Ini adalah kueri rentang yang tepat, yang dipahami oleh setiap RDBMS yang baik. RDBMS kami mengetahui bahwa kami menginginkan data dari tabel Reservations di mana nilai CheckInTime — bukan sesuatu yang diturunkan darinya — termasuk dalam rentang yang ditentukan dengan baik. Rencana eksekusi yang dihasilkannya akan lebih seperti:
Get first row from IX_CheckInTime_ClientID where CheckInTime >= '2020-08-15 00:00:00' While found and CheckInTime < '2020-08-16 00:00:00' Fetch Clients.* where ClientID = IX_CheckInTime_ClientID.ClientID Write down Clients.ClientName Get next row from IX_CheckInTime_ClientIDItulah yang benar-benar kami inginkan: memanfaatkan tidak hanya indeks itu sendiri tetapi juga fakta bahwa indeks itu diurutkan.
Latihan 2: LIKE Dengan Wildcard di Awal
Kali ini detektif kami datang ke hotel dengan informasi yang tidak jelas tentang tersangka: hanya saja nama belakangnya diakhiri dengan "-son." Detektif menginginkan nama depan dan belakang semua tamu tersebut:
SELECT FirstName, LastName FROM Clients WHERE LastName LIKE '%son'; Untuk tabel Clients dan indeks pada LastName , kami akan menggunakan spreadsheet ini. Tuliskan hasil yang akan dikembalikan oleh kueri. Pikirkan tentang pendekatan berbeda yang dapat Anda terapkan.
Pendekatan Pemindaian Tabel
Strategi paling sederhana adalah membaca semua data dari tabel dan menuliskan nama tamu ketika nama belakang mereka diakhiri dengan "-son":
For each row from Clients If LastName like '%son' then write down FirstName, LastNameDi sini, kita harus membaca seluruh tabel secara berurutan.
Menggunakan Indeks
Mari kita coba manfaatkan indeks pada kolom LastName . Buka lembar IX_LastName, gunakan untuk menemukan semua klien yang memenuhi kriteria yang diberikan, dan tuliskan nama mereka.
Ternyata Anda harus membaca seluruh indeks untuk menemukan semua Anderson, Robinson, dan Thompson dari tabel. Apakah itu lebih baik daripada menggunakan pemindaian tabel? Selain membaca seluruh indeks, Anda juga harus menemukan, untuk setiap entri yang cocok, baris yang sesuai dari tabel menggunakan nilai rowAddress , lalu tulis FirstName dari sana:
For each row from IX_LastName If LastName like '%son' then Fetch Clients.* where RowAddress = IX_LastName.RowAddress Write down FirstName, LastNameBagi kami, membaca tabel secara berurutan lebih sederhana dan lebih cepat. Untuk RDBMS kami, itu akan tergantung pada persentase baris yang memenuhi kriteria. Jika hanya ada beberapa Anderson, Robinson, dan Thompson dalam tabel besar, RDBMS akan membaca lebih sedikit blok data dari entri indeks yang jauh lebih sempit bahkan jika harus membaca beberapa blok dari tabel saat ditemukan kecocokan. Jika tidak, pemindaian tabel membutuhkan waktu lebih sedikit.
Memesan data dalam indeks tidak memberikan bantuan apa pun dengan kueri semacam itu. Ukuran baris indeks yang lebih kecil dapat membantu—tetapi hanya terkadang.
Latihan 3: LIKE Dengan Wildcard di Akhir
Kali berikutnya detektif kami datang, kami perlu menemukan semua klien yang nama belakangnya dimulai dengan "Rob-."
SELECT FirstName, LastName FROM Clients WHERE LastName LIKE 'Rob%';Cobalah untuk mengekstrak data yang cocok dengan kueri dari spreadsheet yang sama.
Jika Anda menggunakan pendekatan pemindaian tabel, Anda melewatkan kesempatan untuk memanfaatkan sepenuhnya indeks IX_LastName . Jauh lebih cepat untuk menemukan entri pertama dari indeks yang dimulai dengan "Rob-" (Roberts), baca baris berikutnya (Robses dan Robinsons), dan berhenti ketika LastName tidak lagi cocok dengan kriteria:
Get first row from IX_LastName where LastName <= 'Rob' While found and LastName < 'Roc' Fetch Clients.* where rowAddress = IX_LastName.rowAddress Write down FirstName, LastName Get next from IX_LastNameDalam kasus ini, setelah pencarian B-tree untuk entri pertama, kami hanya membaca entri yang memenuhi kriteria. Kami berhenti membaca segera setelah kami membaca nama yang tidak sesuai dengan kriteria.
Mengatasi Masalah Penskalaan B-tree
Biasanya ketika kami menggunakan database baru, ada beberapa tabel pencarian yang terisi dan tabel transaksional yang kosong. Sistem berjalan dengan lancar sejak awal, terutama jika kami menghormati praktik desain database yang baik dengan menormalkan tabel; membuat kunci utama, asing, dan unik; dan mendukung kunci asing dengan indeks yang sesuai.
Setelah beberapa bulan atau tahun, ketika volume data telah meningkatkan kompleksitas sistem dan database secara signifikan, kami mulai melihat penurunan kinerja. Pendapat muncul tentang mengapa sistem melambat dan apa yang harus dilakukan untuk mengatasinya.
Pendapat populer sering kali bahwa ukuran database adalah penyebab utama. Solusinya tampaknya menghapus data historis yang tidak kita perlukan setiap hari dan menempatkannya di database terpisah untuk pelaporan dan analitik.
Mari kita telusuri asumsi utamanya terlebih dahulu.
Kueri Rentang SQL: Apakah Waktu Eksekusi Bergantung pada Ukuran Tabel?
Pertimbangkan kueri rentang khas dari satu tabel:
SELECT Column1, …, ColumnN FROM Table WHERE Column BETWEEN X AND Y; Dengan asumsi ada indeks pada Column , rencana eksekusi yang optimal adalah:
Get first row from IX_Column where Column between X and Y While found and Column <= Y Fetch Table.* where rowAddress = IX_Column.rowAddress Write down Column1, …, ColumnN Get next row from IX_ColumnMari kita hitung blok yang harus dibaca RDBMS untuk mengembalikan data ini.
Bagian Get first row diimplementasikan oleh pencarian B-tree yang kami perkenalkan di pelajaran kedua. Jumlah blok yang harus dibaca sama dengan kedalaman pohon-B. Setelah itu, kami membaca item berikutnya dari tingkat daun indeks.
Dengan kueri OLTP, biasanya semua hasil akan ditemukan dalam satu blok indeks (terkadang dua tetapi jarang lebih). Selain itu, untuk setiap entri indeks, kami memiliki akses ke blok dalam tabel untuk menemukan baris yang sesuai berdasarkan alamatnya. Beberapa baris tabel mungkin berada dalam blok tabel yang sama yang telah kita muat, tetapi untuk menyederhanakan estimasi, mari kita asumsikan bahwa kita memuat blok baru setiap saat.
Jadi rumusnya adalah:
B = D + 1 + R
B adalah jumlah total blok yang dibaca, D adalah kedalaman pohon-B, dan R adalah jumlah baris yang dikembalikan oleh kueri.
Satu-satunya parameter yang bergantung pada jumlah baris dalam tabel adalah D, kedalaman B-tree.
Untuk menyederhanakan perhitungan dan membuat poin, asumsikan bahwa 1.000 entri indeks masuk ke dalam satu blok. D = 1 selama ada kurang dari 1.000 baris dalam tabel. Untuk tabel yang menyimpan transaksi bisnis, hal itu mungkin terjadi pada hari kerja pertama setelah penerapan sistem. Tak lama kemudian, kedalaman B-tree akan meningkat. Selama ada kurang dari 1 juta baris dalam tabel, indeks akan terdiri dari dua tingkat.
Jika kita terganggu oleh waktu respons database yang lambat dan menyalahkan volume data untuk hal ini, perhatikan bahwa tabel transaksi seringkali hanya memiliki jutaan baris. Karena hanya 1 juta baris yang sesuai dengan indeks pohon B dua tingkat, kedalamannya harus setidaknya tiga. Kedalaman tidak akan bertambah menjadi empat kecuali ada lebih dari 1 miliar baris dalam tabel. Sekarang kami memiliki perkiraan yang lebih tepat:
B = 4 + R
Jika R kecil, menurunkan kedalaman B-tree kembali ke dua akan mempercepat kueri secara signifikan. Saat kami mencari berdasarkan nilai kunci utama atau unik, sistem akan membaca empat blok, bukan lima, yang merupakan peningkatan 20%. Jika kueri mengembalikan lebih banyak baris, peningkatannya mungkin tidak terlihat. Masalahnya adalah, untuk banyak aplikasi, kami mungkin tidak dapat mendukung operasi bisnis yang diperlukan dengan menyimpan kurang dari 1 juta transaksi dalam database.

Jadi kesimpulannya tampaknya ukuran meja tidak masalah; dengan kata lain, memindahkan data historis adalah pemborosan waktu dan sumber daya.
Tapi tidak secepat itu: Mari pelajari lebih lanjut tentang struktur indeks B-tree dan bagaimana perubahan data memengaruhinya.
Detail Implementasi Indeks B-tree
Dalam cakupan indeks B-tree kami di pelajaran kedua, kami melihat bahwa semua level dari pohon seimbang (secara fisik) diurutkan berdasarkan nilai kolom kunci. Namun, ketika kita ingin menyisipkan, memperbarui, atau menghapus suatu item, seringkali kita harus memindahkan sejumlah besar data untuk mempertahankan urutannya.
Katakanlah kita memasukkan di tengah blok yang kebetulan penuh. Kami harus membagi blok, mengatur ulang data, dan terkadang bahkan memperbarui data pada level B-tree lain yang menunjuk ke level B-tree saat ini.
Untuk membuat kasus seperti itu lebih efisien, setiap item indeks berisi pointer ke baris sebelumnya dan berikutnya, membuatnya tertaut ganda. Untuk penyisipan secara umum, ini berarti kita hanya menulis item baru sedekat mungkin dengan item sebelumnya dan mengoreksi pointer.
Saat kita perlu membagi blok juga, kita harus menulis item baru di level B-tree sebelumnya. Ini hanya masalah mengoreksi beberapa petunjuk lagi—tidak perlu menulis ulang sebagian besar pohon. Setelah dipecah, kedua blok data kira-kira setengah penuh. Tergantung di mana ada ruang kosong pada disk, blok "tetangga" bisa secara fisik cukup jauh.
Setelah beberapa waktu, fragmentasi indeks meningkat dan perlambatan eksekusi kueri menjadi nyata. Dengan RDBMS yang mengeksekusi kueri seperti yang kami jelaskan, asumsi urutan dan kedekatan item menjadi semakin tidak benar, yang mengarah ke lebih banyak pembacaan. Dalam kasus terburuk, dengan semua blok data setengah kosong, sistem harus membaca blok dua kali lebih banyak.
Pemeliharaan Indeks B-tree
Obat untuk ini adalah defragmentasi indeks (atau "pengindeksan ulang"). Setiap RDBMS menyediakan fitur untuk membuat ulang seluruh indeks; setelah pengindeksan ulang, indeks sekali lagi dipesan secara fisik.
Pengindeksan ulang adalah operasi yang cukup cepat, meskipun membaca dan menulis data dalam jumlah besar. RDBMS modern biasanya menawarkan dua mode pengindeksan ulang, dengan yang lebih cepat membutuhkan tabel untuk dikunci selama pemrosesan. Either way, lebih baik untuk mengindeks ulang di luar jam sibuk. Jika tidak, pemrosesan mungkin memperlambat kinerja database.
Menghapus Data Historis
Ketika kami memiliki tabel dengan miliaran atau bahkan ratusan juta baris, mungkin tidak mungkin untuk menyelesaikan operasi pengindeksan ulang selama jam tidak sibuk.
Untuk menghindari situasi ini, memindahkan data historis dari database OLTP mungkin menjadi solusinya. Namun, jika kami hanya menghapus baris yang lebih lama dari ambang batas tertentu, kami membuat indeks menjadi lebih terfragmentasi, dan kami perlu mengindeks ulang lebih sering.
Partisi SQL untuk Menyelamatkan?
Ada cara untuk menghindari fragmentasi yang disebabkan oleh penghapusan data historis, dengan hanya menyimpan transaksi "aktif" dalam database produksi. Gagasan bahwa semua implementasi RDBMS utama adalah untuk membagi tabel menjadi bagian yang lebih kecil (disebut partisi ) dan menyediakan kemampuan untuk menambahkannya, menghapusnya, dan bahkan mengalihkannya di antara tabel (misalnya, dari tabel aktif ke tabel historis dengan tabel yang sama. struktur).
Mari kita lihat tabel Reservations yang dipartisi dalam spreadsheet ini. Tabel dibagi berdasarkan bulan, dengan nama partisi dipetakan ke periode tanggal dan spreadsheet lainnya. Untuk melihat bagaimana query pada tabel yang dipartisi dijalankan, kita akan melakukan beberapa latihan.
Latihan 4: Kueri Partisi dalam SQL
Dari spreadsheet yang ditautkan di atas, coba ekstrak data yang diminta oleh kueri berikut—tanpa menggunakan indeks apa pun:
SELECT HotelID, ReservationID, ClientID, DateFrom, DateTo FROM Reservations WHERE DateFrom BETWEEN TO_DATE('2021-03-01','YYYY-MM-DD') AND TO_DATE('2021-03-03');Anda mungkin mengetahui bahwa Anda harus terlebih dahulu melihat lembar pemetaan partisi dan menemukan partisi yang berisi reservasi mulai Maret 2021. Setelah itu, Anda membuka partisi yang sesuai, membaca data secara berurutan, dan memfilter baris yang tidak memenuhi kondisi.
Meskipun langsung, Anda mungkin tidak suka menyimpan begitu sedikit baris setelah membaca begitu banyak. Membaca partisi Maret lebih baik daripada membaca seluruh tabel reservasi tetapi masih belum ideal. Bagaimana dengan indeks?
Indeks Global
RDBMS memungkinkan kita untuk membuat indeks global untuk mencakup semua partisi dari tabel yang dipartisi. Tetapi tidak ada perbedaan antara cara kerja indeks global dan reguler di bawahnya: Indeks global tidak sadar akan partisi. Jadi, kueri CRUD menggunakan indeks global tidak melibatkan peta partisi untuk tabelnya.
Kami hanya perlu memperbarui peta partisi ketika kami menjatuhkan seluruh partisi. Kami kemudian harus menghapus setiap baris dari indeks yang mengarah ke partisi yang dihapus. Itu berarti seluruh indeks global perlu dibangun kembali.
Jendela pemadaman tetap diperlukan karena indeks tidak dapat digunakan sampai item usang dihapus. Jika kita dapat secara teratur menjatuhkan partisi, membatasi jumlah yang aktif, maka operasi pengindeksan ulang mungkin cocok dengan jendela pemadaman. Jadi menggunakan partisi memang membantu masalah awal dengan mempersingkat waktu yang diperlukan untuk tugas pemeliharaan, termasuk pemeliharaan indeks global.
Tetapi bagaimana jika kita masih tidak mampu membayar pemadaman?
Indeks yang Dipartisi Secara Global
Strategi ini menyelesaikan masalah itu: Kami hanya mempartisi indeks dengan cara yang sama seperti kami mempartisi tabel. Dalam spreadsheet yang ditautkan oleh spreadsheet partisi, setiap partisi berisi bagiannya dari tabel Reservations dan lembar indeks yang disebut IX_DateFrom, keduanya dipartisi oleh DateFrom .
Untuk mengeksekusi kueri dari Latihan 4, RDBMS pertama-tama akan melihat peta partisi indeks dan mengidentifikasi partisi mana yang berisi tanggal dari rentang. (Dalam kasus kami, ini hanya satu partisi indeks.) Setelah itu, ia akan menggunakan pencarian B-tree, beralih ke tingkat daun, dan akhirnya mengakses tabel menggunakan alamat baris yang sesuai.
Saat kita menghapus partisi dari tabel, cukup dengan menghapus partisi yang sesuai dari indeks. Tidak ada waktu henti yang diperlukan.
Indeks Lokal
Kelemahan utama dari indeks yang dipartisi secara global adalah bahwa kita harus berhati-hati dalam menjatuhkan tabel dan partisi indeks yang sesuai. Hanya ada sedikit biaya tambahan yang terkait dengan membaca dari dan memelihara peta partisi indeks itu sendiri.
Indeks lokal melibatkan pendekatan yang serupa tetapi sedikit berbeda. Alih-alih mempartisi indeks global tunggal, kami membuat indeks lokal di dalam setiap partisi tabel. Dalam melakukannya, indeks lokal berbagi keuntungan utama dari indeks yang dipartisi secara global—yaitu, tidak ada waktu henti—sambil menghindari kekurangannya.
Sepertinya solusi yang sempurna. Namun sebelum kita merayakannya, mari kita selidiki kemungkinan rencana eksekusi dari beberapa pertanyaan.
Latihan 5: Indeks yang Dipartisi Secara Lokal
Coba jalankan kueri lagi, kali ini menggunakan indeks yang dipartisi secara lokal pada DateFrom .
Anda mungkin menggunakan rencana eksekusi ini:
For all partitions where [StartDateFrom, StartDateTo) intersects ['2021-03-01', '2021-03-03'] Get first row from IX_DateFrom where DateFrom between '2021-03-01' and '2021-03-03' While found and DateFrom < '2021-03-04' Fetch Reservations.* where RowAddress = IX_DateFrom.RowAddress Write down HotelID, ReservationID, ClientID, DateFrom, DateTo Get next row from IX_DateFromKami beruntung bahwa semua tanggal termasuk dalam satu partisi, jadi kami harus melintasi hanya satu indeks lokal. Jika jangka waktunya enam bulan, kita harus membaca enam indeks lokal.
Latihan 6: Sebaliknya
Tugas Anda adalah menggunakan kembali peta partisi Reservasi, kali ini untuk membuat daftar periode ketika Klien 124 mengunjungi Hotel 1:
SELECT DateFrom, DateTo FROM Reservations WHERE ClientID = 124 AND HotelID = 1; Di sini kita bisa melihat kelemahan utama dari indeks lokal. Kami harus membaca lembar indeks lokal IX_HotelID_CientID dari setiap partisi tabel Reservations :
For all partitions Get first row from IX_HotelID_ClientID where ClientID = 124 and HotelID = 1 While found and ClientID = 124 and HotelID = 1 Fetch Reservations.* where RowAddress = IX_HotelID_ClientID.RowAddress Write down DateFrom, DateTo Get next row from IX_HotelID_ClientIDEksekusi ini jelas akan membaca lebih banyak blok dan membutuhkan lebih banyak waktu daripada jika tabel tidak dipartisi.
Jadi, sementara kami menemukan cara untuk menjaga kesehatan indeks kami selama periode tidak sibuk, strategi tersebut juga membuat beberapa kueri kami menjadi lebih lambat.
Jika model bisnis kami memungkinkan kami untuk menyimpan sejumlah kecil partisi atau setidaknya kueri yang paling sering berisi kriteria yang memungkinkan RDBMS membaca hanya satu atau dua partisi, solusi ini mungkin yang kami butuhkan. Jika tidak, sebaiknya kita menghindari partisi dan berupaya meningkatkan model data, indeks, dan kueri—dan meningkatkan server database.
Indeks dalam SQL: Apa yang Harus Dipelajari Selanjutnya
Ini adalah akhir dari perjalanan kita. Dalam SQL Indexes Explained, saya fokus pada implementasi indeks yang umum untuk semua RDBMS modern. Saya juga berfokus pada topik yang diminati oleh pengembang aplikasi, dengan mengorbankan topik yang biasanya menyangkut administrator basis data. Yang terakhir akan melakukannya dengan baik untuk meneliti dampak faktor pengisian pada fragmentasi indeks, tetapi orang-orang di kedua peran kemungkinan akan merasa berguna untuk membaca lebih lanjut tentang:
- Caching data dan indeks
- Struktur indeks non-B-tree, seperti hash, GiST, bitmap, dan indeks columnstore
- Indeks berkerumun (dikenal sebagai tabel yang diatur indeks di Oracle)
- indeks fungsional
- Indeks parsial
Pendekatan partisi yang kita diskusikan adalah partisi range . Ini adalah jenis partisi yang paling umum digunakan, tetapi ada yang lain, seperti partisi hash dan partisi daftar. Juga, beberapa RDBMS menawarkan opsi beberapa tingkat partisi.
Terakhir, pengembang SQL sebaiknya menjelajahi topik penting lainnya seputar eksekusi kueri RDBMS—pertama, penguraian kueri, lalu kompilasi rencana eksekusi berbasis biaya, caching, dan penggunaan kembali.
Untuk empat RDMBS yang saya miliki, saya merekomendasikan sumber daya ini sebagai langkah selanjutnya:
Peramal
- Ikhtisar Pengoptimal
- Indeks dan Tabel Terorganisir Indeks
- Mengelola Indeks
- Gambaran Umum Partisi
- Panduan Partisi
- Tanya Tom
PostgreSQL
- Pemrosesan Kueri
- Indeks di PostgreSQL
- Indeks di PostgreSQL (Dokumentasi Resmi)
- Manajemen Penyangga
- Partisi Tabel
- Panduan Partisi
Microsoft SQL Server
- Arsitektur Pemrosesan Kueri
- indeks
- Tabel dan Indeks yang Dipartisi
MySQL/MariaDB
- Memahami Rencana Eksekusi Kueri
- Optimasi dan Indeks
- Partisi - Dasar
- Partisi - Dokumentasi
- Dokumentasi MariaDB: Pengoptimalan dan Indeks Kueri
