MySQL index analysis and optimization (important)

Build SQL table

CREATE TABLE staffs (
  id INT PRIMARY KEY AUTO_INCREMENT,
  NAME VARCHAR (24)  NULL DEFAULT '' COMMENT '姓名',
  age INT NOT NULL DEFAULT 0 COMMENT '年龄',
  pos VARCHAR (20) NOT NULL DEFAULT '' COMMENT '职位',
  add_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '入职时间'
) CHARSET utf8 COMMENT '员工记录表' ;
 
 
INSERT INTO staffs(NAME,age,pos,add_time) VALUES('z3',22,'manager',NOW());
INSERT INTO staffs(NAME,age,pos,add_time) VALUES('July',23,'dev',NOW());
INSERT INTO staffs(NAME,age,pos,add_time) VALUES('2000',23,'dev',NOW());
INSERT INTO staffs(NAME,age,pos,add_time) VALUES(null,23,'dev',NOW());
SELECT * FROM staffs;
 
ALTER TABLE staffs ADD INDEX idx_staffs_nameAgePos(name, age, pos);

Case (index failed)

1, the full value of my favorite matches

Index idx_staffs_nameAgePos indexing in the order of name, age, pos established. Full match the value represented by the sequence match 
EXPLAIN the SELECT * the FROM Staffs the WHERE NAME = 'July'; 
EXPLAIN the SELECT * the FROM Staffs the WHERE NAME = 'July' the AND Age = 25; 
EXPLAIN the SELECT * the FROM Staffs the WHERE NAME = 'July' the AND Age = 25 AND pos = 'dev';

Note: If the query process, if not the first query NAME field, the index is invalid

There NAME, no age, part of the index fail

The first index field is equivalent to a locomotive, carriage is equivalent to the back of the index field, if only the front, the train still running, if there is no front, the train will not run. You can use this analogy.

2, the best left-prefix rule

If the index multiple columns, the most left-prefix to comply with the law. It refers to a query from the leftmost in the forefront of the index beginning and not skip column in the index .

 

and ignore about relationships. Even if there is no order either due to the presence optimizer automatically optimized. 
After testing idx_nameAge Conclusion A primary key index id 
    1. When using the cover index, (select name / age / id from staffs where age = 10 ( no other fields behind the absence of index)), if not begin to name also used idx_nameAge index. 
    Select both the indexed field, where the field is also an index, regardless of the execution order. 
    2. Aside from the above conditions only meet the most left-prefix rule. 
 
The FROM Staffs the WHERE the SELECT * EXPLAIN Age = 25 = the AND POS 'dev'; 
 
EXPLAIN the SELECT * = the FROM Staffs the WHERE POS 'dev';

Formulas: take the lead in Big Brother can not die, the middle brother can not be broken. Like the right percentage increase

3, do not do anything (calculation function (automatic or manual) type conversion) of the index columns, the index will lead to failure of the steering full table scan

EXPLAIN SELECT * FROM staffs WHERE left(NAME,4) = 'July';

4, the storage engine can not use the column index in the range of conditions of the right

If the index range is able to use the index, index range conditions on the right will expire (with a combination of the right conditions index range and scope of the conditions of use, the right will fail. If different indices will not fail)

5, try to use a covering index (an index only access query (indexed columns and query columns consistent)) to reduce the select *

6, mysql using the not equal (! = Or <>) can not be used when the index will lead to a full table scan

索引  idx_nameAgeJob
         idx_name
使用 != 和 <> 的字段索引失效( != 针对数值类型。 <> 针对字符类型
前提 where and 后的字段在混合索引中的位置比比当前字段靠后  where age != 10 and name='xxx'  ,这种情况下,mysql自动优化,将 name='xxx' 放在 age !=10 之前,name 依然能使用索引。只是 age 的索引失效)

7、is not null 也无法使用索引,但是is null是可以使用索引的

8、like以通配符开头('%abc...')mysql索引失效会变成全表扫描的操作

like ‘%abc%’ type 类型会变成 all
like ‘abc%’ type 类型为 range ,算是范围,可以使用索引

问题:解决like '%字符串%'时索引不被使用的方法??

建表,插入数据

CREATE TABLE `tbl_user` (
 `id` INT(11) NOT NULL AUTO_INCREMENT,
 `NAME` VARCHAR(20) DEFAULT NULL,
 `age` INT(11) DEFAULT NULL,
 email VARCHAR(20) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
 
#drop table tbl_user
 
INSERT INTO tbl_user(NAME,age,email) VALUES('1aa1',21,'[email protected]');
INSERT INTO tbl_user(NAME,age,email) VALUES('2aa2',222,'[email protected]');
INSERT INTO tbl_user(NAME,age,email) VALUES('3aa3',265,'[email protected]');
INSERT INTO tbl_user(NAME,age,email) VALUES('4aa4',21,'[email protected]');
INSERT INTO tbl_user(NAME,age,email) VALUES('aa',121,'[email protected]');

建索引之前进行测试

#before index
 
EXPLAIN SELECT NAME,age    FROM tbl_user WHERE NAME LIKE '%aa%';
 
EXPLAIN SELECT id    FROM tbl_user WHERE NAME LIKE '%aa%';
EXPLAIN SELECT NAME     FROM tbl_user WHERE NAME LIKE '%aa%';
EXPLAIN SELECT age   FROM tbl_user WHERE NAME LIKE '%aa%';
 
EXPLAIN SELECT id,NAME    FROM tbl_user WHERE NAME LIKE '%aa%';
EXPLAIN SELECT id,NAME,age FROM tbl_user WHERE NAME LIKE '%aa%';
EXPLAIN SELECT NAME,age FROM tbl_user WHERE NAME LIKE '%aa%';
 
EXPLAIN SELECT *     FROM tbl_user WHERE NAME LIKE '%aa%';
EXPLAIN SELECT id,NAME,age,email  FROM tbl_user WHERE NAME LIKE '%aa%';

需求分析:查询时字段两边都是%,且索引不能失效

创建索引(覆盖索引)

#create index
CREATE INDEX idx_user_nameAge ON tbl_user(NAME,age);
 
#DROP INDEX idx_user_nameAge ON tbl_user

分析:email字段并没有创建索引,覆盖索引失效

覆盖索引:建立的索引字段和查询的字段在个数、顺序上最好完全一致。

 9、字符串不加单引号索引失效

 底层进行转换使索引失效,使用了函数造成索引失效

10、少用or,用它来连接时会索引失效

【总结】

带头大哥不能死

中间兄弟不能断(永远要符合最佳左前缀原则)

索引列上无计算

like百分加右边

范围之后全失效

字符串里有引号

 

Guess you like

Origin www.cnblogs.com/116970u/p/10987171.html