MySQL processlist shows that there are many threads running the same slow query, and the back log continue to grow...
Looking at SQL, it is not complex:
SELECT COUNT(*) FROM tblA WHERE tblA.fkA_ID = 38926722 AND tblA.fkAType_ID = 1 AND tblA.fkADetail_ID = 476 AND tblA.`Date` = '2013-05-10 07:14:41' AND tblA.Time = '2013-05-10 07:14:41'
And the EXPLAIN output is:
id: 1 select_type: SIMPLE table: tblA type: index_merge possible_keys: FK_A_ID,FK_fkAType_ID,FK_fkADetail_ID,IX_Date key: FK_ApmAudit2ApmCase,FK_ApmAudit2ApmAuditType key_len: 4,1 ref: NULL rows: 1 Extra: Using intersect(FK_A_ID,FK_fkAType_ID); Using where 1 row in set (0.00 sec)
At first glance, it does not look too bad. MySQL is using two different indexes to search 1 out of 66M rows to return the count of total rows. It is worth mentioning here that column fkAType_ID is not very selective i.e. it holds value 1 or 2. Sadly, 90% of the rows had value 1. This means query is looking at millions of rows before doing index merge with column fkA_ID.
Ok, we know now what's wrong with the query, let's see what options do we have to to optimize this query:?
A) The table hasn't been purged for the past several months; this couldn't be done at this time
B) Pass index hints to the query optimizer to favor index on fkA_ID column.
SELECT COUNT(*) FROM tblA USE INDEX (FK_A_ID) WHERE tblA.fkA_ID = 38926722 AND tblA.fkAType_ID = 1 AND tblA.fkADetail_ID = 476 AND tblA.`Date` = '2013-05-10 07:14:41' AND tblA.Time = '2013-05-10 07:14:41' Query OK, 1 row affected (0.20 sec)
Query completed in a fraction of a second, compared to 30 seconds! Lets look at EXPLAIN output:
*************************** 1. row *************************** id: 1 select_type: SIMPLE table: tblA type: ref possible_keys: FK_A_ID key: FK_A_ID key_len: 4 ref: const rows: 179 Extra: Using where 1 row in set (0.00 sec)Once the backlog consumed, in the next available maintenance window, we purged historic data, removed index hints and added following index to the table:
ALTER TABLE tblA DROP INDEX `FK_A_ID`, ADD INDEX `FK_A_ID_DATE` (`fkA_ID`,`Date`)Note: index on column FK_fkAType_ID is needed due to foreign key constraint. The table structure info:
CREATE TABLE `tblA` ( `pkID` int(10) unsigned NOT NULL AUTO_INCREMENT, `fkApplication_ID` smallint(5) unsigned NOT NULL, `fkA_ID` int(10) unsigned NOT NULL, `fkAType_ID` tinyint(3) unsigned NOT NULL, `Date` date NOT NULL, ... KEY `FK_Application` (`fkApplication_ID`), KEY `FK_fkAType_ID` (`fkAType_ID`), KEY `IX_Date` (`Date`), KEY `FK_A_ID` (`fkA_ID`), ... CONSTRAINT `FK_AType` FOREIGN KEY (`fkAType_ID`) REFERENCES `tblAType` (`pkAType_ID`), ... ) ENGINE=InnoDB AUTO_INCREMENT=505970021 DEFAULT CHARSET=utf8
Nice post, but it seems less, but very interesting to read and understand, hope post more blogs with more information Thank you
ReplyDeletePlease Click Here For More Information About Any Course or Training Institute all over the world
https://www.calfre.com/USA/Texas/Houston/Oracle-Fusion-SCM-Training/listing
Oracle Fusion SCM Training in Houston
Thx
ReplyDelete