2013-07-22 69 views
2

我有2個大型表,產品和product_variants。 目前我正在使用MySQL視圖,因爲我需要多次SQL語句。 數據庫結構不能更改atm。MySQL聯盟中的視圖

產品:
ID | IsMaster | EAN |名稱|價格...

Product_Variants:
ID | PID(在Product.ID上的FK)| IsMaster | EAN |名稱|價格...

視圖my_view包含一個選擇是這樣的:

(SELECT * FROM `product`) UNION (SELECT * FROM `product_variants`) 

當我現在做這樣的查詢:

SELECT * FROM my_view WHERE EAN = '11110' 

大約需要0,5達1秒。 如果我加入where每個子查詢中直接使用視圖的內容,它是超級快(〜0.004秒):

(SELECT * FROM `product` WHERE EAN = '11110') UNION (SELECT * FROM `product_variants` WHERE EAN = '11110') 

我怎樣才能用在視圖中更快的方法?我需要更改爲MySQL函數嗎?

TIA 馬特

+0

您可以將數據作爲更多列(聯合)而不是更多行(聯合)嗎? – Bohemian

回答

1

你應該使用一些mysql命令來分析您的查詢作爲使用EXPLAIN用select語句 和檢查表和索引結構。

使用命令

集剖析= 1;

然後用你的選擇查詢 使用命令

爲QUERY1顯示配置文件;

檢查結果哪個東西在說多少時間。

和其他一些小鬼查詢是

* SHOW CREATE TABLE TBL \ G變 - 引擎,索引

  • SHOW TABLE STATUS LIKE '甲組' \ G變 - 大小

  • EXPLAIN SELECT ... \ G - 效率低下的線索

  • SHOW VARIABLES LIKE'%buffer%'; - ca **

+0

使用性能分析返回「發送數據」時使用0.3秒。這是什麼意思? – frgtv10

+0

根據我的知識,發送數據條款在mysql中用於掃描表以獲取結果。所以你可以看到,當你做第一次聯合,然後使用的地方接近獲取結果,然後mysql完全掃描您的看法,然後根據您的查詢 獲取結果,第二種情況下,當你在「union」之前使用「where」時,然後由於預過濾where子句,mysql將掃描較少的結果 。欲瞭解更多信息,你可以檢查選擇語句流程 – developerCK

+0

你建議在這種情況下停止使用視圖,對吧? – frgtv10

2

基本問題是視圖內的聯合被執行(沒有where子句的好處)之前 where子句被應用來過濾這些行。

效果是從兩個表中選擇每一行到一個巨大的臨時表中,然後在該臨時表上應用where子句,當然沒有索引的好處(即使存在於基表上)。

你可以嘗試使用UNION ALL(而不僅僅是UNION),因爲UNION ALL保持所有行,而UNION丟棄重複,這掩蓋從結果的基礎表由於去欺騙的過程。


真正問題是數據庫設計 - 這兩個表是如此的相似這是很明顯,應該只有一個isVariant列區分行類型。如果你不能改變的表,你可以創建一個新表:

NewProduct 
ID | PID (fk to self for variants, null otherwise) | IsMaster | IsVariant | EAN | Name | Price .. 

並把您搜尋(在這種情況下,EAN)對任何列的索引。

您可以輕鬆地填充它。爲了與舊錶保持同步,您可以在產品信息更改時手動截斷並重新運行填充腳本,也可以使用舊錶上的觸發器自動保持同步。這取決於你的網站的細節是什麼。

+0

謝謝你的解釋。這有助於我將查詢從1秒降低到0.7秒。 你的意思是我應該嘗試使用連接而不是聯合來構建查詢? – frgtv10

+0

您的應用程序可以處理將數據並排作爲連接嗎? – Bohemian

+0

你的意思是我應該嘗試使用連接而不是工會?你是什​​麼意思並肩? – frgtv10

0

爲兩個表中的EAN列編制索引並嘗試。

也試試這個

explain (SELECT * FROM `product` WHERE EAN = '11110') UNION (SELECT * FROM `product_variants` WHERE EAN = '11110') 
+0

問題是你寫的查詢已經準備好了,大概需要0,0002秒。但是,使用where情況下的視圖花費了1秒鐘的時間。 – frgtv10

+0

創建視圖時不要放置where條件。視圖就像臨時表一樣。它可以包含與您的Select查詢相關的所有數據。因此,您可以在查看數據的同時使用where條件。試試看。 –