mysql> show index from area;
+-------+------------+----------+--------------+-------------+-----------+------
-------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardi
nality | Sub_part | Packed | Null | Index_type | Comment |
+-------+------------+----------+--------------+-------------+-----------+------
-------+----------+--------+------+------------+---------+
| area | 0 | PRIMARY | 1 | area_id | A |
3811 | NULL | NULL | | BTREE | |
+-------+------------+----------+--------------+-------------+-----------+------
-------+----------+--------+------+------------+---------+
1 row in set (0.09 sec)
mysql>
terminal的字段area_center_id是area表的外键。
1:正常情况下,用小表驱动大表查询看看执行的开销
mysql> select sql_no_cache count(*) from terminal inner join area on terminal.area_center_id=area.area_id;
+----------+
| count(*) |
+----------+
| 1577 |
+----------+
1 row in set (0.13 sec)
mysql> explain select sql_no_cache count(*) from terminal inner join area on terminal.area_center_id=area.area_id;
+----+-------------+----------+--------+---------------+---------+---------+-----------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+--------+---------------+---------+---------+-----------------------------+------+-------------+
| 1 | SIMPLE | terminal | ALL | NULL | NULL | NULL | NULL | 1565 | |
| 1 | SIMPLE | area | eq_ref | PRIMARY | PRIMARY | 4 | cpc.terminal.area_center_id | 1 | Using index |
+----+-------------+----------+--------+---------------+---------+---------+-----------------------------+------+-------------+
2 rows in set (0.09 sec)
mysql> show status like '%last%';
+-----------------+-------------+
| Variable_name | Value |
+-----------------+-------------+
| Last_query_cost | 1906.999000 |
+-----------------+-------------+
1 row in set (0.11 sec)
mysql>
很明显,首先查询的是TERMINAL表。在这个执行计划下,一共开销1906.999次随机IO读取。
现在换过来,用大表驱动小表,看看执行计划和开销
mysql> explain select sql_no_cache count(*) from area inner join terminal on terminal.area_center_id=area.area_id;
+----+-------------+----------+--------+---------------+---------+---------+-----------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+--------+---------------+---------+---------+-----------------------------+------+-------------+
| 1 | SIMPLE | terminal | ALL | NULL | NULL | NULL | NULL | 1565 | |
| 1 | SIMPLE | area | eq_ref | PRIMARY | PRIMARY | 4 | cpc.terminal.area_center_id | 1 | Using index |
+----+-------------+----------+--------+---------------+---------+---------+-----------------------------+------+-------------+
2 rows in set (0.47 sec)
执行计划还是自动选择先读小表,再读大表。
我们再强制执行计划安装查询语句定义的顺序读取表,看看开销
mysql> select sql_no_cache count(*) from area straight_join terminal on terminal.area_center_id=area.area_id;
+----------+
| count(*) |
+----------+
| 1577 |
+----------+
1 row in set (0.38 sec)
mysql> show status like '%last%';
+-----------------+----------------+
| Variable_name | Value |
+-----------------+----------------+
| Last_query_cost | 1192884.999000 |
+-----------------+----------------+
1 row in set (0.06 sec)
mysql> explain select sql_no_cache count(*) from area straight_join terminal on terminal.area_center_id=area.area_id;
+----+-------------+----------+-------+---------------+---------+---------+------+------+--------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------+---------+---------+------+------+--------------------------------+
| 1 | SIMPLE | area | index | PRIMARY | PRIMARY | 4 | NULL | 3811 | Using index |
| 1 | SIMPLE | terminal | ALL | NULL | NULL | NULL | NULL | 1565 | Using where; Using join buffer |
+----+-------------+----------+-------+---------------+---------+---------+------+------+--------------------------------+
2 rows in set (0.06 sec)