İki tablo var, ilk tablo bir CMS içindeki tüm makaleler / blog gönderileri içerir. Bu makalelerin bazıları bir dergide de görünebilir, bu durumda dergiye özgü bilgiler içeren başka bir tablo ile yabancı anahtar ilişkisi vardır.
Aşağıda, bu iki tablo için tablo oluşturma sözdiziminin basitleştirilmiş bir sürümü bulunmaktadır ve bazı temel olmayan satırlar çıkarılmıştır:
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 toplamda yaklaşık 250.000 makale içeriyor ve bu sorunu yerel olarak çoğaltmak istiyorlarsa, bir test veritabanını örnek verilerle doldurmak için kullanılabilecek basit bir Python betiği yazdım .
Bu tablolardan birini seçersem, MySQL uygun bir dizin seçmek ya da makaleleri hızlı bir şekilde almakta sorun yaşamaz. Ancak, iki tablo aşağıdaki gibi basit bir sorguda birleştirildiğinde:
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 uygun bir sorgulama ve performans düşüşü seçemez. İlgili genişletilmiş açıklama (bir saniyenin üzerinde olan yürütme süresi):
+----+-------------+--------------+--------+-----------------------------------+---------+---------+----------------------------------------+-------+----------+---------------------------------+
| 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 |
+----+-------------+--------------+--------+-----------------------------------+---------+---------+----------------------------------------+-------+----------+---------------------------------+
- 30 Eylül EDIT:
WHERE
yan tümceyi bu sorgudan kaldırabilir , ancakEXPLAIN
yine de aynı görünüyor ve sorgu hala yavaş.
Potansiyel bir çözüm, bir endeksi zorlamaktır. Aynı sorguyu FORCE INDEX (base_articel_date_published)
yaklaşık 1,6 milisaniyede çalışan bir sorguda sonuçlarla çalıştırmak.
+----+-------------+--------------+--------+---------------+-----------------------------+---------+-------------------------+------+-----------+-------------+
| 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 | |
+----+-------------+--------------+--------+---------------+-----------------------------+---------+-------------------------+------+-----------+-------------+
Birkaç nedenden ötürü, bu sorguyu önlemek için bir dizin zorlamak zorunda değil tercih ederim. En önemlisi, bu temel sorgu çeşitli şekillerde (ile filtreleme gibi) filtrelenebilir / değiştirilebilir; issue_slug
bundan sonra base_article_date_published
artık en iyi endeks kullanılmayabilir.
Herkes bu sorgu için performansı artırmak için bir strateji önerebilir?
base_article_is_published
(is_published
) .. bana bakıyor boolean bir tip ..