The sixth chapter · MySQL index management and implementation plan

I. Introduction Index

1. What is the index

  • 1) Index directory is like a book, it allows you to quickly find the content they want.
  • 2) allow more targeted data acquisition, thereby improving the performance of the database to retrieve the data.

2. Index Type Description

  • 1) BTREE: B + tree index
  • 2) HASH: HASH index
  • 3) FULLTEXT: full-text index
  • 4) RTREE: R-tree index

    FIG 1 · B + tree index

    FIG. 2 · B * tree index

3. Management Index

索引建立在表的列上(字段)的。
在where后面的列建立索引才会加快查询速度。
pages<---索引(属性)<----查数据。

3.1, the index Category:

主键索引
普通索引*****
唯一索引

3.2, adding an index:

#创建索引
alter table test add index index_name(name);
#创建索引
create index index_name on test(name);
#查看索引
desc table;
#查看索引
show index from table;
#删除索引
alter table test drop key index_name;
#添加主键索引(略)
#添加唯一性索引
alter table student add unique key uni_xxx(xxx);
#查看表中数据行数
select count(*) from city;
#查看去重数据行数
select count(distinct name) from city;

3.3, and the United prefix index index

Prefix index

Indexed according to the first N-character field

alter table test add index idx_name(name(10));

避免对大列建索引
如果有,就使用前缀索引

Joint index

Establish a multiple index fields

例:
where a.女生 and b.身高 and c.体重 and d.身材好
index(a,b,c)
特点:前缀生效特性
a,ab,ac,abc,abcd 可以走索引或部分走索引
b bc bcd cd c d ba ... 不走索引

Principles: the most commonly used as query terms on the front row

#创建people表
create table people (id int,name varchar(20),age tinyint,money int ,gender enum('m','f'));
#创建联合索引
alter table people add index  idx_gam(gender,age,money);

Two .explain Detailed

explain the command to use

mysql> explain select name,countrycode from city where id=1;

explain the application command
mode query data

1. Full table scan

  • 1) In the statement explain the result type is ALL
  • 2) when a full table scan occurs?
    2.1 Business really want to get all the data
    2.2 does not take the index due to a full table scan
    2.2.1 no index
    2.2.2 create index in question
    2.2.3 statement has problems
    in production, mysql full use performance when scanning the table is extremely poor, so MySQL try to avoid full table scan

2. index scan

- 2.1 常见的索引扫描类型:
1)index
2)range
3)ref
4)eq_ref
5)const
6)system
7)null

From top to bottom, from worst to best performance, we believe that to reach at least the level range

index : Index Full Scan, index and index types to distinguish ALL traversing the index tree only.
the Range : an index range scan, index scan begins at a certain point, the return match range of the line. Index range scan is apparent with a where clause with or between <,> query.

mysql> alter table city add index idx_city(population);
mysql> explain select * from city where population>30000000;

ref:使用非唯一索引扫描或者唯一索引的前缀扫描,返回匹配某个单独值的记录行。

mysql> alter table city drop key idx_code;
mysql> explain select * from city where countrycode='chn';
mysql> explain select * from city where countrycode in ('CHN','USA');
mysql> explain select * from city where countrycode='CHN' union all select * from city where countrycode='USA';

eq_ref:类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件A

join B 
on A.sid=B.sid

const、system:当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。

如将主键置于where列表中,MySQL就能将该查询转换为一个常量

mysql> explain select * from city where id=1000;

NULL:MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。

mysql> explain select * from city where id=1000000000000000000000000000;

Extra(扩展)

Using temporary
Using filesort 使用了默认的文件排序(如果使用了索引,会避免这类排序)
Using join buffer

如果出现Using filesort请检查order by ,group by ,distinct,join 条件列上没有索引

mysql> explain select * from city where countrycode='CHN' order by population;

当order by语句中出现Using filesort,那就尽量让排序值在where条件中出现

mysql> explain select * from city where population>30000000 order by population;
mysql> select * from city where population=2870300 order by population;
key_len: 越小越好

前缀索引去控制

rows: 越小越好

三.建立索引的原则(规范)

为了使索引的使用效率更高,在创建索引时,必须考虑在哪些字段上创建索引和创建什么类型的索引。

那么索引设计原则又是怎样的?

1、选择唯一性索引

唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。

例如:
学生表中学号是具有唯一性的字段。为该字段建立唯一性索引可以很快的确定某个学生的信息。
如果使用姓名的话,可能存在同名现象,从而降低查询速度。
主键索引和唯一键索引,在查询中使用是效率最高的。
select count(*) from world.city;
select count(distinct countrycode) from world.city;
select count(distinct countrycode,population ) from world.city;

注意:如果重复值较多,可以考虑采用联合索引

2.为经常需要排序、分组和联合操作的字段建立索引

例如:
经常需要ORDER BY、GROUP BY、DISTINCT和UNION等操作的字段,排序操作会浪费很多时间。
如果为其建立索引,可以有效地避免排序操作

3.为常作为查询条件的字段建立索引

如果某个字段经常用来做查询条件,那么该字段的查询速度会影响整个表的查询速度。
因此,为这样的字段建立索引,可以提高整个表的查询速度。

  • 3.1 经常查询
  • 3.2 列值的重复值少
    注:如果经常作为条件的列,重复值特别多,可以建立联合索引

4.尽量使用前缀来索引

如果索引字段的值很长,最好使用值的前缀来索引。例如,TEXT和BLOG类型的字段,进行全文检索
会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索速度。

5.限制索引的数目

索引的数目不是越多越好。每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。
修改表时,对索引的重构和更新很麻烦。越多的索引,会使更新表变得很浪费时间。

6.删除不再使用或者很少使用的索引

表中的数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能不再需要。数据库管理
员应当定期找出这些索引,将它们删除,从而减少索引对更新操作的影响。

7.重点关注:

7.1.没有查询条件,或者查询条件没有建立索引

#全表扫描
select * from table;
select  * from tab where 1=1;

在业务数据库中,特别是数据量比较大的表,是没有全表扫描这种需求。

  • 1)对用户查看是非常痛苦的。
  • 2)对服务器来讲毁灭性的。
  • 3)SQL改写成以下语句:
#情况1
#全表扫描
select * from table;
#需要在price列上建立索引
selec  * from tab  order by  price  limit 10;
#情况2
#name列没有索引
select * from table where name='zhangsan'; 
1、换成有索引的列作为查询条件
2、将name列建立索引

7.2.查询结果集是原表中的大部分数据,应该是25%以上

mysql> explain select * from city where population>3000 order by population;
  • 1)如果业务允许,可以使用limit控制。
  • 2)结合业务判断,有没有更好的方式。如果没有更好的改写方案就尽量不要在mysql存放这个数据了,放到redis里面。

    7.3.索引本身失效,统计数据不真实

索引有自我维护的能力。
对于表内容变化比较频繁的情况下,有可能会出现索引失效。
重建索引就可以解决

7.4.查询条件使用函数在索引列上或者对索引列进行运算,运算包括(+,-,*等)

#例子
错误的例子:select * from test where id-1=9; 
正确的例子:select * from test where id=10;

7.5.隐式转换导致索引失效.这一点应当引起重视.也是开发中经常会犯的错误

mysql> create table test (id int ,name varchar(20),telnum varchar(10));
mysql> insert into test values(1,'zs','110'),(2,'l4',120),(3,'w5',119),(4,'z4',112);
mysql> explain select * from test where telnum=120;
mysql> alter table test add index idx_tel(telnum);
mysql> explain select * from test where telnum=120;
mysql> explain select * from test where telnum=120;
mysql> explain select * from test where telnum='120';

7.6. <> ,not in 不走索引

mysql> select * from tab where telnum <> '1555555';
mysql> explain select * from tab where telnum <> '1555555';

单独的>,<,in 有可能走,也有可能不走,和结果集有关,尽量结合业务添加limit
or或in尽量改成union

EXPLAIN  SELECT * FROM teltab WHERE telnum IN ('110','119');
#改写成
EXPLAIN SELECT * FROM teltab WHERE telnum='110'
UNION ALL
SELECT * FROM teltab WHERE telnum='119'

7.7.like "%_" 百分号在最前面不走

#走range索引扫描
EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '31%';
#不走索引
EXPLAIN SELECT * FROM teltab WHERE telnum LIKE '%110';

%linux%类的搜索需求,可以使用Elasticsearch -------> ELK

7.8.单独引用联合索引里非第一位置的索引列

CREATE TABLE t1 (id INT,NAME VARCHAR(20),age INT ,sex ENUM('m','f'),money INT);
ALTER TABLE t1 ADD INDEX t1_idx(money,age,sex);
DESC t1
SHOW INDEX FROM t1
#走索引的情况测试
EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND age=30  AND sex='m';
#部分走索引
EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30 AND age=30;
EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE money=30  AND sex='m'; 
#不走索引
EXPLAIN SELECT  NAME,age,sex,money FROM t1 WHERE age=20
EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE age=30 AND sex='m';
EXPLAIN SELECT NAME,age,sex,money FROM t1 WHERE sex='m';

Guess you like

Origin www.cnblogs.com/Forever-x/p/10992592.html