2009-07-29 19 views
3

我有兩個表,表A和表B:如何在進行簡單的JOIN時防止全表掃描?

CREATE TABLE `TableA` (
    `shared_id` int(10) unsigned NOT NULL default '0', 
    `foo` int(10) unsigned NOT NULL, 
    PRIMARY KEY (`shared_id`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 


CREATE TABLE `TableB` (
    `shared_id` int(10) unsigned NOT NULL auto_increment, 
    `bar` int(10) unsigned NOT NULL, 
    KEY `shared_id` (`shared_id`) 
) ENGINE=MyISAM AUTO_INCREMENT=1001 DEFAULT CHARSET=latin1 

這裏是我的查詢:

SELECT TableB.bar 
FROM TableB, TableA 
WHERE TableA.foo = 1000 
AND TableA.shared_id = TableB.shared_id; 

這裏的問題:

mysql> explain SELECT TableB.bar FROM TableB, TableA WHERE TableA.foo = 1000 AND TableA.shared_id = TableB.shared_id; 

+----+-------------+--------------+--------+---------------+---------+---------+------------------------------------------+------+-------------+ 
| id | select_type | table  | type | possible_keys | key  | key_len | ref          | rows | Extra  | 
+----+-------------+--------------+--------+---------------+---------+---------+------------------------------------------+------+-------------+ 
| 1 | SIMPLE  | TableB  | ALL | shared_id  | NULL | NULL | NULL          | 1000 |    | 
| 1 | SIMPLE  | TableA  | eq_ref | PRIMARY  | PRIMARY | 4  | MyDatabase.TableB.shared_id    | 1 | Using where | 
+----+-------------+--------------+--------+---------------+---------+---------+------------------------------------------+------+-------------+ 

是否有我可以添加的索引那會妨礙TableB的全表掃描?

回答

2

Runcible,你的查詢可能會使用一些重寫。您應該始終在ON子句中指定JOIN條件,而不是在WHERE中。

您的查詢就會變成:

SELECT TableB.bar 
FROM TableB 
JOIN TableA 
ON TableB.shared_id = TableA.shared_id 
AND TableA.foo = 1000; 

不僅要做到這一點:

ALTER TABLE TableB ADD INDEX (shared_id,bar); 

你要索引添加到如下:

ALTER TABLE TableA ADD INDEX (foo, shared_id); 

請執行此操作,並提供EXPLAIN輸出。

另請注意,通過在(shared_id,bar)上添加索引,您只是使您的(shared_id)索引變得冗餘。算了吧。

+0

添加第二個索引的確有用。 @hobodave:感謝您的幫助! – Runcible 2009-07-30 21:06:03