2010-06-04 145 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