2011-12-29 188 views
1

我需要一些幫助優化我的數據庫的一些查詢。我明白使用索引來幫助連接和通過語句進行排序來幫助加快速度,但是我想知道是否有一些技術可用來避免使用filesort,並在使用EXPLAIN命令時使用臨時文件。這是我正在使用的一個例子。MySQL ORDER BY多連接優化

SELECT a.id, DATE_FORMAT(a.submitted_at, '%d-%b-%Y') as submitted_at, a.user_id, 
      data1.*, 
      data2.name, data2.type, 
      u.first_name, u.last_name    
      FROM applications AS a 
      LEFT JOIN users AS u ON u.id = a.user_id 
      LEFT JOIN score_table AS data1 ON data1.applications_id = a.id 
      LEFT JOIN sections AS data2 ON data2.id = data1.section_id 
      WHERE category_id = [value] && submitted_at IS NOT NULL 
      ORDER BY data2.type 

同樣,索引正在我的查詢中正確使用,就像上面的查詢一樣。如果我取出ORDER BY子句,則查詢將使用適當的索引快速執行。我知道連接的順序會影響查詢的性能。當我在用戶表上使用ORDER BY進行測試時,因爲它是「const」之後的下一個表,所以它只會在EXPLAIN上使用「Using where,Using Filesort」。如果我放到任何其他表中,我們會進入「使用臨時」問題。

我的問題是:什麼是最佳方式來優化這樣的查詢運行得更快,在最好的情況下,避免在EXPLAIN中使用filesort/temporary?我對任何可能性都開放:)對於如何使這樣的查詢執行更好的理論,我對或多或少感興趣,而不是這個確切的查詢,因爲我必須在這些深層次的ORDER BY查詢中執行越來越多的查詢我正在處理的數據庫。

- 編輯 -

這裏是上面的查詢的解釋.....

id select_type  table type possible_keys    key   key_len  ref     rows Extra 
1 SIMPLE   a  ref  category_id,submitted_at category_id  4   const    49  Using where; Using temporary; Using filesort 
1 SIMPLE   u  eq_ref PRIMARY      PRIMARY  4   a.user_id   1 
1 SIMPLE   data1 ref  app id      app id  4   a.id    7 
1 SIMPLE   data2 eq_ref PRIMARY      PRIMARY  4   data1.section_id 1 
+0

你對'連接條件'中的字段和'where'字段中的字段有'索引'嗎?按'排序'? – piotrekkr 2011-12-29 20:46:31

+0

@piotrekkr是的,我(所有上述),我只是編輯我的帖子,以反映這一點。 – n0nag0n 2011-12-29 20:47:29

+0

由於您在一個左連接的表上的ORDER BY,您將無法繞過臨時表的創建。這是因爲MySQL無法驅動來自同一個表的查詢,它按順序排列。 – 2011-12-29 20:49:43

回答

4

夫婦的事情。

  1. 您確定需要使用'LEFT JOIN'嗎?看看這個查詢,看起來你可以用'INNER JOIN'逃脫,這會減少潛在的行數。

  2. 您沒有發佈您的架構,但我認爲users.id,applications.user_id,score_table.applications_id,applications.id,sections.id和score_table.section_id都是整數?如果他們是非整數,我會強烈要求你轉換它們。如果不是主鍵,請確保它們已被編入索引。

  3. 我不會運行任何mysql級別的數據格式(即DATE_FORMAT),因爲它會在查詢過程中產生一些開銷,而我會在應用層格式化數據。

  4. ORDER BY強制MySQL創建臨時表以便正確排序,因此請確保您絕對需要此功能。如果是這樣,請確保sections.type已編入索引。

  5. 我會考慮使用不同的別名命名約定。 data1和data2是如此抽象,很難辨別它們實際上指的是什麼。例如,我建議你使用你正在別名的表格的縮寫構造;應用程序變成應用程序(而不是a),score_table變成分數(而不是數據1)等。

+0

1.是的,我正在考慮留在LEFT JOINs。它能夠正確地提取數據,並且正是我需要的。 2.是的,他們都是整數。 3.這是保持在我心中的東西。謝謝你的提示。 4.是的,我絕對需要這個功能,因爲數據必須按特定的字段排序,而且這個字段通常只有幾層。 5.我只是以這種方式命名錶格。 謝謝! – n0nag0n 2011-12-29 21:08:48

+0

@ImmortalFirefly:您可能想考慮刪除where子句中的submitted_at,然後運行解釋,我認爲這是導致您的查詢使用filesort的原因。如果是這樣,請嘗試爲category_id和submitted_at添加一個組合索引。 – 2011-12-29 21:15:16

+0

我試圖改變查詢以ORDER BY a.id(主鍵),我仍然得到filesort即使刪除DATE_FORMAT()在submitted_at – n0nag0n 2011-12-29 21:28:10