Pembagian berdasarkan rentang (range partitioning) membagi tabel atau indeks menjadi segmen-segmen berdasarkan nilai batas. Pendekatan ini merupakan standar untuk data time-series dan tabel besar yang memerlukan rotasi data secara berkala—memungkinkan pengoptimal kueri melewati segmen-segmen yang tidak relevan sepenuhnya serta memungkinkan penambahan atau penghapusan data pada tingkat partisi, bukan baris per baris.
Kapan range partitioning cocok digunakan
Percepat kueri rentang dengan pemangkasan partisi
Ketika tabel besar sering dikueri berdasarkan rentang tanggal atau numerik—seperti tabel pesanan (ORDER) atau jadwal pembelian (LINEITEM)—range partitioning memungkinkan pengoptimal kueri melewati partisi-partisi yang tidak relevan sepenuhnya. Teknik ini dikenal sebagai pemangkasan partisi (partition pruning).
Sebagai contoh, jika Anda mempartisi tabel pesanan berdasarkan tahun dan mengkueri data dari satu tahun tertentu, pengoptimal hanya mengakses satu partisi alih-alih memindai semua partisi. Pada tabel yang berisi data delapan tahun, kueri satu tahun hanya menyentuh satu dari delapan partisi—memberikan pengurangan proporsional dalam I/O dan waktu pemindaian.
Menyederhanakan rotasi data dengan jendela bergulir
Range partitioning merupakan pendekatan standar untuk memelihara jendela data bergulir—misalnya, menyimpan data 36 bulan terakhir. Menambahkan bulan baru dan menghapus bulan terlama dilakukan pada tingkat partisi, bukan tingkat baris:
Muat data bulan baru ke dalam tabel staging.
Bersihkan dan buat indeks pada tabel staging.
Jalankan
EXCHANGE PARTITIONuntuk menukar tabel staging ke dalam tabel terpartisi. Tabel terpartisi tetap dapat dikueri selama proses ini.Jalankan
DROP PARTITIONuntuk menghapus partisi bulan terlama.
Operasi pada seluruh partisi jauh lebih efisien dibandingkan menghapus baris satu per satu atau membangun ulang indeks di seluruh tabel.
Bagi tabel besar untuk kemudahan manajemen
Operasi backup dan pemulihan pada satu tabel besar dapat melebihi jendela pemeliharaan. Range partitioning membagi tabel menjadi blok-blok logis yang lebih kecil, sehingga Anda dapat melakukan backup, memulihkan, atau mengarsipkan partisi-partisi secara independen.
Contoh range partitioning
Contoh berikut menunjukkan tabel orders yang mencakup lebih dari sembilan tahun. Tabel ini dipartisi berdasarkan kolom o_orderdate menjadi delapan partisi tahunan (ditambah satu partisi overflow). Tata letak ini mendukung baik analisis penjualan interval pendek melalui pemangkasan partisi maupun manajemen data jendela bergulir.
CREATE TABLE `orders` (
`o_orderkey` int(11) NOT NULL,
`o_custkey` int(11) NOT NULL,
`o_orderstatus` char(1) DEFAULT NULL,
`o_totalprice` decimal(10,2) DEFAULT NULL,
`o_orderDATE` date NOT NULL,
`o_orderpriority` char(15) DEFAULT NULL,
`o_clerk` char(15) DEFAULT NULL,
`o_shippriority` int(11) DEFAULT NULL,
`o_comment` varchar(79) DEFAULT NULL,
PRIMARY KEY (`o_orderkey`,`o_orderDATE`,`o_custkey`),
KEY `o_orderkey` (`o_orderkey`),
KEY `i_o_custkey` (`o_custkey`),
KEY `i_o_orderdate` (`o_orderDATE`)
) ENGINE=InnoDB
PARTITION BY RANGE (TO_DAYS(o_orderdate))
(PARTITION item1 VALUES LESS THAN (TO_DAYS('1992-01-01')),
PARTITION item2 VALUES LESS THAN (TO_DAYS('1993-01-01')),
PARTITION item3 VALUES LESS THAN (TO_DAYS('1994-01-01')),
PARTITION item4 VALUES LESS THAN (TO_DAYS('1995-01-01')),
PARTITION item5 VALUES LESS THAN (TO_DAYS('1996-01-01')),
PARTITION item6 VALUES LESS THAN (TO_DAYS('1997-01-01')),
PARTITION item7 VALUES LESS THAN (TO_DAYS('1998-01-01')),
PARTITION item8 VALUES LESS THAN (TO_DAYS('1999-01-01')),
PARTITION item9 VALUES LESS THAN (MAXVALUE));Jalankan EXPLAIN untuk memastikan terjadinya pemangkasan partisi. Kueri pada o_orderDATE = '1992-03-01' seharusnya hanya mengakses item2:
EXPLAIN SELECT * FROM orders WHERE o_orderDATE = '1992-03-01';+----+-------------+--------+------------+------+---------------+---------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+---------------+---------+-------+------+----------+-------+
| 1 | SIMPLE | orders | item2 | ref | i_o_orderdate | i_o_orderdate | 3 | const | 1 | 100.00 | NULL |
+----+-------------+--------+------------+------+---------------+---------------+---------+-------+------+----------+-------+Karena keterbatasan tipe RANGE, pernyataan DDL asli mungkin tidak ditampilkan setelah Anda mempartisi tabel menggunakanTO_DAYS()dan menjalankan pernyataanSHOW CREATE TABLE. Batas partisi mungkin muncul sebagai nilai hari dalam bentuk integer, bukan string tanggal. Ini merupakan keterbatasan tampilan yang sudah diketahui dan tidak memengaruhi perilaku kueri.
SHOW CREATE TABLE orders;CREATE TABLE `orders` (
...
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50100 PARTITION BY RANGE (to_days(`o_orderDATE`))
(PARTITION item1 VALUES LESS THAN (727563),
PARTITION item2 VALUES LESS THAN (727929),
PARTITION item3 VALUES LESS THAN (728294),
PARTITION item4 VALUES LESS THAN (728659),
PARTITION item5 VALUES LESS THAN (729024),
PARTITION item6 VALUES LESS THAN (729390),
PARTITION item7 VALUES LESS THAN (729755),
PARTITION item8 VALUES LESS THAN (730120),
PARTITION item9 VALUES LESS THAN MAXVALUE) */Pembagian berdasarkan rentang kolom
Pembagian berdasarkan rentang kolom (range columns partitioning) memperluas range partitioning dalam tiga cara:
Column names only:
RANGE COLUMNS()menerima nama kolom, bukan ekspresi.Multi-column support:
RANGE COLUMNS()dapat mencakup satu atau beberapa kolom. Penempatan partisi ditentukan berdasarkan perbandingan tupel, bukan perbandingan nilai skalar.Dukungan tipe data yang lebih luas: Kolom kunci partisi dapat bertipe INTEGER, STRING, DATE, atau DATETIME.
CREATE TABLE `orders` (
`o_orderkey` int(11) NOT NULL,
`o_custkey` int(11) NOT NULL,
`o_orderstatus` char(1) DEFAULT NULL,
`o_totalprice` decimal(10,2) DEFAULT NULL,
`o_orderDATE` date NOT NULL,
`o_orderpriority` char(15) DEFAULT NULL,
`o_clerk` char(15) DEFAULT NULL,
`o_shippriority` int(11) DEFAULT NULL,
`o_comment` varchar(79) DEFAULT NULL,
PRIMARY KEY (`o_orderkey`,`o_orderDATE`,`o_custkey`),
KEY `o_orderkey` (`o_orderkey`),
KEY `i_o_custkey` (`o_custkey`),
KEY `i_o_orderdate` (`o_orderDATE`)
) ENGINE=InnoDB
PARTITION BY RANGE COLUMNS(o_orderdate)
(PARTITION item1 VALUES LESS THAN ('1992-01-01'),
PARTITION item2 VALUES LESS THAN ('1993-01-01'),
PARTITION item3 VALUES LESS THAN ('1994-01-01'),
PARTITION item4 VALUES LESS THAN ('1995-01-01'),
PARTITION item5 VALUES LESS THAN ('1996-01-01'),
PARTITION item6 VALUES LESS THAN ('1997-01-01'),
PARTITION item7 VALUES LESS THAN ('1998-01-01'),
PARTITION item8 VALUES LESS THAN ('1999-01-01'),
PARTITION item9 VALUES LESS THAN (MAXVALUE));