這樣寫sql避免索引失效

2021-10-01 03:47:30 字數 3321 閱讀 1297

合理地對資料表加索引可以大大加快資料的訪問效率,但索引也不是對任何查詢都有效,如果sql的結構不當,也會發生索引失效。所以為避免採坑,寫下此文,作為記錄。下面的例子是在mysql中建立的一張表,建表語句如下:

create table `user_info` (

`id` bigint(32) not null,

`name` varchar(32) default null,

`age` int(3) default null,

`address` varchar(32) default null,

`nick_name` varchar(32) default null,

`role_id` bigint(32) default null,

`create_time` date default null,

`update_time` date default null,

primary key (`id`)

) engine=innodb default charset=utf8;

在對錶建立索引時,如果可以使用復合索引,盡量使用復合索引而不是單列索引,理由如下。現建立的乙個復合索引:

create index idx_name_age_status on user(name, age, status);
這裡建立了乙個名為idx_name_age_status的復合索引,索引涉及到三個字段。在mysql中,這乙個索引實際上相當於三個索引,分別是name、 name + age、 name + age + stauts,那麼在使用name或name + age或name + age + stauts進行查詢時,都會使索引生效。而如果分別給三個字段三個單列索引,在查詢這張表時條件中有這三個字段,資料庫會選擇乙個最優的單列索引,而不會使用全部三個索引。

使用到復合索引時,注意最左字首法,也就是查詢的條件需要從索引的最左列開始,並且不跳過中間列,才能使索引發揮最好的效果。現在建立這樣的索引:

create index idx_name_age_status on user(name, age, status);
使用name或name + age或name + age + status進行查詢能使索引生效;使用單個查詢條件age或status或者age + status 進行查詢不會使索引生效;使用name + stauts進行查詢只有name欄位的索引生效。

三個欄位在同乙個復合索引中,如果查詢條件中用到了範圍查詢,範圍查詢後面的索引不再生效比如建立如下索引:

create index idx_name_age_status on user(name, age, status);
使用這三個字段作為查詢條件,處於中間的age如果用到了範圍查詢,則status上的索引不會生效。

-- name + age + nick_name索引生效

select * from user_info where name = '張三' and age = 22 and nick_name = '三兒';

-- age用到了範圍查詢,僅name + age索引生效

select * from user_info where name = '張三' and age > 22 and nick_name = '三兒';

在索引列上進行運算操作後,索引將失效。比如有這樣乙個索引:

create index idx_name on user_info(name);
直接以name作為條件查詢索引是生效的,如果在name上使用函式會導致索引失效,比如這樣:

select * from user_info where substring(name, 1, 2) = '夏侯';
查詢條件中的模糊條件,如果是以%開頭,不走索引,比如

select * from user_info where name like '%三兒%';    -- 不走索引
或者

select * from user_info where name like '%三兒';    -- 不走索引
以上兩種寫法都不會走索引,下面這種寫法索引是有效的

select * from user_info where name like '三兒%';    -- 走索引
查詢時字串如果沒加引號,索引失效。

在mysql中,假設有乙個欄位名是name,型別為varchar,使用name作為條件查詢。此時忘記給name的值加上引號,就像這樣:

select * from user_info where name = 12;    -- name為varchar型別
此時name條件查詢的值是12,mysql是可以執行的,如果這裡寫乙個name = 張三,mysql不能執行。雖然這條語句可以執行,並且如果資料表中有name值為12的資料也是可以查出來的。但是,它不會走索引。  

name欄位上有索引,所以這樣查肯定是走索引的。

select * from user_info where name = '張三';
在這張表中另外有一列nick_name,不管這一字段有沒有加索引,下面這乙個語句都不會走索引

select * from user_info where name = '張三' or nick_name = '頑皮';
盡量使用覆蓋索引,也就是盡量只查詢索引列,比如復合索引如下:

create index idx_name_age_status on user(name, age, status);
使用select * from user_info where name = '張三' and age = 12 and status = 1進行查詢,索引自然會生效,但是效率肯定不如select name, age, status from user_info where name = '張三' and age = 12 and status = 1,這在資料量大的時候可以看出來。

另外,盡量不要寫select * from user_info這樣的語句,select後面只跟需要用到的列是好的選擇。

避免索引失效

1.全值匹配,對索引中所有列都指定具體值。2.最左字首法則,如果索引有多列,要遵循最左字首法則。指的是查詢從索引的最左前列開始,並且不跳過索引中的列。否者不走索引。3.範圍查詢右邊的列,不走索引,應為mysql底層範圍查詢之後結構就斷了,就無法使用後面得索引了。4.不要在索引列上進行運算操作,索引將...

怎麼避免索引失效

首先在接著 之前,我們先說一下,如何判斷資料庫的索引是否生效!相信大家應該猜到了,就是explain!explain顯示了mysql如何使用索引來處理select語句以及連線表。他可以幫助選擇更好的索引和寫出更優化的查詢語句。例如我們有一張表user,為name列建立索引name index,如下所...

如何避免索引失效

全值匹配 最佳左字首法則 如果索引了多列,要遵守最左字首法則。指得時查詢從索引的最左前列開始並且不跳過索引中的列 不在索引列上左任何操作 計算 函式 自動or手動 型別轉換 因為在索引列上做操作會導致索引失效而轉向全表掃瞄 儲存引擎不能使用索引中範圍條件右邊的列 盡量使用覆蓋索引 只訪問索引的查詢 ...