'How to solve usng temporary;using filesort using MySQL SELET SELECT UNION SELECT

I have this query:

SELECT *
FROM
  (SELECT a.id AS id,
          a.user_id AS user_id,
          aa.power * a.amount AS total_power,
          a.group_number AS group_number,
          a.amount AS total_amount,
          aa.type AS TYPE
   FROM units a
   JOIN unit_diagrams aa ON a.diagram_id = aa.id
   WHERE a.group_id = 0
     AND a.current_x = 1
     AND a.current_y = 1
     AND a.movement_start_time = 0
   UNION SELECT MIN(b.id) AS id,
                MIN(b.user_id) AS user_id,
                SUM(bb.power * b.amount) AS total_power,
                MAX(b.group_number) AS group_number,
                SUM(b.amount) AS total_amount,
                MIN(bb.type) AS TYPE
   FROM units b
   JOIN unit_diagrams bb ON b.diagram_id = bb.id
   WHERE b.group_id != 0
     AND b.current_x = 1
     AND b.current_y = 1
     AND b.movement_start_time = 0
   GROUP BY b.group_id) hello
ORDER BY group_number ASC,
         total_power DESC
LIMIT 10,
      10

When I run explain on it I get:

+----------------------------------+--------------+------------+--------+-------------------------------------------------------+---------------------------------+------+--------------------------------------------+------+----------------------------------------------+--+
|                                  |              |            |        |                                                       |                                 |      |                                            |      |                                              |  |
+----------------------------------+--------------+------------+--------+-------------------------------------------------------+---------------------------------+------+--------------------------------------------+------+----------------------------------------------+--+
|                                  |              |            |        |                                                       |                                 |      |                                            |      |                                              |  |
|                                  |              |            |        |                                                       |                                 |      |                                            |      |                                              |  |
| 1                                | PRIMARY      | <derived2> | ALL    | NULL                                                  | NULL                            | NULL | NULL                                       | 123  | Using filesort                               |  |
| 2                                | DERIVED      | aa         | index  | PRIMARY,unit_diagrams_idx_id_power_type               | unit_diagrams_idx_id_power_type | 12   | NULL                                       | 6    | Using index                                  |  |
| 2                                | DERIVED      | a          | ref    | current_x,select_units_on_loc,units_idx_id_x_y_tim... | select_units_on_loc             | 20   | const,const,const,const,gpar_game_db.aa.id | 5    | Using index                                  |  |
| 3                                | UNION        | b          | ref    | current_x,select_units_on_loc,units_idx_id_x_y_tim... | current_x                       | 8    | const,const                                | 93   | Using where; Using temporary; Using filesort |  |
| 3                                | UNION        | bb         | eq_ref | PRIMARY,unit_diagrams_idx_id_power_type               | PRIMARY                         | 4    | gpar_game_db.b.diagram_id                  | 1    |                                              |  |
| NULL                             | UNION RESULT | <union2,3> | ALL    | NULL                                                  | NULL                            | NULL | NULL                                       | NULL |                                              |  |
|  4                         | -2,027.1     |            |        |                                                       |                                 |      |                                            |      |                                              |  |
| |              |            |        |                                                       |                                 |      |                                            |      |                                              |  |
+----------------------------------+--------------+------------+--------+-------------------------------------------------------+---------------------------------+------+--------------------------------------------+------+----------------------------------------------+--+

I have this indexes on both tables units and user_diagrams:

ALTER TABLE `units`
  ADD PRIMARY KEY (`id`),
  ADD KEY `current_x` (`current_x`,`current_y`),
  ADD KEY `to_x` (`to_x`,`to_y`),
  ADD KEY `select_units_on_loc` (`group_id`,`movement_start_time`,`current_y`,`current_x`,`diagram_id`,`id`,`user_id`,`group_number`,`amount`),
  ADD KEY `units_idx_id_x_y_time_id` (`group_id`,`current_x`,`current_y`,`movement_start_time`,`diagram_id`);


ALTER TABLE `units`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;
ALTER TABLE `unit_diagrams`
  ADD PRIMARY KEY (`id`),
  ADD KEY `user_id_index` (`user_id`),
  ADD KEY `unit_diagrams_idx_id_power_type` (`id`,`power`,`type`);


ALTER TABLE `unit_diagrams`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;

The table is not very big yet as I am just testing the app now, but even now the query is slower than other parts of my app. If I do profile it executed in about 0.007-0.011 sec, which it too slow, and I am sure this is because of the temporary/filesort. How to optimise this query?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source