2012-08-15 67 views
0

我有四個表,我試圖加入並輸出結果到一個新表。我的代碼如下所示:在mysql中連接表時沒有正確使用索引?

create table tbl 
select a.dte, a.permno, (ret - rf) f0_xs_ret, (xs_ret - (betav*xs_mkt)) f0_resid, mkt_cap  last_year_mkt_cap, betav beta_value 
from a inner join b using (dte) 
inner join c on (year(a.dte) = c.yr and a.permno = c.permno) 
inner join d on (a.permno = d.permno and year(a.dte)-1 = year(d.dte)); 

所有的表有多個索引和表a(dte, permno)確定一個唯一的記錄,爲表bdte ID是唯一的記錄,爲表c(yr, permno) ID的唯一記錄併爲表d,(dte, permno)確定一個唯一記錄。該解釋從查詢的select部分是:

+----+-------------+-------+--------+-------------------+---------+---------+---------- ------------------------+--------+-------------------+ 
| id | select_type | table | type | possible_keys  | key  | key_len | ref         | rows | Extra    | 
+----+-------------+-------+--------+-------------------+---------+---------+---------- ------------------------+--------+-------------------+ 
| 1 | SIMPLE  | d  | ALL | idx1    | NULL | NULL | NULL         | 264129 |     | 
| 1 | SIMPLE  | c  | ref | idx2    | idx2 | 4  |  achernya.d.permno    |  16 |     | 
| 1 | SIMPLE  | b  | ALL | PRIMARY,idx2  | NULL | NULL | NULL         | 12336 | Using join buffer | 
| 1 | SIMPLE  | a  | eq_ref | PRIMARY,idx1,idx2 | PRIMARY | 7  | achernya.b.dte,achernya.d.permno |  1 | Using where  | 
+----+-------------+-------+--------+-------------------+---------+---------+----------------------------------+--------+-------------------+ 

爲什麼MySQL的要讀這麼多行來處理這件事情?如果我正確閱讀這個,它必須讀(264129*16*12336)行,這應該需要一個好月份。

可能有人請解釋一下這是怎麼回事呢?

+0

哦 - 我看到的。我的理解是,對於第一個表中讀取的每一行,它必須讀取另一個表中的16 * 12336行。我認爲它會簡單地沿着第一個表的行,然後對第一行的每一行按順序讀取其他行。是不正確的? – Alex 2012-08-15 03:26:37

+0

你是否確定這是理解行列的方法?我瞭解了通過允許mysql轉到表的子集來縮小要掃描的行數量的索引,但是它仍然必須讀取我原始表中每行的整個子集? – Alex 2012-08-15 03:32:55

+0

我讀這個網上:「omputing行進行檢查是比較複雜的,是採取從各行的估計行數頻繁方法聯接和繁殖他們......」他接着說,這是不準確等,但他並沒有說任何關於添加東西的事情。你有什麼資料可以查看嗎?如果這只是一個總和然後我的查詢將已經 – Alex 2012-08-15 03:39:07

回答

2

MySQL有,因爲你使用的功能爲您的加盟條件,讀取行。 dte上的索引無助於在查詢中解析YEAR(dte)。如果你想快速做到這一點,那麼把年份放在自己的列中用於連接並將索引移動到該列,即使這意味着一些非規範化。

至於在索引中的其他列,你不適用功能,他們可以不使用,如果該索引將不會提供多少好處,或者他們是不是在索引中最左邊的列和你不在連接條件中不使用該索引的最左邊的前綴。

有時MySQL不使用索引,即使有索引可用。出現這種情況的一種情況是,優化程序估計使用索引需要MySQL訪問表中非常大部分的行。 (在這種情況下,表掃描可能會更快,因爲它需要較少的追求。)

http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html

+0

是有道理的。我剛剛做到了這一點,併爲年度專欄和事情加分。謝謝! – Alex 2012-08-15 04:18:26

+0

順便說一句,我讀到了嗎?你乘以行數來得到估計? – Alex 2012-08-15 04:20:14