2014-09-01 37 views
1

這個查詢在MySQL中是最優的嗎?我的意思是:是否有一個不斷執行的查詢量?MySQL是否優化相關表上的選定聚合以避免N + 1?

或者它是否屬於N + 1問題?在有關優化的官方MySQL文檔中沒有發現太詳細的內容。

SELECT t.*, (SELECT COUNT(1) from related_table rt where rt.t_id = t.id) 
FROM table t 

在一個天真的景象,有一個查詢和N查詢,所以它會落在N + 1問題。

MySQL 5.5+是否自動+內部改進此查詢以使查詢數量保持不變?也許它轉化到內部類似:

SELECT t.*, COUNT(rt.id) 
FROM table t LEFT OUTER JOIN related_table rt 
GROUP BY t.id 

我的意思是:我知道如何用手工來改善它,但我問這是因爲:

  1. 也許讓一個apportation一個框架與(不知何故不完整恕我直言)ORM通過庫。
  2. 好奇心。在官方的MySQL文檔中找不到太多的文檔。
+0

我不明白引用的問題是如何重複的,因爲它涉及'in'運算符。 – 2014-09-02 02:36:35

+2

。 。如果你想知道MySQL如何處理查詢,請了解'explain'。您擁有的兩個查詢將具有不同的執行路徑。 – 2014-09-02 02:37:23

+0

謝謝:D我會今天檢查 – 2014-09-02 13:18:12

回答

1

不,選擇列表中的相關子查詢沒有被MySQL優化。

您可以通過使用EXPLAIN來確認此優化計劃的報告。下面是一個使用測試數據庫的類似查詢:

mysql> explain select *, (SELECT COUNT(*) FROM cast_info where cast_info.role_id = role_type.id) AS c 
    from role_type\G 
*************************** 1. row *************************** 
      id: 1 
    select_type: PRIMARY 
     table: role_type 
    partitions: NULL 
     type: index 
possible_keys: NULL 
      key: role 
     key_len: 98 
      ref: NULL 
     rows: 12 
    filtered: 100.00 
     Extra: Using index 
*************************** 2. row *************************** 
      id: 2 
    select_type: DEPENDENT SUBQUERY 
     table: cast_info 
    partitions: NULL 
     type: ref 
possible_keys: cr 
      key: cr 
     key_len: 4 
      ref: imdb.role_type.id 
     rows: 2534411 
    filtered: 100.00 
     Extra: Using index 

選擇類型依賴SUBQUERY意味着子查詢會爲外層查詢的每一行被執行多次,大概一次。

比較與解釋的手動優化查詢:

mysql> explain select r.*, COUNT(c.id) AS c from role_type AS r left outer join cast_info as c on r.id = c.role_id group by r.id\G 
*************************** 1. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: r 
    partitions: NULL 
     type: index 
possible_keys: PRIMARY,role 
      key: PRIMARY 
     key_len: 4 
      ref: NULL 
     rows: 12 
    filtered: 100.00 
     Extra: NULL 
*************************** 2. row *************************** 
      id: 1 
    select_type: SIMPLE 
     table: c 
    partitions: NULL 
     type: ref 
possible_keys: cr 
      key: cr 
     key_len: 4 
      ref: imdb.r.id 
     rows: 2534411 
    filtered: 100.00 
     Extra: Using index 

這表明接入第二表只是一個簡單的通過引用加入。

您也可以使用MySQL query profiler進行測試。這裏的第二個查詢,使用聯接:

+----------------------+----------+ 
| Status    | Duration | 
+----------------------+----------+ 
| starting    | 0.000167 | 
| checking permissions | 0.000015 | 
| checking permissions | 0.000016 | 
| Opening tables  | 0.000050 | 
| init     | 0.000059 | 
| System lock   | 0.000044 | 
| optimizing   | 0.000011 | 
| statistics   | 0.000151 | 
| preparing   | 0.000099 | 
| Sorting result  | 0.000019 | 
| executing   | 0.000010 | 
| Sending data   | 9.700879 | 
| end     | 0.000024 | 
| query end   | 0.000022 | 
| closing tables  | 0.000017 | 
| freeing items  | 0.000243 | 
| cleaning up   | 0.000056 | 
+----------------------+----------+ 

而這裏的一個與相關子查詢:

+----------------------+----------+ 
| Status    | Duration | 
+----------------------+----------+ 
| starting    | 0.000152 | 
| checking permissions | 0.000014 | 
| checking permissions | 0.000013 | 
| Opening tables  | 0.000050 | 
| init     | 0.000067 | 
| System lock   | 0.000042 | 
| optimizing   | 0.000010 | 
| statistics   | 0.000367 | 
| preparing   | 0.000033 | 
| optimizing   | 0.000015 | 
| statistics   | 0.000032 | 
| preparing   | 0.000020 | 
| executing   | 0.000010 | 
| Sending data   | 0.000191 | 
| executing   | 0.000010 | 
| Sending data   | 4.103899 | 
| executing   | 0.000018 | 
| Sending data   | 2.413570 | 
| executing   | 0.000018 | 
| Sending data   | 0.043924 | 
| executing   | 0.000022 | 
| Sending data   | 0.037834 | 
| executing   | 0.000020 | 
| Sending data   | 0.014127 | 
| executing   | 0.000021 | 
| Sending data   | 0.089977 | 
| executing   | 0.000023 | 
| Sending data   | 0.045968 | 
| executing   | 0.000024 | 
| Sending data   | 0.000044 | 
| executing   | 0.000005 | 
| Sending data   | 0.190935 | 
| executing   | 0.000034 | 
| Sending data   | 1.046394 | 
| executing   | 0.000018 | 
| Sending data   | 0.017567 | 
| executing   | 0.000021 | 
| Sending data   | 0.882959 | 
| end     | 0.000046 | 
| query end   | 0.000023 | 
| closing tables  | 0.000018 | 
| freeing items  | 0.000248 | 
| cleaning up   | 0.000025 | 
+----------------------+----------+ 

你可以看到,子查詢導致多次執行。就我而言,我在role_type表中只有幾行,但如果您有數百或數千個,則子查詢執行的次數可能會變得很長,以至於事件探查器會截斷該報告。

+0

U're right。它仍在創建依賴子查詢 – 2014-09-22 20:00:55

相關問題