2012-06-20 123 views
0

我有300 000條記錄(MyISAM)的表。我得到的記錄從該表中使用此功能:優化mysql查詢(SELECT)?

public function loadRows() { 
    if (!$this->result) 
     die("Nothing found!"); 
    $this->rows = array(); 
    while ($r = mysql_fetch_array($this->result, MYSQL_ASSOC)) 
     $this->rows[] = $r; 
    //mysql_free_result($this->result); 
    return $this->rows; 
} 

估計時間顯示從該表100次的記錄是6秒,非常緩慢,從該查詢所使用的內存爲512 MB。我錯在哪裏?

查詢是:

SELECT i.* FROM inv i 
LEFT JOIN (inv_m im) ON (i.m_id = im.id) 
LEFT JOIN (inv_f iff) ON (iff.num = i.num) 
LEFT JOIN (temp_a ta) ON (ta.num = i.num) 
WHERE i.vid = 1 
AND iff.num IS NULL 
AND ta.num IS NULL 
LIMIT 100 

對於i.vid我顯示所有記錄。

申報指標:

i.m_id INDEX

im.id PRIMARY KEY

iff.num INDEX

i.num INDEX

ta.num指數

EXPLAIN的結果

id select_type table type  possible_keys key  key_len ref     rows Extra 
1 SIMPLE  i  ref  vid   vid  4  const    85343 Using where 
1 SIMPLE  im  eq_ref PRIMARY  PRIMARY 4  checksys_r1.i.m_id 1 
1 SIMPLE  iff ref  num   num  182  checksys_r1.i.num 1  Using where 
1 SIMPLE  ta  ref  num   num  194  checksys_r1.i.num 1  Using where 
+1

你是否聲明瞭任何索引? – DonCallisto

+0

你加入四張桌子,但只談論一張。發佈有關您的架構的更多細節。 – lanzz

+0

「num」字段是否被索引? – raina77ow

回答

1

開始運行:

EXPLAIN SELECT i.* FROM inv i 
LEFT JOIN (inv_m im) ON (i.m_id = im.id) 
LEFT JOIN (inv_f iff) ON (iff.num = i.num) 
LEFT JOIN (temp_a ta) ON (ta.num = i.num) 
WHERE i.vid = 1 
AND iff.num IS NULL 
AND ta.num IS NULL 
LIMIT 100 

看的東西像一個完整的行掃描,文件I/O等郵政這裏的結果。有時候桌子也可能需要修理。

另外,是否有任何理由你在InnoDB上使用MyISAM?

+0

我發佈EXPLAIN結果 – dido

+0

表inv,ivm_m是myIsam,但是表temp_a是innoDB – dido

+0

如果你拿出i。vid = 1(現在),查詢運行得更快嗎? – StackOverflowed

-1

有2個可能的原因,既可能是造成。 首先,儘量避免選擇*儘可能。明確指定列將節省您對主數據庫的每個連接查詢以反覆查找列名稱。 第二個是你指定一個where子句,它只會在你的連接之後運行。因此,它將創建一個包含所有連接的海量記錄集,然後過濾該記錄集。將條件移至連接本身應該會讓您的性能提高一些。 所以.....

SELECT i.Column1, i.Column2, i.Column3 
FROM inv i 
LEFT JOIN (inv_m im) ON (i.m_id = im.id AND i.vid = 1) 
LEFT JOIN (inv_f iff) ON (iff.num = i.num AND iff.num IS NULL) 
LEFT JOIN (temp_a ta) ON (ta.num = i.num AND ta.num IS NULL) 
LIMIT 100