2011-10-13 131 views
1

我正在使用一些利用連接的MySQL語句。這些查詢的性能似乎相當差,並且可能會在查詢運行期間取消查詢。下面列出的是我正在使用的查詢的幾個樣本。我是MySQL JOIN語句的新手,對任何人都可以幫助我優化這些以獲得更好的性能感到好奇。MySQL加入優化問題

我們使用這兩種查詢我們的售票系統數據庫,生成有關處理各類門票的一些報道,他們從被處理的地點等

SELECT * FROM tickets t 
LEFT Join customfieldvalues cv1 ON t.ticketid = cv1.typeid 
LEFT Join customfields cf1 ON cv1.customfieldid = cf1.customfieldid 
LEFT Join customfieldoptions co1 on cv1.fieldvalue = co1.customfieldoptionid 
WHERE t.dateline BETWEEN 1314853200 AND 1317445199 
Group by t.ticketid 
Order by t.Dateline asc; 

這是一個基本的查詢(無過濾添加)從9月1日至9月30日。運行時間〜140秒如果您拿走三條連接線,運行時間會縮短至約0.01秒。

SELECT * FROM tickets t 
LEFT Join customfieldvalues cv1 ON t.ticketid = cv1.typeid 
LEFT Join customfields cf1 ON cv1.customfieldid = cf1.customfieldid 
LEFT Join customfieldoptions co1 on cv1.fieldvalue = co1.customfieldoptionid 
LEFT Join customfieldvalues cv2 ON cv1.typeid = cv2.typeid 
LEFT Join customfields cf2 ON cv2.customfieldid = cf2.customfieldid 
LEFT Join customfieldoptions co2 on cv2.fieldvalue = co2.customfieldoptionid 
WHERE t.dateline BETWEEN 1314853200 AND 1317445199 
AND cf1.title ='Customer Type' AND co1.optionvalue = 'Staff' 
And cf2.title ='Building or Hall' AND co2.optionvalue like '%Stroupe%' 
Group by t.ticketid 
Order by t.Dateline asc; 

該查詢將與2個過濾器基本查詢補充說:客戶類型(即員工)和地點建築物或霍爾(Stroupe)。使用與上述相同的時間幀,運行時間約爲0.1秒。

==============================

編輯:這裏是EXPLAIN命令的輸出上列出第一個查詢。

INSERT INTO `table_name` (`id`,`select_type`,`table`,`type`,`possible_keys`,`key`,`key_len`,`ref`,`rows`,`Extra`) VALUES (1,'SIMPLE','t','range','tickets7','tickets7','4',NULL,601,'Using where; Using temporary; Using filesort'); 
INSERT INTO `table_name` (`id`,`select_type`,`table`,`type`,`possible_keys`,`key`,`key_len`,`ref`,`rows`,`Extra`) VALUES (1,'SIMPLE','cv1','ALL',NULL,NULL,NULL,NULL,104679,''); 
INSERT INTO `table_name` (`id`,`select_type`,`table`,`type`,`possible_keys`,`key`,`key_len`,`ref`,`rows`,`Extra`) VALUES (1,'SIMPLE','cf1','eq_ref','PRIMARY','PRIMARY','4','DB.cv1.customfieldid',1,''); 
INSERT INTO `table_name` (`id`,`select_type`,`table`,`type`,`possible_keys`,`key`,`key_len`,`ref`,`rows`,`Extra`) VALUES (1,'SIMPLE','co1','eq_ref','PRIMARY','PRIMARY','4','DB.cv1.fieldvalue',1,''); 

這是第二個查詢的EXPLAIN輸出。

1,SIMPLE,cf1,ref,「PRIMARY,title1」,title1,767,const,1使用where;其他;使用臨時;使用filesort「1,SIMPLE,co1,ref,」PRIMARY,optionvalue1「,optionvalue1,767,const,1,」使用where「1,SIMPLE,cf2,ref,」PRIMARY,title1「,title1, 767,const,1,「使用where」 1,SIMPLE,tv,range,「PRIMARY,tickets7,tickets15,tickets16」,tickets7,4,NULL,601,「Using where」,SIMPLE,cv1,ref, customfieldvalues1,customfieldvalues1,8,「DB.cf1.customfieldid,DB.t.ticketid」,1,「Using where」,SIMPLE,cv2,ref,customfieldvalues1,customfieldvalues1,8,「DB.cf2.customfieldid,DB。 t.ticketid「,1,」Using where「,SIMPLE,co2,eq_ref,PRIMARY,PRI MARY,4,DB.cv2.fieldvalue,1,「使用哪裏」

+0

您是否製作上參與JOIN操作的列索引? –

+0

@喬 - 我只是看着,是的,似乎每一個都有索引。 – John

+1

有兩件事情可以幫助我們獲得更好的答案:表格定義(所以我們可以檢查我們預期的列上是否有索引)以及EXPLAIN –

回答

1

它的連接是錯誤的你的左連接+ where子句=內連接,你需要重寫查詢。

您的意思是讓我把cf1中的所有行都放進去,即使它們不存在,也只有那些標題爲'Customer Type'的行。

如果你改變了左側連接到內部連接這將是更好的性能,(雖然可能不會返回你想要的)

+0

@凱文 - 感謝您的想法。我對此仍然陌生。我如何創建查詢計劃?另外,內部連接會更好嗎?我已經爲標題和選項值添加了兩個索引(我認爲我做對了)。 – John

+0

切換到內部聯接對於數據庫和where子句結合起來更有意義,在這兩個部分衝突的時刻。 –

+0

是否有一個公式來理解連接類型。例如,你提到一個內部連接基本上是 - INNER JOIN = LEFT JOIN + WHERE CLAUSE?其他類型還有其他這樣的公式嗎? – John