山山未迟

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

七、索引覆盖

索引覆盖是指:如果查询的列恰好是索引的一部分,那么查询只需要在索引文件上进行,不需要回行到磁盘再找数据,这种查询速度非常快,称为“索引覆盖”

案例1,如下对name字段添加了普通索引,要查询name字段信息。

wps1A71.tmp

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

wps1A91.tmp

八、前缀索引,

利用字段数据的前部分作为索引,称为前缀索引。减少索引长度,提高索引效率。

比如:统计密码的前7个字符,作为不相同匹配条件,几乎可以做到1:1

此时,就可以利用前7个字符做索引关键字即可(离散程度高)

wps1AA2.tmp

语法:

alter table 表名 add index (passwd(7)) 指定前7位作为索引关键字。

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

wps1AA3.tmp

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

wps1AB3.tmp

wps1AC4.tmp

九、翻页优化

翻页的sql语句:

select * from table_name   limit  offset    N

使用如上语句,在翻页时,翻到最后,越来越慢,

原因:并不是跨过offset行,取出n条,

是取出offset+N条数据,舍弃前面的offset行,只取出n条数据。

wps1AD5.tmp

如何解决?

(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;语句取出的结果不一样,。

wps1AF5.tmp

(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去查具体条目,这种技巧就是延迟索引

十、碎片整理

比如建表测试:

wps1B06.tmp

数据表文件原来的容量:

wps1B16.tmp

当delete from ceshi where id=1,应该容量减去三分之一,但是并没有被删除。

需要把里面的一些碎片给释放掉。

使用optimize table 表名;或alter table 表名  engine myisam(innodb)

执行optimize table 表名,命令后,把原来的碎片空间给释放掉

wps1B27.tmp

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

如果表的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

读锁的演示:

wps1B28.tmpwps1B38.tmpwps1B49.tmp

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

wps1B5A.tmp

写锁的演示

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

wps1B5B.tmp

wps1B7B.tmp

2、行锁的演示:

是innodb支持的一种锁,在使用时,要添加条件限制是要操作哪行数据。

语法:

begin; //开始

执行语句; //要锁的行

commit; //解锁

wps1B9B.tmpwps1BAC.tmpwps1BAD.tmpwps1BAE.tmpwps1BAF.tmpwps1BBF.tmpwps1BC0.tmp

文件锁,flock_file

十二、分区分表技术

基本概念,把一个表,从逻辑上分成多个区域,便于存储数据。

采用分区的前提:数据量非常大

wps1BC1.tmp

分区的语法,在创建表时,完成分区

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)

);

wps1BE2.tmp

wps1BE3.tmp

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

wps1BF3.tmp

explain partitions select *from emp where store_id=3

测试是否用到了分区:

explain partitions select * from p_list where store_id=20\G

注意:在使用分区时,where后面的字段必须是分区字段,才能使用到分区。

wps1C04.tmp

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)

);

posted on 2016-05-08 21:32  山山未迟  阅读(143)  评论(0编辑  收藏  举报