這是使用MySQL 5.5。 我似乎無法說服MySQL使用這些查詢的索引,並且它們需要2-10秒的時間才能在有110萬行的表上運行。如何讓mysql使用帶有簡單AND + OR查詢的索引?
表:
CREATE TABLE `notifiable_events` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`key` varchar(255) NOT NULL,
`trigger_profile_id` int(10) unsigned DEFAULT NULL,
`model1` varchar(25) NOT NULL,
`model1_id` varchar(36) NOT NULL,
`model2` varchar(25) NOT NULL DEFAULT '',
`model2_id` varchar(36) NOT NULL DEFAULT '',
`event_data` text,
`created` datetime DEFAULT NULL,
`modified` datetime DEFAULT NULL,
`deleted` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `key` (`key`),
KEY `notifiable_events__trigger_profile` (`trigger_profile_id`),
KEY `deleted` (`deleted`),
KEY `noti_evnts__m2` (`model2`),
KEY `noti_evnts__m1` (`model1`),
CONSTRAINT `notifiable_events__trigger_profile` FOREIGN KEY (`trigger_profile_id`) REFERENCES `profiles` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1177918 DEFAULT CHARSET=utf8
QUERY:
SELECT *
FROM notifiable_events
WHERE (`model1` = 'page' AND `model1_id` = '54321')
OR (`model2` = 'page' AND `model2_id` = '12345');
EXPLAIN(S):
mysql> EXPLAIN EXTENDED SELECT * FROM notifiable_events WHERE (`model1` = 'page' AND `model1_id` = '922645') OR (`model2` = 'page' AND `model2_id` = '922645')\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: notifiable_events type: ALL possible_keys: noti_evnts__m2,noti_evnts__m1,noti_evnts__m1_m2 key: NULL key_len: NULL ref: NULL rows: 1033088 filtered: 100.00 Extra: Using where 1 row in set, 1 warning (0.00 sec) mysql> EXPLAIN EXTENDED SELECT * FROM notifiable_events WHERE (`model1` = 'page' AND `model1_id` = '922645') OR (`model1` = 'page' AND `model1_id` = '922645')\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: notifiable_events type: ref possible_keys: noti_evnts__m1,noti_evnts__m1_m2 key: noti_evnts__m1 key_len: 77 ref: const rows: 1 filtered: 100.00 Extra: Using where 1 row in set, 1 warning (0.00 sec) mysql> EXPLAIN EXTENDED SELECT * FROM notifiable_events WHERE (`model2` = 'page' AND `model2_id` = '922645') OR (`model2` = 'page' AND `model2_id` = '922645')\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: notifiable_events type: ref possible_keys: noti_evnts__m2 key: noti_evnts__m2 key_len: 77 ref: const rows: 428920 filtered: 100.00 Extra: Using where 1 row in set, 1 warning (0.00 sec)
你可以看到,如果我只用MODEL1或只使用MODEL2那麼它會使用索引,但是,只要我嘗試將它們一起使用,就會完全放棄索引,並執行全表掃描。 我已經嘗試了FORCE INDEX,並且我嘗試了多鍵索引的組合(我爲此表留下了一個作爲示例)。我也嘗試重新排列查詢中元素的順序,但似乎也沒有任何效果。
更新: 我忘了提及我已經嘗試了ANALYZE和OPTIMIZE(每次多次,沒有改變)。我也已經在* _id(基數非常糟糕,這些列大多是唯一條目)和索引中使用了所有4列的索引。在這兩種情況下都沒有改進或使用指數。
它似乎應該很容易使用索引來限制在這裏檢查的行,所以我希望我只是錯過了一些東西。
如果似乎'x_id'列應該被索引(改爲)?無論如何,如果表格統計信息被更新呢? – 2012-07-12 01:50:22