MySQL常见索引报错_MySQL(索引)

索引:

索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。

组合索引,即一个索包含多个列。

创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。 实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。上面都在说使用索引的好处,但过多的使用索引将会造成滥用。

缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。建立索引会占用磁盘空间的索引文件。

MySQL中常见索引有:

普通索引:仅加速查询。

唯一索引:加速查询 + 列值唯一(可以有null)。

主键索引:加速查询 + 列值唯一 + 表中只有一个(不可以有null)。

组合索引:多列值组成一个索引,专门针对多条件查询。

全文索引:对文本的内容进行分词,进行搜索 。

索引合并:使用多个单列索引组合搜索。

覆盖索引,select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖。

普通索引:

#先创建一个新的表格

CREATE TABLE People(

id INT NOT NULL auto_increment ,#自增

NAME VARCHAR(32) NOT NULL ,

email VARCHAR(126) ,

PRIMARY KEY(id)#设置id为主键

) ENGINE = INNODB DEFAULT CHARSET = utf8;#查看索引

show index from People;+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |

+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| people | 0 | PRIMARY | 1 | id | A | 0 | NULL | NULL | | BTREE | | |

+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

#我们现在也没有创建索引啊,怎么People中的id就成了索引呢? 注意:表中的主键默认就是索引。

创建索引:

创建表格后添加:

mysql>create index ix_name on People(name);

Query OK, 0 rows affected (0.01sec)

mysql> show index from People;+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |

+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| people | 0 | PRIMARY | 1 | id | A | 0 | NULL | NULL | | BTREE | | |

| people | 1 | ix_name | 1 | NAME | A | 0 | NULL | NULL | | BTREE | | |

+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

创建表格时添加索引:

index 索引名称(列(大小))

DROP TABLEifEXISTS People;

CREATE TABLE People(

id INT NOT NULL auto_increment ,

name VARCHAR(32) NOT NULL ,

email VARCHAR(126) ,

PRIMARY KEY(id),

INDEX ix_name(name(32))

) ENGINE= INNODB DEFAULT CHARSET =utf8;

mysql> show index from People;+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |

+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| people | 0 | PRIMARY | 1 | id | A | 0 | NULL | NULL | | BTREE | | |

| people | 1 | ix_name | 1 | name | A | 0 | NULL | NULL | | BTREE | | |

+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

2 rows in set (0.00sec)#删除索引

drop index 索引名称 on 表名;

mysql>drop index ix_name on People;

Query OK, 0 rows affected (0.01sec)

Records: 0 Duplicates: 0 Warnings: 0

mysql> show index from People;+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |

+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| people | 0 | PRIMARY | 1 | id | A | 0 | NULL | NULL | | BTREE | | |

+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

1 row in set (0.00 sec)

查看索引type:

explain select *from People where email ='tom@123.com'

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

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

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

| 1 | SIMPLE | People | NULL | ALL | NULL | NULL | NULL | NULL | 6 | 16.67 | Using where |

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+mysql> explain select *from People where id = 1;+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+

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

+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+

| 1 | SIMPLE | People | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL |

+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+

1 row in set, 1 warning (0.00sec)

mysql> explain select *from People where name = 'alex';+----+-------------+--------+------------+------+---------------+------------+---------+-------+------+----------+-------+

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

+----+-------------+--------+------------+------+---------------+------------+---------+-------+------+----------+-------+

| 1 | SIMPLE | People | NULL | ref | index_name | index_name | 98 | const | 1 | 100.00 | NULL |

+----+-------------+--------+------------+------+---------------+------------+---------+-------+------+----------+-------+

1 row in set, 1 warning (0.00sec)#其中的 type 为 ALL 这就是MySQL默认的搜索type 也是最慢的,而id的type 为const ,name 为 ref 都是快速的索引。

唯一索引:

唯一索引和普通索引差不多,他的索引值必须是具有唯一性,值可以为NULL。如果是组合索引,则列值的组合必须唯一。

作用:加速查询和唯一约束(可含null)

创建表格是添加唯一索引:

unique 索引名称(列名(大小))

CREATE TABLE People(

id INT NOT NULL auto_increment ,

name VARCHAR(32),

email VARCHAR(126) not null,

PRIMARY KEY(id),

UNIQUE ix_name(name(32)) #设置name为唯一索引

) ENGINE= INNODB DEFAULT CHARSET = utf8;

唯一性:通过往表中插入数据来验证,因为name列是唯一性的,所以,如果重复插入相同的名字就会报错

mysql>desc People;+-------+--------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |

+-------+--------------+------+-----+---------+----------------+

| id | int(11) | NO | PRI | NULL | auto_increment |

| name | varchar(32) | YES | UNI | NULL | |

| email | varchar(126) | NO | | NULL | |

+-------+--------------+------+-----+---------+----------------+

3 rows in set (0.00sec)

mysql>insert into People(name,email)values('alex','alex@123.com');

Query OK,1 row affected (0.00sec)

mysql> insert into People(name,email)values('alex','alex@123.com');

ERROR1062 (23000): Duplicate entry 'alex' for key 'ix_name'

可为NULL:

可以为NULL的意思就是可以插入NULL值

mysql> insert into People(name,email)values(NULL,'alex@123.com');

Query OK,1 row affected (0.00sec)

mysql> insert into People(name,email)values(NULL,'alex@123.com');

Query OK,1 row affected (0.00sec)

mysql> select *fromPeople;+----+------+--------------+

| id | name | email |

+----+------+--------------+

| 1 | alex | alex@123.com |

| 3 | NULL | alex@123.com |

| 4 | NULL | alex@123.com |

+----+------+--------------+

3 rows in set (0.00sec)#查看搜索type

mysql> explain select *from People where name = 'alex';+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+

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

+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+

| 1 | SIMPLE | People | NULL | const | ix_name | ix_name | 99 | const | 1 | 100.00 | NULL |

+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+

1 row in set, 1 warning (0.00sec)

mysql> explain select *from People where name = NULL; 查找不到+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+

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

+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+

| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | no matching row in const table |

+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+--------------------------------+

1 row in set, 1 warning (0.00sec)

mysql> explain select *from People where name is NULL;+----+-------------+--------+------------+------+---------------+---------+---------+-------+------+----------+-----------------------+

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

+----+-------------+--------+------------+------+---------------+---------+---------+-------+------+----------+-----------------------+

| 1 | SIMPLE | People | NULL | ref | ix_name | ix_name | 99 | const | 2 | 100.00 | Using index condition |

+----+-------------+--------+------------+------+---------------+---------+---------+-------+------+----------+-----------------------+

1 row in set, 1 warning (0.00sec)

mysql> select *from People where name is NULL;+----+------+--------------+

| id | name | email |

+----+------+--------------+

| 3 | NULL | alex@123.com |

| 4 | NULL | alex@123.com |

+----+------+--------------+

2 rows in set (0.00sec)#当设置为NULL的时候,能够查找到结果的写法是 where name is NULL,相应的搜索type 也变成了普通索引的 ref

主键索引:

他的索引值必须是具有唯一性,且索引值不可为NULL。如果是组合索引,则列值的组合必须唯一。

作用:加速查询和唯一约束(不可含null)

创建主键的时候默认的就会指定索引。

mysql> explain select *from People where id = 3;+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+

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

+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+

| 1 | SIMPLE | People | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 | 100.00 | NULL |

+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+

组合索引:

组合索引是将多个列组合成一个索引。

其应用场景为:频繁的同时使用多个列来进行查询,如:where n1 = 'alex' and n2 = 666。

创建表:

DROP TABLE ifEXISTS People;

CREATE TABLE People(

id INT NOT NULL auto_increment ,

name VARCHAR(32),

email VARCHAR(126) NOT NULL,

PRIMARY KEY(id),

) ENGINE= INNODB DEFAULT CHARSET = utf8;

创建索引:

create index ix_name_email on People(name,email);

如上创建组合索引之后,查询:

name and email  -- 使用索引

name                 -- 使用索引

email                 -- 不使用索引,最左索引

注意:对于同时搜索多个条件时,组合索引的性能好于多个单一索引合并。

索引相关应用:

相关命令:

- 查看表结构:desc 表名;

mysql>desc People;+-------+--------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |

+-------+--------------+------+-----+---------+----------------+

| id | int(11) | NO | PRI | NULL | auto_increment |

| name | varchar(32) | YES | MUL | NULL | |

| email | varchar(126) | NO | | NULL | |

+-------+--------------+------+-----+---------+----------------+

- 查看索引:show index on 表名;

mysql> show index in People;+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |

+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| people | 0 | PRIMARY | 1 | id | A | 0 | NULL | NULL | | BTREE | | |

| people | 0 | ix_name | 1 | name | A | 0 | NULL | NULL | YES | BTREE | | |

| people | 0 | ix_name | 2 | email | A | 0 | NULL | NULL | | BTREE | | |

+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

- 查看执行时间:

set profiling = 1;

SQL语句

show profiles;

mysql> set profiling = 1;

Query OK, 0 rows affected,1 warning (0.00sec)

mysql> select *from Person where id = 1;+----+------+------+------------+

| id | name | age | part_2_nid |

+----+------+------+------------+

| 1 | tom | 11 | 1 |

+----+------+------+------------+

1 row in set (0.00sec)

mysql>show profiles;+----------+------------+----------------------------------+

| Query_ID | Duration | Query |

+----------+------------+----------------------------------+

| 1 | 0.00025400 | select *from Person where id = 1 |

+----------+------------+----------------------------------+

1 row in set, 1 warning (0.00 sec)

正确使用索引:

数据库表中添加索引后确实会让查询速度起飞,但前提必须是正确的使用索引来查询,如果以错误的方式使用,则即使建立索引也会不奏效。

即使建立索引,索引也不会生效:

验证时使用的表格:

mysql> select *from Person;+----+-------+------+------------+--------+

| id | name | age | part_2_nid | color |

+----+-------+------+------------+--------+

| 1 | tom | 11 | 1 | red |

| 2 | jerry | 12 | 2 | yellow |

| 3 | jack | 123 | 3 | black |

| 4 | rose | 14 | 3 | green |

| 5 | coco | NULL | 2 | white |

| 6 | kk | NULL | 3 | orange |

+----+-------+------+------------+--------+

6 rows in set (0.00sec)

mysql> show index from Person;+--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |

+--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| person | 0 | PRIMARY | 1 | id | A | 6 | NULL | NULL | | BTREE | | |

| person | 0 | age_index_1 | 1 | age | A | 5 | NULL | NULL | YES | BTREE | | |

| person | 1 | part_1_nid | 1 | part_2_nid | A | 3 | NULL | NULL | | BTREE | | |

| person | 1 | part_2_nid | 1 | part_2_nid | A | 3 | NULL | NULL | | BTREE | | |

| person | 1 | ix_name | 1 | name | A | 6 | NULL | NULL | | BTREE | | |

+--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

5 rows in set (0.00sec)

mysql>desc Person;+------------+-------------+------+-----+---------+----------------+

| Field | Type | Null | Key | Default | Extra |

+------------+-------------+------+-----+---------+----------------+

| id | int(32) | NO | PRI | NULL | auto_increment |

| name | varchar(32) | NO | MUL | NULL | |

| age | int(32) | YES | UNI | NULL | |

| part_2_nid | int(11) | NO | MUL | NULL | |

| color | char(32) | NO | | NULL | |

+------------+-------------+------+-----+---------+----------------+

5 rows in set (0.00 sec)

- like '%xxx':

mysql> create index ix_name on Person(name(32));

Query OK, 0 rows affected (0.01sec)

Records: 0 Duplicates: 0 Warnings: 0

mysql>explain select *from Person where name like '%om';+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

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

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

| 1 | SIMPLE | Person | NULL | ALL | NULL | NULL | NULL | NULL | 6 | 16.67 | Using where |

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

1 row in set, 1 warning (0.00sec)

# 正确使用:

mysql> explain select *from Person where name like 'T%';+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+

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

+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+

| 1 | SIMPLE | Person | NULL | range | ix_name | ix_name | 34 | NULL | 1 | 100.00 | Using index condition |

+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-----------------------+

1 row in set, 1 warning (0.00 sec)

给Person 中的name 建立索引后,用模糊查询的字段开始用%占位符查询用的是全局查询,是不会用索引的,而后边用占位符的话是可以使用查询的。

- 使用函数:

mysql> explain select *from Person where reverse(name) = 'moT';+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

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

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

| 1 | SIMPLE | Person | NULL | ALL | NULL | NULL | NULL | NULL | 6 | 100.00 | Using where |

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

1 row in set, 1 warning (0.00sec)#正确使用:

mysql> explain select *from Person where name = reverse('moT');+----+-------------+--------+------------+------+---------------+---------+---------+-------+------+----------+-------+

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

+----+-------------+--------+------------+------+---------------+---------+---------+-------+------+----------+-------+

| 1 | SIMPLE | Person | NULL | ref | ix_name | ix_name | 34 | const | 1 | 100.00 | NULL |

+----+-------------+--------+------------+------+---------------+---------+---------+-------+------+----------+-------+

1 row in set, 1 warning (0.00 sec)

- or

#or 条件不会使用索引(两列都建立索引也不会走索引)

mysql> show index from Person;+--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |

+--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

| person | 0 | PRIMARY | 1 | id | A | 6 | NULL | NULL | | BTREE | | |

| person | 0 | age_index_1 | 1 | age | A | 5 | NULL | NULL | YES | BTREE | | |

| person | 1 | part_1_nid | 1 | part_2_nid | A | 3 | NULL | NULL | | BTREE | | |

| person | 1 | part_2_nid | 1 | part_2_nid | A | 3 | NULL | NULL | | BTREE | | |

| person | 1 | ix_name | 1 | name | A | 6 | NULL | NULL | | BTREE | | |

+--------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

5 rows in set (0.00sec)

mysql> explain select *from Person where name = 'tom' or color = 'red' and age = 11;+----+-------------+--------+------------+------+---------------------+------+---------+------+------+----------+-------------+

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

+----+-------------+--------+------------+------+---------------------+------+---------+------+------+----------+-------------+

| 1 | SIMPLE | Person | NULL | ALL | age_index_1,ix_name | NULL | NULL | NULL | 6 | 19.44 | Using where |

+----+-------------+--------+------------+------+---------------------+------+---------+------+------+----------+-------------+

1 row in set, 1 warning (0.00sec)

mysql> explain select *from Person where name = 'tom' or age = 11;+----+-------------+--------+------------+------+---------------------+------+---------+------+------+----------+-------------+

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

+----+-------------+--------+------------+------+---------------------+------+---------+------+------+----------+-------------+

| 1 | SIMPLE | Person | NULL | ALL | age_index_1,ix_name | NULL | NULL | NULL | 6 | 33.33 | Using where |

+----+-------------+--------+------------+------+---------------------+------+---------+------+------+----------+-------------+

1 row in set, 1 warning (0.00sec)

mysql> explain select *from Person where name = 'tom' or color = 'red';+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

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

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

| 1 | SIMPLE | Person | NULL | ALL | ix_name | NULL | NULL | NULL | 6 | 30.56 | Using where |

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

1 row in set, 1 warning (0.00 sec)

- 类型不一致:

指的是如果输入值与搜索类型的值类型不一致,也是不会走索引

mysql> explain select *from Person where name = 888; 搜索类型为int+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

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

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

| 1 | SIMPLE | Person | NULL | ALL | ix_name | NULL | NULL | NULL | 6 | 16.67 | Using where |

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

1 row in set, 3 warnings (0.00sec)

mysql> explain select *from Person where name = '888';+----+-------------+--------+------------+------+---------------+---------+---------+-------+------+----------+-------+

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

+----+-------------+--------+------------+------+---------------+---------+---------+-------+------+----------+-------+

| 1 | SIMPLE | Person | NULL | ref | ix_name | ix_name | 34 | const | 1 | 100.00 | NULL |

+----+-------------+--------+------------+------+---------------+---------+---------+-------+------+----------+-------+

1 row in set, 1 warning (0.00 sec)

- !=

在搜索的列不为主键的情况下,不走索引。

mysql> explain select *from Person where name != 'tom'; 搜索条件不是主键时+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

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

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

| 1 | SIMPLE | Person | NULL | ALL | ix_name | NULL | NULL | NULL | 6 | 100.00 | Using where |

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

1 row in set, 1 warning (0.00sec)

mysql> explain select *from Person where id != 2;  搜索条件为主键时是走索引的+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

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

+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

| 1 | SIMPLE | Person | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 5 | 100.00 | Using where |

+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

- >

当搜索条件为主键或者搜索条件为整形时(小数类型不走索引),可以走索引。注:< 都是走索引的。

mysql> explain select *from Person where name > 'dfds'; 搜索条件不为整形切不是主键+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

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

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+

| 1 | SIMPLE | Person | NULL | ALL | ix_name | NULL | NULL | NULL | 6 | 83.33 | Using where |

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+-------------+mysql> explain select *from Person where id > 1; 搜索条件为主键+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

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

+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

| 1 | SIMPLE | Person | NULL | range | PRIMARY | PRIMARY | 4 | NULL | 5 | 100.00 | Using where |

+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

1 row in set, 1 warning (0.00sec)

mysql> explain select *from Person where age > 21; 值为 int 类型+----+-------------+--------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+

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

+----+-------------+--------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+

| 1 | SIMPLE | Person | NULL | range | age_index_1 | age_index_1 | 5 | NULL | 1 | 100.00 | Using index condition |

+----+-------------+--------+------------+-------+---------------+-------------+---------+------+------+----------+-----------------------+

1 row in set, 1 warning (0.00 sec)

-  order by

当根据索引排序时候,选择的映射如果不是索引,则不走索引

mysql> explain select *from Person order by name desc; 其中的 color 没有索引属性+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+----------------+

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

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+----------------+

| 1 | SIMPLE | Person | NULL | ALL | NULL | NULL | NULL | NULL | 6 | 100.00 | Using filesort |

+----+-------------+--------+------------+------+---------------+------+---------+------+------+----------+----------------+

1 row in set, 1 warning (0.00sec)

mysql> explain select id,name from Person order by name desc; 其中返回的 id 和 name 都是具有索引属性。+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

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

+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

| 1 | SIMPLE | Person | NULL | index | NULL | ix_name | 34 | NULL | 6 | 100.00 | Using index |

+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------------+

1 row in set, 1 warning (0.00 sec)

当索引排序的列为主键时,不管映射是否为索引,会走索引的。

mysql> explain select id,name from Person order by id desc;+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------+

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

+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------+

| 1 | SIMPLE | Person | NULL | index | NULL | PRIMARY | 4 | NULL | 6 | 100.00 | NULL |

+----+-------------+--------+------------+-------+---------------+---------+---------+------+------+----------+-------+

1 row in set, 1 warning (0.00 sec)

注意事项:

避免使用select *

count(1)或count(列) 代替count(*)

创建表时尽量时char 代替varchar

表的字段顺序固定长度的字段优先

Limit 分页:无论是否有索引,limit分页是一个很棒的功能.

假如说我们有1000万条数据,类似论坛里的回贴,那么 我们如果想查询第200万条数据之后的10条数据,该怎样查询呢?

常用的查询方法是 :

select *from tb limit 2000000, 10;

但是 这种查询方法是属于全局搜索,也就是说搜索的type = ALL 非常浪费时间.

优化方案1(可取,但优化效果不大):

select* from tb where id > (select id from tb limit(20000000-1),1) limit10;

虽然也是优化,但是也就提高了0.X秒左右,效率也没有提高多少。

优化方案2:

可以分页成每页显示10条数据

第一页:1,2,3,4,5,6,7,8,9,10;         -select * from tb where id > 0 order asc limit 10;

第二页:11,12,13,14,15,16,17,18,19,20;         - select * from tb where id > 10 order asc limit 10;

第N页:....                       -select * from tb where id >(n-1)*10 order asc limit 10;

继续优化:

4ee4890fc4ae7820d8c2f1ea295860b9.png

如果说我现在在第一页,但是我想看第4页的数据:那么数据就是从中间就是间隔了(4-1)*10 = 30,从起始值开始算的话,就是0+30 = 30 ,第4页就是从30以后的10条数据。

这样我们就可以先获取从第4页的 id 起始索引:

第四页的起始索引 = select id from (select id from tb where id > 0 order by asc limit 30) as A  order by desc limit 1;

然后就开始从这个索引的起始开始查找数据:

select *from tb where id > (select id from (select id from tb where id > 0 order by asc limit 30) as A  order by desc limit 1; ) limit 10;

这种方式唯一的缺点就是说如果跳转的数据太多的话 ,是需要 将中间的数据都查找的过程是比较耗时。

执行计划:

prolain MySQL 查询语句:

id

查询顺序标识

如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B;+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+

| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |

+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+

| 1 | PRIMARY | | ALL | NULL | NULL | NULL | NULL | 9 | NULL |

| 2 | DERIVED | tb1 | range | PRIMARY | PRIMARY | 8 | NULL | 9 | Using where |

+----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+特别的:如果使用union连接气值可能为null

select_type

查询类型

SIMPLE 简单查询

PRIMARY 最外层查询

SUBQUERY 映射为子查询

DERIVED 子查询

UNION 联合

UNION RESULT 使用联合的结果

...

table

正在访问的表名

type

查询时的访问方式,性能:all< index < range < index_merge < ref_or_null < ref < eq_ref < system/const

ALL 全表扫描,对于数据表从头到尾找一遍

select* fromtb1;

特别的:如果有limit限制,则找到之后就不在继续向下扫描

select* from tb1 where email = 'seven@live.com'select* from tb1 where email = 'seven@live.com' limit 1;

虽然上述两个语句都会进行全表扫描,第二句使用了limit,则找到一个后就不再继续扫描。

INDEX 全索引扫描,对索引从头到尾找一遍

select nidfromtb1;

RANGE 对索引列进行范围查找

select* from tb1 where name < 'alex';

PS:

betweenand

in

> >= < <=操作

注意:!= 和 >符号

INDEX_MERGE 合并索引,使用多个单列索引搜索

select* from tb1 where name = 'alex' or nid in (11,22,33);

REF 根据索引查找一个或多个值

select* from tb1 where name = 'seven';

EQ_REF 连接时使用primary key 或 unique类型

select tb2.nid,tb1.namefrom tb2 left join tb1 on tb2.nid =tb1.nid;

CONST 常量

表最多有一个匹配行,因为仅有一行,在这行的列值可被优化器剩余部分认为是常数,const表很快,因为它们只读取一次。

select nidfrom tb1 where nid = 2;

SYSTEM 系统

表仅有一行(=系统表)。这是const联接类型的一个特例。

select* from (select nid from tb1 where nid = 1) as A;

possible_keys

可能使用的索引

key

真实使用的

key_len

MySQL中使用索引字节长度

rows

mysql估计为了找到所需的行而要读取的行数------只是预估值

extra

该列包含MySQL解决查询的详细信息

“Using index”

此值表示mysql将使用覆盖索引,以避免访问表。不要把覆盖索引和index访问类型弄混了。

“Using where”

这意味着mysql服务器将在存储引擎检索行后再进行过滤,许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个暗示:查询可受益于不同的索引。

“Using temporary”

这意味着mysql在对查询结果排序时会使用一个临时表。

“Using filesort”

这意味着mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。mysql有两种文件排序算法,这两种排序方式都可以在内存或者磁盘上完成,explain不会告诉你mysql将使用哪一种文件排序,也不会告诉你排序会在内存里还是磁盘上完成。

“Range checkedforeach record(index map: N)”

这个意味着没有好用的索引,新的索引将在联接的每一行上重新估算,N是显示在possible_keys列中索引的位图,并且是冗余的。

更多:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值