收到一個mysql服務器負載告警,上去一看,load average都飆到280多了,用top一看,CPU跑到了336%,不過IO和內存的負載并不高,根據經驗,應該又是一起索引引起的慘案了。
看下processlist以及slow query情況,發現有一個SQL經常出現,執行計劃中的掃描記錄數看著還可以,單次執行耗時為0.07s,還不算太大。乍一看,可能不是它引發的,但出現頻率實在太高,而且執行計劃看起來也不夠完美:
| mysql> explain SELECT count(1) FROM a , b WHERE a.id = b.video_id and b.state = 1 AND b.column_id = '81'/G |
| *************************** 1. row ***************************id: 1select_type: SIMPLEtable: btype: index_mergepossible_keys: columnid_videoid,column_id,state,video_time_stamp,idx_videoidkey: column_id,statekey_len: 4,4ref: NULLrows: 100Extra: Using intersect(column_id,state); Using where*************************** 2. row ***************************id: 1select_type: SIMPLEtable: atype: eq_refpossible_keys: PRIMARYkey: PRIMARYkey_len: 4ref: b.video_idrows: 1Extra: Using where; Using index |
再看下該表的索引情況:
| mysql> show index from b/G |
| *************************** 1. row ***************************Table: bNon_unique: 0Key_name: PRIMARYSeq_in_index: 1Column_name: idCollation: ACardinality: 167483Sub_part: NULLPacked: NULLNull:Index_type: BTREEComment:Index_comment:*************************** 2. row ***************************Table: bNon_unique: 1Key_name: column_idSeq_in_index: 1Column_name: column_idCollation: ACardinality: 8374Sub_part: NULLPacked: NULLNull:Index_type: BTREEComment:Index_comment:*************************** 3. row ***************************Table: bNon_unique: 1Key_name: stateSeq_in_index: 2Column_name: stateCollation: ACardinality: 5Sub_part: NULLPacked: NULLNull:Index_type: BTREEComment:Index_comment: |
可以看到執行計劃中,使用的是index merge,效率自然沒有用聯合索引(也有的叫做覆蓋索引)來的好了,而且 state 字段的基數(唯一性)太差,索引效果很差。刪掉兩個獨立索引,修改成聯合看看效果如何:
| mysql> show index from b; |
| *************************** 1. row ***************************Table: bNon_unique: 0Key_name: PRIMARYSeq_in_index: 1Column_name: idCollation: ACardinality: 128151Sub_part: NULLPacked: NULLNull:Index_type: BTREEComment:Index_comment:*************************** 2. row ***************************Table: bNon_unique: 1Key_name: idx_columnid_stateSeq_in_index: 1Column_name: column_idCollation: ACardinality: 3203Sub_part: NULLPacked: NULLNull:Index_type: BTREEComment:Index_comment:*************************** 3. row ***************************Table: bNon_unique: 1Key_name: idx_columnid_stateSeq_in_index: 2Column_name: stateCollation: ACardinality: 3463Sub_part: NULLPacked: NULLNull:Index_type: BTREEComment:Index_comment:mysql> explain SELECT count(1) FROM a , b WHERE a.id = b.video_id and b.state = 1 AND b.column_id = '81' /G*************************** 1. row ***************************id: 1select_type: SIMPLEtable: btype: refpossible_keys: columnid_videoid,idx_videoid,idx_columnid_statekey: columnid_videoidkey_len: 4ref: constrows: 199Extra: Using where*************************** 2. row ***************************id: 1select_type: SIMPLEtable: atype: eq_refpossible_keys: PRIMARYkey: PRIMARYkey_len: 4ref: b.video_idrows: 1Extra: Using where; Using index |