indrarajw
indrarajw

Reputation: 198

MySql Query Optimization with LEFT JOIN

I have a MySQL query to optimized because when this query runs it increase MySQL process CPU usage to 100%. So I did some modification on that query and now it decrease its running time but still CPU usage is near to 100%. I index all search fields in both tables.

These 'milestone_and_events' and 'milestone_and_events_reminders' has one to many relationship ('milestone_and_events' have one or more 'milestone_and_events_reminders') and 'milestone_and_events_reminders' table have nearly 1.5 million records.

Is there any way to further optimize this query, can any one give me a guide ?? thank you

This is original query

SELECT MAE.*
     , MAER.reminder_user_id
     , MAER.reminder_type
     , MAER.id as reminder_id 
  FROM milestone_and_events AS MAE 
  LEFT 
  JOIN milestone_and_events_reminders MAER 
    ON MAE.id = MAER.milestone_and_events_id 
 WHERE MAER.alert_time < '$currentTime'
   AND MAER.issued ! = 1 
   AND MAE.completed = 0
 GROUP 
    BY MAE.id
     , MAER.reminder_user_id
     , MAER.reminder_type

This is my current query

$currentTime = date('Y-m-d H:i:s');
$query = 'SELECT MAE.id, MAE.time, MAER.reminder_user_id, MAER.reminder_type, MAER.id AS reminder_id 
            FROM milestone_and_events AS MAE 
            LEFT JOIN milestone_and_events_reminders MAER ON 
            MAE.id = MAER.milestone_and_events_id AND 
            MAER.issued =0 AND 
            MAER.alert_time < "' . $currentTime . '" AND 
            MAE.completed =0 
            WHERE MAER.reminder_type != "onTime"
            GROUP BY MAER.milestone_and_events_id,MAER.reminder_user_id,MAER.reminder_type';

UPDATE 1

this 'milestone_and_events' table have nearly 200 entries.

CREATE TABLE `milestone_and_events` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `description` varchar(250) NOT NULL, 
 `time` datetime NOT NULL,
 `attached_type` int(11) DEFAULT NULL,
 `attached_type_value` int(11) DEFAULT NULL, 
 `completed` int(11) NOT NULL DEFAULT '0', 
 `type` int(11) NOT NULL DEFAULT '1', 
 PRIMARY KEY (`id`),
 KEY `time` (`time`), 
 KEY `completed` (`completed`),
 KEY `id` (`id`,`completed`)
) ENGINE=InnoDB AUTO_INCREMENT=154 DEFAULT CHARSET=utf8

'milestone_and_events_reminders' table have nearly 1.5 million entries.

CREATE TABLE `milestone_and_events_reminders` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `reminder_user_id` int(11) NOT NULL,
  `milestone_and_events_id` int(11) NOT NULL,
  `alert_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `issued` tinyint(11) NOT NULL DEFAULT '0',
  `reminder_type` enum('upComming','delayed','onTime') NOT NULL,
  PRIMARY KEY (`id`),
  KEY `user_id` (`reminder_user_id`),
  KEY `reminder_type` (`reminder_type`),
  KEY `issued` (`issued`),
  KEY `milestone_and_events_id` (`milestone_and_events_id`, `issued`,`reminder_type`),
   CONSTRAINT `milestone_and_events_reminders_ibfk_1` FOREIGN KEY                       (`milestone_and_events_id`) 
   REFERENCES `milestone_and_events` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
   ) ENGINE=InnoDB AUTO_INCREMENT=3323544 DEFAULT CHARSET=utf8

Upvotes: 0

Views: 51

Answers (1)

Gordon Linoff
Gordon Linoff

Reputation: 1269623

This is your query:

SELECT MAE.id, MAE.time, MAER.reminder_user_id, MAER.reminder_type, MAER.id AS reminder_id 
FROM milestone_and_events AS MAE LEFT JOIN
     milestone_and_events_reminders MAER
     ON MAE.id = MAER.milestone_and_events_id AND 
        MAER.issued = 0 AND 
        MAER.alert_time < "' . $currentTime . '"            
WHERE MAE.completed = 0 AND MAER.reminder_type <> "onTime"
GROUP BY MAE.id, MAER.reminder_user_id, MAER.reminder_type;

Note: I moved the condition MAE.completed = 0 from the on clause to the where clause. It does nothing in the on clause. And, I changed the first key in the group by to match the SELECT.

The best indexes for this query are composite indexes : milestone_and_events(completed, id) and milestone_and_events_reminders(milestone_and_events_id, issued, alert_time, reminder_type).

My guess is that putting the completed = 0 where it belongs will reduce the amount of data and improve the performance of the query.

Upvotes: 1

Related Questions