2012-05-10 48 views
1

我想連接兩個MySQL表並將其存儲爲視圖,因此我可以在應用程序中解決此視圖而不是查詢兩個表。但這種看法發生得非常緩慢。MySQL視圖的優化

這是我的表:

CREATE TABLE spectrumsets (
    setid INT(11) NOT NULL, 
    timestampdt INT(11) NULL DEFAULT NULL, 
    timestampd INT(10) UNSIGNED NOT NULL, 
    timestampt INT(10) UNSIGNED NOT NULL, 
    device INT(11) NOT NULL, 
    methodname VARCHAR(50) NOT NULL, 
    PRIMARY KEY (setid), 
    UNIQUE INDEX setid_idx (setid), 
    UNIQUE INDEX timestamp_device_idx (timestampd, timestampt, device), 
    INDEX device_fk (device), 
    INDEX timestampd_idx (timestampd), 
    CONSTRAINT device_fk FOREIGN KEY (device) 
     REFERENCES spectrumdevices (deviceid) 
) 
COLLATE='utf8_general_ci' 
ENGINE=InnoDB 

CREATE TABLE spectrumdata (
    valueid INT(11) NOT NULL AUTO_INCREMENT, 
    spectrumset INT(11) NOT NULL, 
    wavelength DOUBLE NULL DEFAULT NULL, 
    intensity DOUBLE NULL DEFAULT NULL, 
    PRIMARY KEY (valueid), 
    INDEX spectrumset_idx (spectrumset), 
    CONSTRAINT spectrumset_fk FOREIGN KEY (spectrumset) 
     REFERENCES spectrumsets (setid) 
) 
COLLATE='utf8_general_ci' 
ENGINE=InnoDB 

這是我的看法:

SELECT spectrumsets.timestampd,spectrumsets.timestampt,spectrumsets.device, 
    spectrumdata.wavelength,spectrumdata.intensity 
FROM spectrumdata INNER JOIN spectrumsets ON spectrumdata.spectrumset= 
    spectrumsets.setid 
WHERE spectrumdata.wavelength>0 
ORDER BY spectrumsets.timestampd,spectrumsets.timestampt,spectrumsets.device, 
    spectrumdata.wavelength 

我的機器上的select count(*)需要385.516秒和成果轉化爲82923705分的記錄,所以一個相當大的數據集

我已經找到了這個link,但仍然不完全明白是什麼錯誤。

UPDATE:

EXPLAIN給出了這樣的結果:

"id","select_type","table","type","possible_keys","key","key_len","ref","rows","Extra" 
"1","SIMPLE","spectrumsets","index","PRIMARY,setid_idx","timestamp_device_idx","12",NULL,"327177","Using index; Using temporary; Using filesort" 
"1","SIMPLE","spectrumdata","ref","spectrumset_idx","spectrumset_idx","4","primprod.spectrumsets.setid","130","Using where" 
+2

你使用EXPLAIN? –

+0

是否運行'分析表譜數據頻譜集?有什麼區別? – Bohemian

+1

什麼是你的buffer_pool_size?看起來數據集不適合內存,所以InnoDB可能在進行全表掃描時強姦磁盤。 –

回答

2

解釋表明,查詢被擊中的加入指數(好的),但是如果使用了臨時表和文件排序查詢的其餘部分。

這是出於兩個原因:

  • 的where子句不打指數
  • order by子句沒有擊中指數

在評論,你說刪除where子句導致了很大的改進;這表明您需要光譜集,波長上的複合索引,假設波長具有相當數量的可能值(如果只有10個值,則索引可能不會做任何事情)。

如果您將「order by」子句排除在視圖之外,應該快得多 - 並且有一個很好的例子,可以讓查詢提取數據而不是視圖來確定排序順序。我猜測大多數查詢都會對數據非常有選擇性 - 限制幾個時間戳;通過在視圖中嵌入訂單,您每次都要付出排序的代價。

如果您確實必須在視圖中具有「排序依據」,請創建一個索引,該索引包含「排序依據」順序中的所有字段,並在前面加入連接。例如:

UNIQUE INDEX timestamp_device_idx(SET_ID,timestampd,timestampt,設備),

+0

+1。這是正確的答案,但MySQL 5。0+可以使用[索引合併](http://dev.mysql.com/doc/refman/5.0/en/index-merge-optimization.html)使用多個索引。我會刪除相反的聲明或澄清。此外,對於該複合索引,請在索引中放置使用範圍的列(本例中爲波長列,請參閱WHERE波長> 0),因爲對索引使用範圍會使剩餘部分無效。除此之外,首先放置最高基數的列。 –

+0

做了一些測試:刪除ORDER BY子句將大約385秒的性能時間減少到大約285秒,但也將WHERE子句刪除到大約48秒!所以我認爲我真的需要將ORDER BY子句移到調用應用程序,而且還要移動WHERE子句。對我而言,這不是一個真正的問題,但我仍然不完全明白髮生了什麼:-(對innodb_buffer_pool_size會有一些幫助,但對視圖的SQL語句的構造也是如此 – waanders

+0

這真是一個很好的跡象表明它是在哪裏從而導致問題;我將相應地編輯答案。 –