您的位置:首页 > 数据库 > MySQL

20150324--Mysql索引优化-02

2016-05-08 21:32 519 查看

七、索引覆盖

索引覆盖是指:如果查询的列恰好是索引的一部分,那么查询只需要在索引文件上进行,不需要回行到磁盘再找数据,这种查询速度非常快,称为“索引覆盖” 案例1,如下对name字段添加了普通索引,要查询name字段信息。

案例2:比如对id和name字段建立符合索引,我们取出的数据是复合索引的一部分,因此用到了索引覆盖。

八、前缀索引,

利用字段数据的前部分作为索引,称为前缀索引。减少索引长度,提高索引效率。 比如:统计密码的前7个字符,作为不相同匹配条件,几乎可以做到1:1 此时,就可以利用前7个字符做索引关键字即可(离散程度高)

语法: alter table 表名 add index (passwd(7)) 指定前7位作为索引关键字。 不使用索引前缀,索引的长度。

使用索引前缀后,索引的长度。



九、翻页优化

翻页的sql语句: select * from table_name limit offset N 使用如上语句,在翻页时,翻到最后,越来越慢, 原因:并不是跨过offset行,取出n条, 是取出offset+N条数据,舍弃前面的offset行,只取出n条数据。

如何解决? (1)从业务上去解决: 办法:不允许翻过100页, 以百度为例,一般翻页到70页左右,谷歌40页左右 (2)不用offset,用条件查询,条件中使用id查询,使用到了索引, select * from user limit 10000,10; select * from user where id>10000 limit 10; 下一页:select * from user where id>10000+10 limit 10 该种方式要注意:如果有数据被删除,会导致select * from user limit 10000,10; 和select * from user where id>10000 limit 10;语句取出的结果不一样,。

(3)假如不能使用限制翻页到100页,数据有删除,还要求翻页,速度不能受影响。 思路:通过翻页,先取出id(主键),在根据id取出数据。 select name,age,email from user inner join (select id from user limit 10000,10) as tmp on tmp.id=user.id 非要物理删除,还要用offset精确查询,还不限制用户分页,怎么办 我们现在必须要查,则只查索引,不查数据,得到id 再用id去查具体条目,这种技巧就是延迟索引

十、碎片整理

比如建表测试:

数据表文件原来的容量:

当delete from ceshi where id=1,应该容量减去三分之一,但是并没有被删除。 需要把里面的一些碎片给释放掉。 使用optimize table 表名;或alter table 表名 engine myisam(innodb) 执行optimize table 表名,命令后,把原来的碎片空间给释放掉

注意:修复表的数据及索引碎片,就会把所有的数据文件重新整理一遍,使之对齐,这个过程,如果表的行数比较大,也是比较耗费资源的操作,所以,不能频繁的修复。 如果表的update操作很频繁,可以按周月来修复

十一、锁机制讲解

场景: 下订单: 库存 为100,买一件: (1)取出库存的数量 100 (2)库存减去1 99 (3)把剩余的库存再写入到表里面。 99 如果是两个人同时操作: 刘备: 100-1=99 99 曹操: 100-1=99 99 锁机制, mysql 的锁有以下几种形式: 表级锁:开销小,加锁快,发生锁冲突的概率最高,并发度最低。myisam引擎属于这种类型。 行级锁:开销大,加锁慢,发生锁冲突的概率最低,并发度也最高。innodb属于这种类型。

1、表锁的演示:

对myisam表的读操作(加读锁),不会阻塞其他进程对同一表的读请求,但会阻塞对同一表的写请求。只有当读锁释放后,才会执行其他进程的操作。 对myisam表的写操作(加写锁),会阻塞其他进程对同一表的读和写操作,只有当写锁释放后,才会执行其他进程的读写操作。 read:所有人都只可以读,只有释放锁之后才可以写。 write:只有锁表的客户可以操作这个表,其他客户读都不能读。 语法: lock table 表名 read|write, 解锁: unlock table 读锁的演示:





要注意:对表添加锁定后,只能操作锁定的表,如果想要操作其他表,则可以在锁定表时,一次性锁定多张表。语法:lock table 表1 read,表2 read;

写锁的演示 对表写锁锁定之后,自己可以进行修改和查询,另外的进程则无法查询,更不能修改。



2、行锁的演示:

是innodb支持的一种锁,在使用时,要添加条件限制是要操作哪行数据。 语法: begin; //开始 执行语句;//要锁的行 commit; //解锁













文件锁,flock_file

十二、分区分表技术

基本概念,把一个表,从逻辑上分成多个区域,便于存储数据。 采用分区的前提:数据量非常大

分区的语法,在创建表时,完成分区 create table 表名( 字段信息 )表选项 partition by 分区的类型(分区的条件)( //分区信息。 );vvvvvvvvvvvvvvvv

1、分区类型:

list :条件值为一个数据列表。 通过预定义的列表的值来对数据进行分割 例子:假如你创建一个如下的一个表,该表保存有全国20家分公司的职员记录,这20家分公司的编号从1到20.而这20家分公司分布在全国5个区域,如下表所示: 职员表: id name store_id(分公司的id) 北部 1,4,5,6,17,18 南部 2,7,9,10,11,13 东部 3,12,19,20 西部 8,14,15,16 id name store_id(分公司的id) 1 李小龙 3 2 大刀王五 8 北部 1,4,5,6,17,18 南部 2,7,9,10,11,13 东部 3,12,19,20 西部 8,14,15,16 create table emp( id int, name varchar(32), store_id int )engine myisam charset utf8 partition by list (store_id)( partition p_north values in (1,4,5,6,17,18), partition p_east values in(2,7,9,10,11,13), partition p_south values in(3,12,19,20), partition p_west values in(8,14,15,16) );



添加两天条语句,测试是否使用了分区存储。

explain partitions select *from emp where store_id=3 测试是否用到了分区: explain partitions select * from p_list where store_id=20\G 注意:在使用分区时,where后面的字段必须是分区字段,才能使用到分区。

Range(范围) 这种模式允许将数据划分不同范围。例如可以将一个表通过年份划分成若干个分区 create table p_range( id int, name varchar(32), birthday date )partition by range (month(birthday))( partition p_1 values less than (3), partition p_2 values less than(6), partition p_3 values less than(9), partition p_4 values less than MAXVALUE ); less than 小于等于; MAXVALUE可能的最大值 partition by range(month(birthday))( partition p_north values in (1,4,5,6,17,18), partition p_east values in(2,7,9,10,11,13), partition p_south values in(3,12,19,20), partition p_west values in(8,14,15,16) );
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: