or導致索引失效的解決方法 SQL優化之索引失效

2021-10-19 19:56:19 字數 3817 閱讀 8315

盡量全值匹配

建表語句:

create table `t_logs` (

`id` int(10) not null auto_increment,

`action` varchar(100) default null,

`data` varchar(2000) default null,

`author_id` int(10) default null,

`ip` varchar(20) default null,

`created` int(10) default null,

primary key (`id`),

key `actionipcreated` (`action`,`created`,`ip`) using btree

) engine=innodb auto_increment=938 default charset=utf8;

其中有三個欄位是聯合索引,在查詢的時候盡量把where條件跟索引全量匹配,例如:

explain select * from t_logs where action = '訪客訪問' and created = '1528366547' and ip = '58.135.82.57';

執行計畫:

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | extra |

| 1 | ****** | t_logs | null | ref | actionipcreated | actionipcreated | 371 | const,const,const | 1 | 100.00 | null |

如果條件不允許使用索引列的全域性匹配,那麼最好使用覆蓋索引,比如:

explain select action,created,ip from t_logs where action = '訪客訪問';

執行計畫:

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | extra |

| 1 | ****** | t_logs | null | ref | actionipcreated | actionipcreated | 303 | const | 195 | 100.00 | using index |

最佳左字首法則

如果索引了多列,要遵守最左字首法則。指的是查詢從索引的最左前列開始並且不跳過索引中的列。

建表語句:

create table `t_logs` (

`id` int(10) not null auto_increment,

`action` varchar(100) default null,

`data` varchar(2000) default null,

`author_id` int(10) default null,

`ip` varchar(20) default null,

`created` int(10) default null,

primary key (`id`),

key `actionipcreated` (`action`,`created`,`ip`) using btree

) engine=innodb auto_increment=938 default charset=utf8;

可見,乙個復合索引,順序是action,created,ip,當在使用這三個索引作為條件查詢的時候可以打亂順序,但不能跳過。

舉例:正確的利用了索引的查詢語句:

explain select * from t_logs where action = '訪客訪問' and created = '1528366547' and ip = '58.135.82.57';

未全部利用索引進行的查詢:

explain select * from t_logs where action = '訪客訪問' and ip = '58.135.82.57';

上面的sql語句僅有action列上的索引起作用了,ip列上的索引是沒有作用的,因為中間的created列沒有作為查詢條件。

如果既想改變順序,又能利用索引,那還是使用覆蓋索引的方法。最佳左字首法則就是:帶頭大哥不能死、中間兄弟不能斷。

補充:例如有乙個聯合索引 idx_nameagegender 假如在查詢的時候三個字段打亂順序,是可以用到索引的,因為mysql有自己的優化器。

不在索引列上做任何操作

不在索引列上做任何操作(計算、函式、(自動or手動)型別轉換),會導致索引失效而轉向全表掃瞄。

舉例,其中data列是索引列:

explain select * from t_logs where left(data,4) = 'bcwn';

執行計畫:

| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | extra |

| 1 | ****** | t_logs | null | all | null | null | null | null | 197 | 100.00 | using where |

範圍條件放最後

儲存引擎不能使用索引中範圍條件右邊的列。會導致最後的索引失效。

例子:explain select * from t_logs where action = '訪客訪問' and created < '1528366547' and ip = '58.135.82.57';

導致了ip這列的索引失效了。

覆蓋索引盡量用

盡量使用覆蓋索引(只訪問索引的查詢(索引列和查詢列一致)),減少select *的出現。

不等於要甚用

mysql 在使用不等於(!= 或者<>)的時候無法使用索引會導致全表掃瞄。解決辦法就是使用覆蓋索引。例子就不舉了,很簡單。

null/not null有影響

建表語句:

create table `t_logs` (

`id` int(10) not null auto_increment,

`action` varchar(100) default null,

`data` varchar(100) default null,

`author_id` int(10) default null,

`ip` varchar(20) default null,

`created` int(10) default null,

primary key (`id`),

key `actionipcreated` (`action`,`created`,`ip`) using btree,

key `data` (`data`) using btree

) engine=innodb auto_increment=938 default charset=utf8;

這個情況有點多,具體取決於該欄位是否預設為null,可以去試試,遇到這種sql需要根據實際情況去優化,索引並不一定會失效。如果說碰到is null或is not null一定會導致索引失效肯定是錯了。

like查詢

like以萬用字元開頭('%abc...')mysql索引失效會變成全表掃瞄的操作,但不以'%'開頭不會導致索引失效。

字元型別加引號

假如乙個列是char或者varchar型別,那麼當它作為條件的時候必須加上單引號,否則會導致這一列的索引失效。就不舉例子了,也很簡單。

or導致索引失效的解決方法 索引失效的7種情況

簡述 什麼時候沒用 1.有or必全有索引 2.復合索引未用左列字段 3.like以 開頭 4.需要型別轉換 5.where中索引列有運算 6.where中索引列使用了函式 7.如果mysql覺得全表掃瞄更快時 資料少 什麼時沒必要用 1.唯一性差 2.頻繁更新的字段不用 更新索引消耗 3.where...

Oracle索引失效原因及解決方法

1使用否定關鍵字 not in,not exist select fromdrama where id 1,mysql不會 2單獨使用不等式關鍵字 直接用 或 可能會失效,mysql不會 3使用null關鍵字 is null或is not null 可能會失效 4左模糊或全模糊 like 放在前面 ...

z index失效解決方法

1 一般z index的使用是在有兩個重疊的標籤,在一定的情況下控制其中乙個在另乙個的上方出現。2 z index值越大就越是在上層。z index 9999 z index元素的position屬性要是relative,absolute或是fixed。3 z index在一定的情況下會失效。父元素...