2017-06-12 65 views
0

我已經在MySQL的表有兩列做複合鍵索引提高性能或條款

id int(11) unsigned NOT NULL AUTO_INCREMENT, 
B varchar(191) CHARACTER SET utf8mb4 DEFAULT NULL, 

的ID是PK。

我需要在查詢中使用其中之一進行查找。 id in (:idList) or B in (:bList)

如果在這兩個列中有一個組合索引,這個查詢會更好嗎?

回答

1

不,它不會。

索引可用於從leftmost columns in an index查找值:

MySQL能使用多列索引來測試索引中的所有列的查詢或查詢該測試只是第一列中,前兩列,前三列,依此類推。如果您在索引定義中以正確順序指定列,則單個組合索引可以加速同一個表上的多種查詢。

所以,如果你有id, B字段(按照這個順序)一個綜合指數,那麼指數可以使用基於其id,或idB值的組合中查找值。但不能用於僅基於B查找值。但是,如果您需要執行or條件:僅根據B查找值。

如果or條件中的兩個字段都是索引中最左邊的字段,那麼MySQL會嘗試執行index merge optimisation,所以實際上最好爲這兩個字段分配不同的索引。

注意:如果您使用innodb表引擎,那麼將主鍵添加到任何多列索引是沒有意義的,因爲innodb會悄悄地將PK添加到每個索引。

0

對於OR我不這麼認爲。

優化器會嘗試在第一面找到匹配項,如果失敗會嘗試第二面。所以每個搜索的個人索引會更好。

對於AND複合索引將有所幫助。

MySQL索引的TIPS

當然,你可以隨時添加索引和比較解釋計劃。

MySQL Explain Plan

+0

實際上,如果表是InnoDB,那麼它對'AND'沒有幫助,因爲InnoDB中的索引已經在最後包含主鍵的隱式副本,並且id是主鍵。 'INDEX(B,id)'功能上等同於'INDEX(B)',除了它可能會佔用更多的空間。在其他任何情況下,你都會對'AND'做出正確的判斷。 –

0

優化OR的訣竅是使用UNION。 (至少,它在某些情況下,效果很好。)

(SELECT ... FROM ... WHERE id IN (...)) 
UNION DISTINCT 
(SELECT ... FROM ... WHERE B IN (...)) 

注:

  • idB需要單獨的索引。
  • 沒有從任何複合指數中獲益(除非它也是「覆蓋」)。
  • DISTINCT更改爲ALL如果您知道idB測試中不會找到任何行。 (這樣可避免重複傳遞。)
  • 如果您需要ORDER BY,請在上面的SQL之後添加它。
  • 如果你需要LIMIT,它會變得更加混亂。 (這可能是爲IN不相關,但它往往是與ORDER BY。)
  • 如果行是「寬」和ResultSet中有很少的行,它可以進一步有益做

事情是這樣的:

SELECT t... 
    FROM t 
    JOIN (
      (SELECT id FROM t WHERE id IN (...)) 
      UNION DISTINCT 
      (SELECT id FROM t WHERE B IN (...)) 
     ) AS u USING(id); 

注:

  • 這需要PRIMARY KEY(id)的d INDEX(B, id)。 (其實沒有差異,正如Michael指出的那樣)。
  • UNION這裏比較便宜,因爲只收集id,而不是龐大的欄目。
  • UNION中的SELECTs速度更快,因爲您應該能夠提供「覆蓋」索引。
  • ORDER BY將在最後。