MySQL选择特定列比选择慢*

MySQL选择特定列比选择慢*,mysql,join,query-optimization,Mysql,Join,Query Optimization,我的MySQL不够强大,所以请原谅任何新手的错误。简短版本: 从destAgg_geo选择locId、count、avg比从destAgg_geo选择*慢很多 prtt.destAgg是在dst_ip主目录上键入的表 mysql> describe prtt.destAgg; +---------+------------------+------+-----+---------+-------+ | Field | Type | Null | Key | De

我的MySQL不够强大,所以请原谅任何新手的错误。简短版本:

从destAgg_geo选择locId、count、avg比从destAgg_geo选择*慢很多

prtt.destAgg是在dst_ip主目录上键入的表

mysql> describe prtt.destAgg;
+---------+------------------+------+-----+---------+-------+
| Field   | Type             | Null | Key | Default | Extra |
+---------+------------------+------+-----+---------+-------+
| dst_ip  | int(10) unsigned | NO   | PRI | 0       |       |
| total   | float unsigned   | YES  |     | NULL    |       |
| avg     | float unsigned   | YES  |     | NULL    |       |
| sqtotal | float unsigned   | YES  |     | NULL    |       |
| sqavg   | float unsigned   | YES  |     | NULL    |       |
| count   | int(10) unsigned | YES  |     | NULL    |       |
+---------+------------------+------+-----+---------+-------+
mysql> describe geoip.blocks;
+------------+------------------+------+-----+---------+-------+
| Field      | Type             | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+-------+
| startIpNum | int(10) unsigned | NO   | MUL | NULL    |       |
| endIpNum   | int(10) unsigned | NO   |     | NULL    |       |
| locId      | int(10) unsigned | NO   |     | NULL    |       |
+------------+------------------+------+-----+---------+-------+
geoip.blocks是一个在startIpNum和endIpNum PRIMARY上都设置了键的表

mysql> describe prtt.destAgg;
+---------+------------------+------+-----+---------+-------+
| Field   | Type             | Null | Key | Default | Extra |
+---------+------------------+------+-----+---------+-------+
| dst_ip  | int(10) unsigned | NO   | PRI | 0       |       |
| total   | float unsigned   | YES  |     | NULL    |       |
| avg     | float unsigned   | YES  |     | NULL    |       |
| sqtotal | float unsigned   | YES  |     | NULL    |       |
| sqavg   | float unsigned   | YES  |     | NULL    |       |
| count   | int(10) unsigned | YES  |     | NULL    |       |
+---------+------------------+------+-----+---------+-------+
mysql> describe geoip.blocks;
+------------+------------------+------+-----+---------+-------+
| Field      | Type             | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+-------+
| startIpNum | int(10) unsigned | NO   | MUL | NULL    |       |
| endIpNum   | int(10) unsigned | NO   |     | NULL    |       |
| locId      | int(10) unsigned | NO   |     | NULL    |       |
+------------+------------------+------+-----+---------+-------+
destAgg_geo是一个视图:

CREATE VIEW destAgg_geo AS SELECT * FROM destAgg JOIN geoip.blocks 
  ON destAgg.dst_ip BETWEEN geoip.blocks.startIpNum AND geoip.blocks.endIpNum;
以下是select*的优化计划:

mysql> explain select * from destAgg_geo;
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows    | Extra                                          |
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+
|  1 | SIMPLE      | blocks  | ALL  | start_end     | NULL | NULL    | NULL | 3486646 |                                                |
|  1 | SIMPLE      | destAgg | ALL  | PRIMARY       | NULL | NULL    | NULL |  101893 | Range checked for each record (index map: 0x1) |
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+
以下是具有特定列的select优化计划:

mysql> explain select locId,count,avg from destAgg_geo;
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows    | Extra                                          |
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+
|  1 | SIMPLE      | destAgg | ALL  | PRIMARY       | NULL | NULL    | NULL |  101893 |                                                |
|  1 | SIMPLE      | blocks  | ALL  | start_end     | NULL | NULL    | NULL | 3486646 | Range checked for each record (index map: 0x1) |
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+
以下是destag中每个列的优化计划,以及geoip.blocks中的locId列的优化计划:

mysql> explain select dst_ip,total,avg,sqtotal,sqavg,count,locId from destAgg_geo;
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows    | Extra                                          |
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+
|  1 | SIMPLE      | blocks  | ALL  | start_end     | NULL | NULL    | NULL | 3486646 |                                                |
|  1 | SIMPLE      | destAgg | ALL  | PRIMARY       | NULL | NULL    | NULL |  101893 | Range checked for each record (index map: 0x1) |
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+
删除除dst_ip之外的任何列,范围检查翻转到块:

mysql> explain select dst_ip,avg,sqtotal,sqavg,count,locId from destAgg_geo;
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows    | Extra                                          |
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+
|  1 | SIMPLE      | destAgg | ALL  | PRIMARY       | NULL | NULL    | NULL |  101893 |                                                |
|  1 | SIMPLE      | blocks  | ALL  | start_end     | NULL | NULL    | NULL | 3486646 | Range checked for each record (index map: 0x1) |
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+
那就慢多了。这是怎么回事

是的,我可以使用*查询结果和流程,但我想知道发生了什么以及为什么

编辑-解释视图查询:

mysql> explain SELECT * FROM destAgg JOIN geoip.blocks ON destAgg.dst_ip BETWEEN geoip.blocks.startIpNum AND geoip.blocks.endIpNum;
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows    | Extra                                          |
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+
|  1 | SIMPLE      | blocks  | ALL  | start_end     | NULL | NULL    | NULL | 3486646 |                                                |
|  1 | SIMPLE      | destAgg | ALL  | PRIMARY       | NULL | NULL    | NULL |  101893 | Range checked for each record (index map: 0x1) |
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+

MySQL可以告诉您是否对这两个查询都运行EXPLAIN PLAN

第一个包含列的查询不包含任何键列,因此我猜它必须进行表扫描


使用SELECT*的第二个查询包含主键,因此它可以使用索引。

我会尝试将compisite索引放在locId、count、avg上,看看这是否不会提高速度。

范围过滤器最后应用,所以问题是查询优化器在一种情况下选择首先加入较大的表,小桌子先放在另一张桌子上。也许对优化器有更多了解的人可以告诉我们,为什么优化器以不同的顺序连接每个表


我认为这里的真正目标应该是尝试让连接使用索引,这样连接的顺序就不那么重要了。

这是一个视图:创建视图destag_geo AS SELECT*FROM destAgg JOIN geoip.blocks ON destAgg.dst_ip geoip.blocks.startIpNum和geoip.blocks.endIpNum之间;请在组成视图的查询上显示解释结果。添加到原始问题解释计划中会给我一个错误1064保留关键字:mysql>解释计划选择*from destag_geo;错误1064 42000:您的SQL语法有错误;检查与您的MySQL服务器版本对应的手册,以了解在第1行MySQL>解释计划从destag_geo选择*附近使用的正确语法;错误1064 42000:您的SQL语法有错误;检查与您的MySQL服务器版本相对应的手册,以了解在第1行的“select*from destag_geo”附近使用的正确语法解释计划是Oracle语法。MySQL只是在查询之后使用EXPLAIN。