2010-10-04 57 views
1

于是我开始了与此查询:的MySQL我想优化这个进一步

SELECT * FROM TABLE1 WHERE hash IN (SELECT id FROM temptable); 

花了一辈子,所以我跑了一个解释:

mysql> explain SELECT * FROM TABLE1 WHERE hash IN (SELECT id FROM temptable); 
+----+--------------------+-----------------+------+---------------+------+---------+------+------------+-------------+ 
| id | select_type  | table   | type | possible_keys | key | key_len | ref | rows  | Extra  | 
+----+--------------------+-----------------+------+---------------+------+---------+------+------------+-------------+ 
| 1 | PRIMARY   | TABLE1   | ALL | NULL   | NULL | NULL | NULL | 2554388553 | Using where | 
| 2 | DEPENDENT SUBQUERY | temptable  | ALL | NULL   | NULL | NULL | NULL |  1506 | Using where | 
+----+--------------------+-----------------+------+---------------+------+---------+------+------------+-------------+ 
2 rows in set (0.01 sec) 

它不是使用索引。所以,我的第二通:

mysql> explain SELECT * FROM TABLE1 JOIN temptable ON TABLE1.hash=temptable.hash; 
+----+-------------+-----------------+------+---------------+----------+---------+------------------------+------+-------------+ 
| id | select_type | table   | type | possible_keys | key  | key_len | ref     | rows | Extra  | 
+----+-------------+-----------------+------+---------------+----------+---------+------------------------+------+-------------+ 
| 1 | SIMPLE  | temptable  | ALL | hash   | NULL  | NULL | NULL     | 1506 |    | 
| 1 | SIMPLE  | TABLE1   | ref | hash   | hash  | 5  | testdb.temptable.hash | 527 | Using where | 
+----+-------------+-----------------+------+---------------+----------+---------+------------------------+------+-------------+ 
2 rows in set (0.00 sec) 

我可以做任何其他的优化?

+1

你真的需要'SELECT *'? – nico 2010-10-04 06:09:26

+0

@nico:+1。谢谢。 – Legend 2010-10-04 06:35:21

回答

1

您可以通过使用covering index获得更多的速度,但需要额外的空间消耗。覆盖索引是一种可以满足查询中所有请求列的索引,而无需对聚集索引进行进一步查找。

首先摆脱SELECT *并明确选择所需的字段。然后,您可以将SELECT子句中的所有字段添加到组合索引的右侧。例如,如果你的查询将是这样的:

SELECT first_name, last_name, age 
FROM table1 
JOIN temptable ON table1.hash = temptable.hash; 

然后你就可以拥有一个覆盖索引,看起来像这样:

CREATE INDEX ix_index ON table1 (hash, first_name, last_name, age); 
+0

我将删除*。一个简单的问题:如果空间不是真的问题,那么在所有列上添加索引是否合乎逻辑? – Legend 2010-10-04 06:19:59

+0

@传奇:是的,在许多情况下,建议。一般而言,覆盖索引超过常规索引的主要缺点是占用更多空间,并且插入和更新速度稍慢(或占用更多资源)。除非你每秒插入许多新记录,否则这很少是一个问题,而且通常可以忽略不计。 – 2010-10-04 06:41:27

+0

谢谢。我会试试看看它是否有效。我的表有20亿条记录,但我不会再更新它们。 – Legend 2010-10-04 07:39:54