Mysql在字段爲允許null時,存在null值,會不會影響索引使用

本文主要考察兩個問題:

  1. 當某一列有爲null值的數據時,該列的索引是否還能生效
  2. is null或者is not null是否能使用到索引

首先貼上幾段官方文檔:

You can add an index on a column that can have NULL values if you are using the MyISAMInnoDB, or MEMORY storage engine. Otherwise, you must declare an indexed column NOT NULL, and you cannot insert NULL into the column.

大意是:如果你選擇了MyISAMInnoDB, or MEMORY 這幾個引擎,那麼你可以爲允許null值的字段加上索引,如果不是這幾個引擎,那麼只能爲那些not null的字段加上索引,這些字段也無法保存null值。

MySQL can perform the same optimization on col_name IS NULL that it can use for col_name = constant_value. For example, MySQL can use indexes and ranges to search for NULL with IS NULL.

大意是:mysql可以使用索引來查詢NULL字段。

 

下面開始測試

建表:a、b、c字段均接受null值

添加索引:

ALTER TABLE `j_copy` ADD INDEX (a);

爲問題1編寫查詢語句:

EXPLAIN select * from j_copy where a = 'a1';

解釋執行過程:

問題1結論:當某一列有爲null值的數據時,該列的索引依然生效

 

爲問題2編寫查詢語句:

1.EXPLAIN select * from j_copy where a is null;

2.EXPLAIN select * from j_copy where a is not null;

解釋執行過程:

1.

2.

情況1:

情況2:

問題2結論:

1.使用is null確實是走了索引,沒有問題。

2.現象比較特殊,在這裏is not null條件並沒有走索引,但是修改成select a from j_copy的話,就可以走索引了。一開始不太理解這個現象,網上翻了很多文章,找到了一個比較靠譜的說法:

select a from j_copy直接讀取索引上的數據後即可返回。而select * from j_copy如果走索引的話,則需要通過索引獲取數據位置再去讀取整行內容,在數據比較少的情況下,可能會更慢,所以mysql的優化器選擇了直接全表掃描。

爲了驗證上面內容,我又測試了一下,爲a、b、c三個字段添加聯合索引,那麼三個字段的數據都會保存在索引裏面,再執行語句:

 

 

以上實驗都是在字段接受null值的條件下做的實驗。在字段not null的情況下,is null和is not null都不會走索引。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章