MySQL选择特定列比选择慢*
我的MySQL不够强大,所以请原谅任何新手的错误。简短版本: 从destAgg_geo选择locId、count、avg比从destAgg_geo选择*慢很多 prtt.destAgg是在dst_ip主目录上键入的表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> 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。