索引條件下推(index condition pushdown)

索引條件下推(index condition pushdown)

概念

​ 當沒有icp時,存儲引擎會運用索引定位到符合索引條件的行,將這些行發送給MySQL server去計算where 條件是否正確。當有icp時,如果where 條件的一部分可以通過索引來計算(意思就是索引中包含的信息可以計算這一部分where條件),那麼MySQL Server就會將這部分索引條件下推到(index condition push)存儲引擎(下推的意思可以看MySQL邏輯架構圖)去計算,這樣的話就可以返回儘量少的行給MySQL Server,也儘量少的讓MySQL Server訪問存儲引擎層。

Index Condition Pushdown (ICP) is an optimization for the case where MySQL retrieves rows from a table using an index. Without ICP, the storage engine traverses the index to locate rows in the base table and returns them to the MySQL server which evaluates the WHERE condition for the rows. With ICP enabled, and if parts of the WHERE condition can be evaluated by using only columns from the index, the MySQL server pushes this part of the WHERE condition down to the storage engine. The storage engine then evaluates the pushed index condition by using the index entry and only if this is satisfied is the row read from the table. ICP can reduce the number of times the storage engine must access the base table and the number of times the MySQL server must access the storage engine.

——官方原文

​ 使用索引下推的標誌是explain的extra列中顯示了Using index condition。

打開和關閉索引條件下推

SET optimizer_switch = 'index_condition_pushdown=off'; 

SET optimizer_switch = 'index_condition_pushdown=on';

例子

例子1:有一個聯合索引(a,b,c),當查詢where a=x and c=x2,根據最左匹配原則,只有a會用得上,對於c不同版本就有區別了:

  1. 在MySQL5.6之前,就是根據二級索引找出每一條a=x的葉子節點的主鍵,然後拿着主鍵去回表,根據回表拿到對應行c的值,將不符合c=x2的行過濾掉
  2. 在MySQL5.6引入了索引下推優化,找到a=x後,因爲在二級索引中就有c的值了,MySQL Server 就會將c=x2這個索引條件下推給存儲引擎去做,所以在二級索引內就判斷該行是否符合c=x2,不符合直接就跳過了,這樣就少了很多次回表

例子2(官方給的例子):

Suppose that a table contains information about people and their addresses and that the table has an index defined as INDEX (zipcode, lastname, firstname). If we know a person’s zipcode value but are not sure about the last name, we can search like this:

SELECT * FROM people
  WHERE zipcode='95054'
  AND lastname LIKE '%etrunia%'
  AND address LIKE '%Main Street%';

MySQL can use the index to scan through people with zipcode='95054'. The second part (lastname LIKE '%etrunia%') cannot be used to limit the number of rows that must be scanned, so without Index Condition Pushdown, this query must retrieve full table rows for all people who have zipcode='95054'.

With Index Condition Pushdown, MySQL checks the lastname LIKE '%etrunia%' part before reading the full table row. This avoids reading full rows corresponding to index tuples that match the zipcode condition but not the lastname condition.

假設一個包含人們信息和他們的地址的表,並且這個表包含了index(zipcode,lastname,firstname)定義的表。如果我們知道一個人的zipcode但不確定他的lastname,我們就可以像這樣一樣搜索

select * from people
  where zipcode = '95054'
    and lastname like '%entrunia%'
    and address like '%Main Street%';

MySQL可以使用索引掃描zipcode='95054’的人。但是第二部分(lastname like ‘%etrunia%’)不能被使用(不符合最左匹配原則)用來限制必須被掃描的行的數量,所以沒有icp的話,這個查詢必須檢索所有zipcode='95054’的人的整個數據行。

使用icp的話,MySQL會在讀取整個數據行之前判斷’lastname like ‘%etrunia%’’ 部分。這避免了讀取 ‘可以使用zipcode 條件但不可以使用lastname條件’ 的索引項對應的整個數據行。

發佈了44 篇原創文章 · 獲贊 12 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章