Saya punya dua tabel, tabel pertama berisi semua artikel / posting blog dalam CMS. Beberapa artikel ini juga dapat muncul di majalah, dalam hal ini mereka memiliki hubungan kunci asing dengan tabel lain yang berisi informasi spesifik majalah.
Berikut ini adalah versi sederhana dari sintaks membuat tabel untuk dua tabel ini dengan beberapa baris yang tidak penting dihapus:
CREATE TABLE `base_article` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date_published` datetime DEFAULT NULL,
`title` varchar(255) NOT NULL,
`description` text,
`content` longtext,
`is_published` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `base_article_date_published` (`date_published`),
KEY `base_article_is_published` (`is_published`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `mag_article` (
`basearticle_ptr_id` int(11) NOT NULL,
`issue_slug` varchar(8) DEFAULT NULL,
`rubric` varchar(75) DEFAULT NULL,
PRIMARY KEY (`basearticle_ptr_id`),
KEY `mag_article_issue_slug` (`issue_slug`),
CONSTRAINT `basearticle_ptr_id_refs_id` FOREIGN KEY (`basearticle_ptr_id`) REFERENCES `base_article` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CMS berisi sekitar 250.000 artikel total dan saya telah menulis skrip Python sederhana yang dapat digunakan untuk mengisi basis data uji dengan data sampel jika mereka ingin mereplikasi masalah ini secara lokal.
Jika saya memilih dari salah satu tabel ini, MySQL tidak memiliki masalah memilih indeks yang sesuai atau mengambil artikel dengan cepat. Namun, saat kedua tabel digabungkan bersama dalam kueri sederhana seperti:
SELECT * FROM `base_article`
INNER JOIN `mag_article` ON (`mag_article`.`basearticle_ptr_id` = `base_article`.`id`)
WHERE is_published = 1
ORDER BY `base_article`.`date_published` DESC
LIMIT 30
MySQL gagal memilih kueri yang sesuai dan kinerja menurun. Berikut penjelasan yang relevan diperpanjang (waktu eksekusi lebih dari satu detik):
+----+-------------+--------------+--------+-----------------------------------+---------+---------+----------------------------------------+-------+----------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------------+--------+-----------------------------------+---------+---------+----------------------------------------+-------+----------+---------------------------------+
| 1 | SIMPLE | mag_article | ALL | PRIMARY | NULL | NULL | NULL | 23830 | 100.00 | Using temporary; Using filesort |
| 1 | SIMPLE | base_article | eq_ref | PRIMARY,base_article_is_published | PRIMARY | 4 | my_test.mag_article.basearticle_ptr_id | 1 | 100.00 | Using where |
+----+-------------+--------------+--------+-----------------------------------+---------+---------+----------------------------------------+-------+----------+---------------------------------+
- EDIT SEPTEMBER 30: Saya bisa menghapus
WHERE
klausa dari kueri ini, tetapi klausaEXPLAIN
masih terlihat sama dan kueri masih lambat.
Salah satu solusi potensial adalah dengan memaksa indeks. Menjalankan kueri yang sama dengan FORCE INDEX (base_articel_date_published)
hasil dalam kueri yang dijalankan sekitar 1,6 milidetik.
+----+-------------+--------------+--------+---------------+-----------------------------+---------+-------------------------+------+-----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------------+--------+---------------+-----------------------------+---------+-------------------------+------+-----------+-------------+
| 1 | SIMPLE | base_article | index | NULL | base_article_date_published | 9 | NULL | 30 | 833396.69 | Using where |
| 1 | SIMPLE | mag_article | eq_ref | PRIMARY | PRIMARY | 4 | my_test.base_article.id | 1 | 100.00 | |
+----+-------------+--------------+--------+---------------+-----------------------------+---------+-------------------------+------+-----------+-------------+
Saya lebih suka tidak harus memaksa indeks pada permintaan ini jika saya bisa menghindarinya, karena beberapa alasan. Paling khusus, permintaan dasar ini dapat difilter / dimodifikasi dalam berbagai cara (seperti pemfilteran oleh issue_slug
) setelah itu base_article_date_published
mungkin tidak lagi menjadi indeks terbaik untuk digunakan.
Adakah yang bisa menyarankan strategi untuk meningkatkan kinerja untuk permintaan ini?
base_article_is_published
(is_published
) .. menurut saya ini adalah tipe boolean ..