I've created a view:
create view dh_hits_new_all_old
as
select * from dh_hits_new_201806
union all
select * from dh_hits_new_201807;
When I select something with a where clause containing a field which has an index on the individual tables, MySQL doesn't use any indexes. See the explain outputs:
mysql> explain select count(*) from dh_hits_new_201806 where id_hits_url = 130442;
+----+-------------+--------------------+------------+------+-----------------------------+-----------------------------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------------------+------------+------+-----------------------------+-----------------------------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | dh_hits_new_201806 | NULL | ref | dh_idx-hits_new-id_hits_url | dh_idx-hits_new-id_hits_url | 4 | const | 4453 | 100.00 | Using index |
+----+-------------+--------------------+------------+------+-----------------------------+-----------------------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0,00 sec)
mysql> explain select count(*) from dh_hits_new_201807 where id_hits_url = 130442;
+----+-------------+--------------------+------------+------+-----------------------------+-----------------------------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------------------+------------+------+-----------------------------+-----------------------------+---------+-------+------+----------+-------------+
| 1 | SIMPLE | dh_hits_new_201807 | NULL | ref | dh_idx-hits_new-id_hits_url | dh_idx-hits_new-id_hits_url | 4 | const | 4009 | 100.00 | Using index |
+----+-------------+--------------------+------------+------+-----------------------------+-----------------------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0,00 sec)
mysql> explain select count(*) from dh_hits_new_all_old where id_hits_url = 130442;
+----+-------------+--------------------+------------+------+---------------+-------------+---------+-------+-------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------------------+------------+------+---------------+-------------+---------+-------+-------+----------+-------+
| 1 | PRIMARY | <derived2> | NULL | ref | <auto_key0> | <auto_key0> | 4 | const | 10 | 100.00 | NULL |
| 2 | DERIVED | dh_hits_new_201806 | NULL | ALL | NULL | NULL | NULL | NULL | 65658 | 100.00 | NULL |
| 3 | UNION | dh_hits_new_201807 | NULL | ALL | NULL | NULL | NULL | NULL | 61552 | 100.00 | NULL |
+----+-------------+--------------------+------------+------+---------------+-------------+---------+-------+-------+----------+-------+
3 rows in set, 1 warning (0,00 sec)
I do not understand why. This behavior is reflected of course also in the execution times:
mysql> select count(*) from dh_hits_new_201806 where id_hits_url = 130442;
+----------+
| count(*) |
+----------+
| 4453 |
+----------+
1 row in set (0,01 sec)
mysql> select count(*) from dh_hits_new_201807 where id_hits_url = 130442;
+----------+
| count(*) |
+----------+
| 4009 |
+----------+
1 row in set (0,00 sec)
mysql> select count(*) from dh_hits_new_all_old where id_hits_url = 130442;
+----------+
| count(*) |
+----------+
| 8462 |
+----------+
1 row in set (2,33 sec)
Best Answer
Because it is a kind of bug in the old MySQL version.
UNION
effect using indexes.In the versions older than the 5.7.3 version of MySQL,
UNION
statement works with a temporary table. It means, first of all, your data move to the temporary table and read them from the temporary table before that implement filtering.Check out version 5.7.3 optimizer fixes.