zoukankan      html  css  js  c++  java
  • 20150324--Mysql索引优化-02

    七、索引覆盖

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

    案例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=20G

    注意:在使用分区时,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)

    );

  • 相关阅读:
    欧拉公式求四面体的体积
    欧拉公式求四面体的体积
    I
    I
    闭包传递(floyed)
    闭包传递(floyed)
    Python hypot() 函数
    Python cos() 函数
    Python atan2() 函数
    Python atan() 函数
  • 原文地址:https://www.cnblogs.com/lifushan/p/5471701.html
Copyright © 2011-2022 走看看