2010-06-04 116 views
4

慢我的MySQL不强壮,所以请原谅任何菜鸟的错误。短版:MySQL选择特定列比选择*

SELECT LOCID,计数,平均FROM destAgg_geo比SELECT *从慢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 |  | 
+---------+------------------+------+-----+---------+-------+ 

geoip的。块是键连接在两个startIpNum和endIpNum(PRIMARY)的表

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; 

下面是优化方案选择*:

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) | 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 

下面是选择优化方案与特定的列:

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) | 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 

下面是从destAgg,只是每一行的优化方案来自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) | 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 

,然后将其慢得多。这里发生了什么?

(是的,我可以只使用从那里*查询结果和过程,但我想知道发生了什么以及为什么)

编辑 - EXPLAIN对视图查询:

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) | 
+----+-------------+---------+------+---------------+------+---------+------+---------+------------------------------------------------+ 
+0

destAgg_geo是如何定义的? – 2010-06-04 17:11:33

+0

这是一个视图:CREATE VIEW destAgg_geo AS SELECT * FROM destAgg JOIN geoip.blocks ON destAgg.dst_ip BETWEEN geoip.blocks.startIpNum AND geoip.blocks。endIpNum; – Pat 2010-06-04 17:12:46

+0

请在构成视图的查询上显示EXPLAIN结果。 – 2010-06-04 17:27:18

回答

1

如果您在两个查询上运行EXPLAIN PLAN,MySQL都会告诉您。

带列的第一个查询不包含任何键列,所以我的猜测是它必须执行TABLE SCAN。

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

+0

EXPLAIN PLAN给我一个错误1064(保留关键字): mysql> EXPLAIN PLAN select * from destAgg_geo; 错误1064(42000):您的SQL语法错误;检查与您的MySQL服务器版本相对应的手册,以便在第1行的'select * from destAgg_geo'附近使用正确的语法。 mysql> EXPLAIN PLAN(select * from destAgg_geo); 错误1064(42000):您的SQL语法错误;检查与您的MySQL服务器版本相对应的手册,以获得在第1行'(select * from destAgg_geo)'处使用的正确语法。 – Pat 2010-06-04 17:17:41

+1

EXPLAIN PLAN是Oracle语法。 MySQL只是使用EXPLAIN,然后是查询。 – 2010-06-04 17:27:13

+0

谢谢比尔。 – duffymo 2010-06-04 17:43:40

0

我会尝试在locId,count,avg上放置一个复合索引,看看它是否不会提高速度。

1

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

我认为这里的真正目标应该是尝试让JOIN使用索引,因此连接的顺序并不重要。

+0

关于如何做到这一点的任何提示? – Pat 2010-06-07 05:05:48