08mysql 优化 - 第二天 - 1

一、查询缓存

1、具体使用

什么是查询缓存?

mysql服务器提供的,用于缓存select语句结果的一种内部内存缓存系统。

如果开启了查询缓存,将所有的查询结果,都缓存起来,使用同样的select语句,再次查询时,直接返回缓存的结果即可

查看缓存设置情况,并给缓存空间设置大小:

show variables  like 'query_cache%';   //查看缓存使用情况

query_cache_size:缓存空间大小

query_cache_type:是否有开启缓存

如何开启查询缓存,并设置缓存空间大小?

在my.ini中对上边的两个变量进行配置:

 

query_cache_size=134217728

query_cache_type=1

 

配置完成,之后需要重启mysql,

查看缓存开启成功:show  variables like ‘query_cache%’;

sql语句第一次执行没有缓存,之后就有缓存了:

2、无缓存

(1)缓存失效

数据表的数据(数据有修改)有变化 或者 数据表结构(字段的增、减)有变化,则会清空全部的缓存数据,即缓存失效。

update emp set job=’123456’ where empno=123456;

上图,执行了一个update语句,导致之前存在缓存(empno=1234567)被清空了

(2)不使用缓存

sql语句有变化表达式,则不会生成/使用缓存。

例如有 时间信息、随机数等

select ename,job,now() from emp where empno=123456;

上图,在sql语句中有“时间”变化的表达式,则不使用缓存

select * from emp order by rand() limit 4;

上图,sql语句中有“随机数”的表达式,不给使用缓存

(3)生成多个缓存

生成缓存的sql语句对“空格”、“大小写”比较敏感

相同结果的sql语句,由于空格、大小写问题就会分别生成多个缓存。

注意:相同结果的sql语句,由于大小写问题会分别生成缓存:

(4)禁用缓存

sql_no_cache 不进行缓存

select  sql_no_cache  * from emp where empno=123456;

意思是当前查询结果不使用查询缓存;

3、查看缓存空间使用情况

如下图,再次使用一个缓存,并读取一次,发现缓存相关参数有变化:

二.分区技术

1、分区介绍

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

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

如果数据表的记录非常多,比如达到上亿条,数据表的活性就大大降低,数据表的运行速度就比较慢、效率低下,影响mysql数据库的整体性能,就可以采用分区解决,分区是mysql本身就支持的技术。

查看当前mysql软件是否支持分区;

show variables like '%partition%';

以上的结构,在创建(修改)表时,可以指定表,可以被分成几个区域。

利用表选项:partition 完成。

create table  table_name(

        字段信息,

    索引,

)engine myisam charser utf8

partition by 分区算法(分区字段)(

        分区选项

);

分区算法:

条件分区:list (列表) range(范围)  取模轮询(hash,key)

2、分区算法

(1)list分区

list :条件值为一个数据列表。

通过预定义的列表的值来对数据进行分割

例子:假如你创建一个如下的一个表,该表保存有全国20家分公司的职员记录,这20家分公司的编号从1到20.而这20家分公司分布在全国4个区域,如下表所示:

职员表:emp

id  name   store_id(分公司的id)

12   小宝     1

14   二宝     6

北部    1,4,5,6,17,18

南部    2,7,9,10,11,13

东部    3,12,19,20

西部    8,14,15,16



insert into emp values(12,’xiaobao’,14)

insert into emp values(15,’二bao’,17)





create table p_list(

    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 p_list where store_id=20\G

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

如下查询,没有分区条件,则会到所有的分区里面去查找,即便如此,查询效率也要比单表查询高。

(2)Range(范围)

这种模式允许将数据划分不同范围。例如可以将一个表通过月份划分成若干个分区

create table p_range(

    id int,

    name varchar(32),

    birthday date

)engine myisam charset utf8

partition by range (month(birthday))(

    partition p_1 values less than (4),

    partition p_2 values less than(7),

    partition p_3 values less than(10),

    partition p_4 values less than MAXVALUE

);

less than   小于;

MAXVALUE 可能的最大值

insert into p_range values(1,’xiaobao’,’2016-09-09’);

insert into p_range values(1,’xiaobao’,’2016-11-09’);

插入的数据如下:

分区的效果如下:

(3)Hash(哈希)

这种模式允许通过对表的一个或多个列的Hash Key进行计算,最后通过这个Hash码不同数值对应的数据区域进行分区。例如可以建立一个对表主键进行分区的表。

create table  p_hash(

        id  int,

        name varchar(20),

        birthday date

)engine myisam charset utf8

partition by hash(month(birthday)) partitions 5;

分区效果如下:

(4)Key(键值)

上面Hash模式的一种延伸,这里的Hash Key是MySQL系统产生的。

create table p_key(

    id int,

    name varchar(32),

    birthday date

)engine myisam charset utf8

partition by key (id) partitions 5;

3、 分区管理

具体就是对已经存在的分区进行增加减少操作。

(1)删除分区

删除分区:

① 在key/hash领域不会造成数据丢失(删除分区后数据会重新整合到剩余的分区去)

② 在range/list领域会造成数据丢失

 

求余方式(key/hash):

>alter table 表名 coalesce partition 数量;

范围方式(range/list):

>alter table 表名 drop partition 分区名称;

 

1)删除hash类型分区

删除分区之前,数据如下

执行删除分区的操作:alter table p_hash  coalesce partition 4

上图,把5个分表中的4个都删除,只剩下一个

剩余一个分表效果:

并且,数据没有减少:

剩余唯一一个分区的时候,就禁止删除了,但是可以drop掉整个数据表,如下图:

alter table p_hash  coalesce  partition 1;

2)删除list类型分表(数据有对应丢失)

alter table p_list drop partition   p_north;

(2)增加分区

求余方式: key/hash

> alter table 表名  add  partition partitions  数量;

范围方式: range/list

alter table 表名 add partition(

           partition 名称 values  less than (常量)

          

           partition 名称 values  in (n,n,n)

       );

 

1) 给p_hash 增加hash分表

 

alter table p_hash  add partition partitions 6;

增加后,一共有7个分表体现:

上图,分表增加好后,又把数据平均地分配给各个分表存储。

 

4、特别注意;

create table p_range2(

    id int primary key auto_increment,

    name varchar(32),

    birthday date

)engine myisam charset utf8

partition by range (month(birthday))(

    partition p_1 values less than (4),

    partition p_2 values less than(7),

    partition p_3 values less than(10),

    partition p_4 values less than MAXVALUE

);

 

注意:创建分区的字段必须是主键或唯一索引的一部分

primary key(id,birthday)

不等价于如下量行代码;

primary key(id)

primary key(birthday)

create table p_range2(

        id  int auto_increment,

        name varchar(32),

        birthday date,

        primary key(id,birthday)

)engine myisam charset utf8

partition by range (month(birthday))(

        partition p_1 values less than (4),

        partition p_2 values less than (7),

        partition p_3 values less than(10),

        partition p_4 values less than MAXVALUE

);

 

三、分表技术

1. 分表设计

物理方式分表设计

自己手动创建多个数据表出来

php程序需要考虑分表算法:数据往哪个表,从哪个表 

 

PHP程序

分表算法

分表1

分表2

分表3

 

 

 

 

 

 

 

 

 

QQ的登录表。假设QQ的用户有10亿,如果只有一张表,每个用户登录的时候数据库都要从这10亿中查找,会很慢很慢。如果将这一张表分成100份,每张表有1000万条,就小了很多,比如qq0,qq1,qq1...qq99表。

用户登录的时候,可以将用户的id%100,那么会得到0-99的数,查询表的时候,将表名qq跟取模的数连接起来,就构建了表名。比如123456789用户,取模的89,那么就到qq89表查询,查询的时间将会大大缩短。

注册时,如何存储到多张表里面?

登录时,如何知道查询那张表?

注册时

$user_id = $redis->incr(‘user_id’);

表单提交过来的内容;

$username = ‘大宝’;

假如我们要分四张表来存储;

$user_id%4 = 获取余数  

假如$user_id=8了  余数是0,那我们就存储到user_0表里面了,

user_0表里面的字段  id   $user_id    ‘大宝’

$redis->set($username_register_name,$user_id)

登录时,我们用名称来登录;

$username = ‘大宝’,如何知道该名称在那张表里面呢? 

 

$username->user_id->通过user_id算出存储的表;

2. 垂直分表(比较常用)

水平分表:是把一个表的全部记录信息分别存储到不同的分表之中。

垂直分表:是把一个表的全部字段分别存储到不同的表里边。

 

有的时候,一个数据表设计好了,里边有许多字段,但是这些字段有的是经常使用的,有的是不常用的。在进行正常数据表操作的时候,不常用的字段也会占据一定的资源,对整体操作的性能造成一定的干扰、影响。

为了减少资源的开销、提升运行效率,就可以把不常用的字段给创建到一个专门的辅表中去。

同一个业务表的不同字段分别存储到不同数据表的过程就是“垂直分表”。

例如: 

会员数据表有如下字段:

会员表: user_id  登录名  密码  邮箱  手机号码  身高  体重  性别  家庭地址  身份证号码

 

以上表,红色是常用的,蓝色的是不常用的

为了使得常用字段运行速度更快、效率更高,把常用字段给调出来,因此数据表做以下垂直分表设计:

会员表()user字段:user_id  登录名  密码  邮箱  手机号码

会员表(辅)user_fu字段:user_id  身高  体重  性别  家庭地址  身份证号码

 

以上把会员表根据字段是否常用给分为两个表的过程就是垂直分表。

存储文章

经常查询的数据     title(标题)   author(作者)   

 

 

四、数据碎片与维护

在长期的数据更改过程中,索引文件和数据文件,都将产生空洞,形成碎片,我们可以通过一个操作(不产生对数据实质影响的操作)来修改表,

建表语句:

create table t1(id int)engine myisam;

insert into t1 values(1),(2),(3)

insert into t1 select * from t1;

表的原始大小:

删除了一部分数据,应该表的容量会减少一部分,但是没有减掉,

开始整理:

optimize    table  表名;

整理后的结果,容量减少了一部分。

比如:表的引擎为innodb,可以alter table xxx engine innodb

optimize table 表名,也可以修复。

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

如果表的update,delete操作很频繁,可以按周月来修复。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值