zoukankan      html  css  js  c++  java
  • linux系统mysql索引

    索引

    一、索引的分类

    1.根据算法分类

    1)主键索引

    #1.建表时创建
    create table test(id int primary key);
    create table test(id int,primary key(id));
    
    #2.添加主键索引
    alter table test add primary key pri_key(id);
    

    2)唯一建索引

    #1.建表时创建
    create table test(id int unique key);
    
    #2.添加唯一建索引
    alter table test add unique key uni_key(id);
    

    3)普通索引

    #1.添加普通索引
    alter table test add index ljp_key(id);
    

    4)全文索引

    5)查看索引

    #1.方式一:
    mysql> show index from test10;
    
    #2.方式二:
    mysql> desc test10;
    +-------+---------+------+-----+---------+-------+
    | Field | Type    | Null | Key | Default | Extra |
    +-------+---------+------+-----+---------+-------+
    | id    | int(11) | YES  | UNI | NULL    |       |
    +-------+---------+------+-----+---------+-------+
    1 row in set (0.00 sec)
    
    PRI:主键索引
    UNI:唯一建索引
    MUL:普通索引
    

    6)删除索引

    mysql> alter table test drop index index_key;
    

    2.根据配置方法分类

    1)注意事项

    1.创建索引时会将数据重新进行排序
    2.创建索引会占用磁盘空间,所以索引不是越多越好
    3.在同一列上避免创建多种索引
    4.避免在数据很长的字段上创建索引,如果要创建就创建前缀索引
    

    2)前缀索引

    #根据前四个字符创建前缀索引
    mysql> alter table test add index index_key(name(4));
    

    3)联合索引

    mysql> create database xiangqing;
    
    mysql> create table xiangqin(id int,name varchar(20),gender enum('m','f'),age tinyint,money int,height int,weight int,looks tinyint);
    
    mysql> insert xiangqin values(1,'qiudao','m',38,-200000,120,130,'10'),(2,'dilireba','f',18,400000,180,100,'60'),(3,'cxk','m',28,100000,170,120,'440'),(4,'fbb','f',18,1000000,165,85,'90');
    
    #创建联合索引
    mysql> alter table xiangqin add index lh_key(money,gender,age,looks);
    
    #联合索引使用三种情况
    1.部分走索引		money,gender,age
    2.全部走索引		money,gender,age,looks
    3.不走索引		 gender,age
    

    二、explain的使用

    1.explain语法

    explain + DQL语句
    
    mysql> explain select * from city where countrycode ='CHN' or countrycode ='USA';
    
    #查询中国和美国的数据
    mysql> select * from city where countrycode ='CHN' or countrycode ='USA';
    mysql> select * from city where countrycode in ('CHN','USA');
    mysql> select * from city where countrycode = 'CHN' union all select * from city where countrycode = 'USA';
    
    Extra(扩展)
    	Using temporary 使用group by大概率出现
    	Using filesort 使用了order by大概率出现
    	Using join buffer 使用join on大概率出现
    

    2.扩展group by

    #一般与聚合索引一起使用
    
    #建表
    mysql> create table jixiao(id int,name varchar(20) charset utf8,jixiao int,product varchar(10) charset utf8);                                    
    Query OK, 0 rows affected (0.03 sec)
    #插入数据
    mysql> insert jixiao values(1,'qiudao','1000000','房地产'),(2,'niulei','10000','房地产'),(3,'lijianpeng','100000','汽车'),(4,'qiandao','200000',' 汽车');
    #查询不同行业绩效最高的人
    mysql> select name,sum(jixiao),product from jixiao group by product;
    +------------+-------------+-----------+
    | name       | sum(jixiao) | product   |
    +------------+-------------+-----------+
    | qiudao     |     1010000 | 房地产    |
    | lijianpeng |      300000 | 汽车      |
    +------------+-------------+-----------+
    2 rows in set (0.00 sec)
    #查询房地产行业绩效最高的人
    mysql> select name,sum(jixiao),product from jixiao group by product having product='房地产';
    +--------+-------------+-----------+
    | name   | sum(jixiao) | product   |
    +--------+-------------+-----------+
    | qiudao |     1010000 | 房地产    |
    +--------+-------------+-----------+
    1 row in set (0.00 sec)
    

    3.查询数据的方式

    1)全表扫描

    #1.什么是全表扫描
    查询数据时type类型为ALL
    
    #2.什么情况全表扫描
    1)查询数据库所有数据
    	mysql> explain select * from country
    2)没有走索引
    	没设置索引
    	索引损坏
    

    2)索引扫描

    1.index			#全索引扫描
    	mysql> explain select Name from city;
    
    2.range			#范围查询
    	mysql> explain select * from city where countrycode ='CHN' or countrycode ='USA';
    	#有限制查询到的数据在总数据的20%以内,超过则走全文扫描,所以在查询是可以使用limit限制
    	mysql> explain select * from city where countrycode != 'CHN' limit 500;
    
    3.ref			#精确查询
    	mysql> explain select * from city where countrycode ='CHN';
    
    4.eq_ref		#使用join on时偶尔会出现
    
    5.const			#查询条件是唯一索引或主键索引
    	mysql> explain select * from city where id=1;
    
    6.system		#查询级别与const一样,当数据很少时为该级别
    
    7.null			#不需要读取数据,只需要获取最大值或者最小值
    	mysql> explain select max(population) from city;
    

    三、索引的建立

    1.索引的建立原则

    1.能创建唯一索引就创建唯一索引
    
    2.为经常需要排序、分组和联合操作的字段建立索引
    
    3.为常作为查询条件的字段建立索引
    	如果某个字段经常用来做查询条件,那么该字段的查询速度会影响整个表的查询速度。
    	因此,为这样的字段建立索引,可以提高整个表的查询速度。
    	
    4.尽量使用前缀来索引
    	如果索引字段的值很长,最好使用值的前缀来索引。
    		例如,TEXT和BLOG类型的字段,进行全文检索,会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索速度。
    		
    5.限制索引的数目
    	索引的数目不是越多越好。每个索引都需要占用磁盘空间,索引越多,需要的磁盘空间就越大。
    	修改表时,对索引的重构和更新很麻烦。越多的索引,会使更新表变得很浪费时间。
    
    6.删除不再使用或者很少使用的索引
    	表中的数据被大量更新,或者数据的使用方式被改变后,原有的一些索引可能不再需要。数据库管理员应当定期找出这些索引,将它们删除,从而减少索引对更新操作的影响。
    

    2.总结什么时候不走索引

    1)没有查询条件,或者查询条件没有索引

    #没有查询条件
    mysql> explain select * from city;
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    |  1 | SIMPLE      | city  | ALL  | NULL          | NULL | NULL    | NULL | 4188 | NULL  |
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    1 row in set (0.00 sec)
    
    #查询条件没有索引
    mysql> explain select District from city;
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    |  1 | SIMPLE      | city  | ALL  | NULL          | NULL | NULL    | NULL | 4188 | NULL  |
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    1 row in set (0.00 sec)
    

    2)查询的结果占总数据的20%左右

    #占总数据的18%,没走索引
    mysql> explain select * from city where population > 400000;
    
    #占总数据的15%,走了索引
    mysql> explain select * from city where population > 450000;
    
    #如果数据量查询就是表中大部分数据,可以用limit做限制
    mysql> explain select * from city where population > 400000 limit 100;
    

    3)索引损坏

    4)查询条件带了特使符号(+,-)

    #在=号左侧有特殊符号,不走索引
    mysql> explain select * from city where id-1=1;
    
    #在=号右侧有特殊符号,走索引
    mysql> explain select * from city where id=3-1;
    

    5)隐式转换

    #建表
    mysql> create table test (id int ,name varchar(20),telnum varchar(10));
    Query OK, 0 rows affected (0.04 sec)
    #插入数据
    mysql> insert into test values(1,'zs','110'),(2,'l4',120),(3,'w5',119),(4,'z4',112);
    Query OK, 4 rows affected (0.00 sec)
    Records: 4  Duplicates: 0  Warnings: 0
    #建立索引
    mysql> desc phonenum;
    +-------+-------------+------+-----+---------+-------+
    | Field | Type        | Null | Key | Default | Extra |
    +-------+-------------+------+-----+---------+-------+
    | id    | int(11)     | YES  |     | NULL    |       |
    | name  | varchar(10) | YES  |     | NULL    |       |
    | phone | varchar(10) | YES  | UNI | NULL    |       |
    +-------+-------------+------+-----+---------+-------+
    3 rows in set (0.00 sec)
    #查询语句级别全文扫描
    mysql> explain select * from phonenum where phone=6666666;
    +----+-------------+----------+------+---------------+------+---------+------+------+-------------+
    | id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows | Extra       |
    +----+-------------+----------+------+---------------+------+---------+------+------+-------------+
    |  1 | SIMPLE      | phonenum | ALL  | uni_key       | NULL | NULL    | NULL |    3 | Using where |
    +----+-------------+----------+------+---------------+------+---------+------+------+-------------+
    1 row in set (0.00 sec)
    #当给字符加上引号,查询为索引扫描
    mysql> explain select * from phonenum where phone='6666666';
    +----+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
    | id | select_type | table    | type  | possible_keys | key     | key_len | ref   | rows | Extra |
    +----+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
    |  1 | SIMPLE      | phonenum | const | uni_key       | uni_key | 13      | const |    1 | NULL  |
    +----+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
    1 row in set (0.00 sec)
    

    6)like "%_" 百分号在最前面不走

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

    7)联合索引查询不按照顺序有可能不走索引

    %linux%类的搜索需求,可以使用Elasticsearch -------> ELK
    单独引用联合索引里非第一位置的索引列

    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';
    
  • 相关阅读:
    【美团技术团队文章--学习笔记】之 Java动态追踪技术探究
    mq
    为啥要读写分离
    算法 数据结构
    对扩展开放,对修改关闭
    redis 事务
    准实时数仓设计方案
    Scala Puzzlers 系列(一):占位符的使用
    【面试题】大数据开发岗位
    Hive 分区和分桶
  • 原文地址:https://www.cnblogs.com/zabcd/p/13330076.html
Copyright © 2011-2022 走看看