盡量全值匹配
建表語句:
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在一定的情況下會失效。父元素...