MySQL之数据库优化

Mysql数据库的优化技术mysql

对mysql优化是一个综合性的技术,主要包括程序员

•表的设计合理化(符合3NF)算法

•添加适当索引(index) [四种: 普通索引、主键索引、惟一索引unique、全文索引]sql

•分表技术(水平分割、垂直分割)数据库

•读写[写: update/delete/add]分离编程

•存储过程 [模块化编程,能够提升速度]windows

•对mysql配置优化 [配置最大并发数my.ini, 调整缓存大小 ]缓存

•mysql服务器硬件升级安全

•定时的去清除不须要的数据,定时进行碎片整理(MyISAM)服务器

数据库优化工做

对于一个以数据为中心的应用,数据库的好坏直接影响到程序的性能,所以数据库性能相当重要。通常来讲,要保证数据库的效率,要作好如下四个方面的工做:

① 数据库设计

② sql语句优化

③ 数据库参数配置

④ 恰当的硬件资源和操做系统

此外,使用适当的存储过程,也能提高性能。

这个顺序也表现了这四个工做对性能影响的大小

数据库表设计

通俗地理解三个范式,对于数据库设计大有好处。在数据库设计中,为了更好地应用三个范式,就必须通俗地理解三个范式(通

俗地理解是够用的理解,并非最科学最准确的理解):

第一范式:1NF是对属性的原子性约束,要求属性(列)具备原子性,不可再分解;(只要是关系型数据库都知足1NF)

第二范式:2NF是对记录的唯一性约束,要求记录有唯一标识,即实体的唯一性;

第三范式:3NF是对字段冗余性的约束,它要求字段没有冗余。 没有冗余的数据库设计能够作到。

可是,没有冗余的数据库未必是最好的数据库,有时为了提升运行效率,就必须下降范式标准,适当保留冗余数据。具体作法是: 在概念数据模型设计时遵照第三范式,下降范式标准的工做放到物理数据模型设计时考虑。下降范式就是增长字段,容许冗余。

☞ 数据库的分类

关系型数据库: mysql/oracle/db2/informix/sysbase/sql server

非关系型数据库: (特色: 面向对象或者集合)

NoSql数据库: MongoDB(特色是面向文档)

举例说明什么是适度冗余,或者说有理由的冗余!

上面这个就是不合适的冗余,缘由是:

在这里,为了提升学生活动记录的检索效率,把单位名称冗余到学生活动记录表里。单位信息有500条记录,而学生活动记录在

一年内大概有200万数据量。 若是学生活动记录表不冗余这个单位名称字段,只包含三个int字段和一个timestamp字段,只占用了16字节,是一个很小的表。而冗余了一个 varchar(32)的字段后则是原来的3倍,检索起来相应也多了这么多的I/O。并且记录数相差悬殊,500 VS 2000000 ,致使更新一个单位名称还要更新4000条冗余记录。因而可知,这个冗余根本就是拔苗助长。

订单表里面的Price就是一个冗余字段,由于咱们能够从订单明细表中统计出这个订单的价格,可是这个冗余是合理的,也能提高查询性能。

从上面两个例子中能够得出一个结论:

1---n 冗余应当发生在1这一方.

SQL语句优化

SQL优化的通常步骤

1.经过show status命令了解各类SQL的执行频率。

2.定位执行效率较低的SQL语句-(重点select)

3.经过explain分析低效率的SQL

4.肯定问题并采起相应的优化措施

-- select语句分类
Select
Dml数据操做语言(insert update delete)
dtl 数据事物语言(commit rollback savepoint)
Ddl数据定义语言(create alter drop..)
Dcl(数据控制语言) grant revoke
-- Show status 经常使用命令
--查询本次会话
Show session status like 'com_%'; //show session status like 'Com_select'
--查询全局
Show global status like 'com_%';
-- 给某个用户受权
grant all privileges on *.* to 'abc'@'%';
--为何这样受权 'abc'表示用户名 '@' 表示host, 查看一下mysql->user表就知道了
--回收权限
revoke all on *.* from 'abc'@'%';
--刷新权限[也能够不写]
flush privileges; 

SQL语句优化-show参数

MySQL客户端链接成功后,经过使用show [session|global] status 命令能够提供服务器状态信息。其中的session来表示当前的链接的统计结果,global来表示自数据库上次启动至今的统计结果。默认是session级别的。

下面的例子:

show status like 'Com_%';

其中Com_XXX表示XXX语句所执行的次数。

重点注意:Com_select,Com_insert,Com_update,Com_delete经过这几个参数,能够容易地了解到当前数据库的应用是以插入更新为主仍是以查询操做为主,以及各种的SQL大体的执行比例是多少。

还有几个经常使用的参数便于用户了解数据库的基本状况。

Connections:试图链接MySQL服务器的次数

Uptime:服务器工做的时间(单位秒)

Slow_queries:慢查询的次数 (默认是慢查询时间10s)

show status like 'Connections'
show status like 'Uptime'
show status like 'Slow_queries' 

如何查询mysql的慢查询时间

Show variables like 'long_query_time'; 

修改mysql 慢查询时间

set long_query_time=2 

SQL语句优化-定位慢查询

问题是: 如何从一个大项目中,迅速的定位执行速度慢的语句. (定位慢查询)

首先咱们了解mysql数据库的一些运行状态如何查询(好比想知道当前mysql运行的时间/一共执行了多少次

select/update/delete.. / 当前链接)

为了便于测试,咱们构建一个大表(400 万)-> 使用存储过程构建

默认状况下,mysql认为10秒才是一个慢查询.

修改mysql的慢查询.

show variables like 'long_query_time' ; //能够显示当前慢查询时间
set long_query_time=1 ;//能够修改慢查询时间 

构建大表->大表中记录有要求, 记录是不一样才有用,不然测试效果和真实的相差大.建立:

CREATE TABLE dept( /*部门表*/
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*编号*/
dname VARCHAR(20) NOT NULL DEFAULT "", /*名称*/
loc VARCHAR(13) NOT NULL DEFAULT "" /*地点*/
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;

CREATE TABLE emp
(empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*编号*/
ename VARCHAR(20) NOT NULL DEFAULT "", /*名字*/
job VARCHAR(9) NOT NULL DEFAULT "",/*工做*/
mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,/*上级编号*/
hiredate DATE NOT NULL,/*入职时间*/
sal DECIMAL(7,2) NOT NULL,/*薪水*/
comm DECIMAL(7,2) NOT NULL,/*红利*/
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部门编号*/
)ENGINE=MyISAM DEFAULT CHARSET=utf8 ;

CREATE TABLE salgrade
(
grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
losal DECIMAL(17,2) NOT NULL,
hisal DECIMAL(17,2) NOT NULL
)ENGINE=MyISAM DEFAULT CHARSET=utf8; 

测试数据

INSERT INTO salgrade VALUES (1,700,1200);
INSERT INTO salgrade VALUES (2,1201,1400);
INSERT INTO salgrade VALUES (3,1401,2000);
INSERT INTO salgrade VALUES (4,2001,3000);
INSERT INTO salgrade VALUES (5,3001,9999); 

为了存储过程可以正常执行,咱们须要把命令执行结束符修改delimiter $$
建立函数,该函数会返回一个指定长度的随机字符串

create function rand_string(n INT) 
returns varchar(255) #该函数会返回一个字符串
begin 
#chars_str定义一个变量 chars_str,类型是 varchar(100),默认值'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
declare chars_str varchar(100) default
'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
declare return_str varchar(255) default '';
declare i int default 0;
while i < n do 
set return_str =concat(return_str,substring(chars_str,floor(1+rand()*52),1));
set i = i + 1;
end while;
return return_str;
end 

建立一个存储过程

create procedure insert_emp(in start int(10),in max_num int(10))
begin
declare i int default 0; 
#set autocommit =0 把autocommit设置成0
set autocommit = 0; 
repeat
set i = i + 1;
insert into emp values ((start+i) ,rand_string(6),'SALESMAN',0001,curdate(),2000,400,rand());
until i = max_num
end repeat;
commit;
end 
#调用刚刚写好的函数, 1800000条记录,从100001号开始
call insert_emp(100001,4000000);

这时咱们若是出现一条语句执行时间超过1秒中,就会统计到.

若是把慢查询的sql记录到咱们的一个日志中

在默认状况下,低版本的mysql不会记录慢查询,须要在启动mysql时候,指定记录慢查询才能够

bin\mysqld.exe - -safe-mode - -slow-query-log [mysql5.5 能够在my.ini指定]

bin\mysqld.exe –log-slow-queries=d:/abc.log [低版本mysql5.0能够在my.ini指定]

该慢查询日志会放在data目录下[在mysql5.0这个版本中时放在 mysql安装目录/data/下],在 mysql5.5.19下是须要查看

my.ini 的 datadir="C:/Documents and Settings/All Users/Application Data/MySQL/MySQL Server 5.5/Data/“来肯定.

在mysql5.6中,默认是启动记录慢查询的,my.ini的所在目录为:C:\ProgramData\MySQL\MySQL Server 5.6,其中有一个配置项

slow-query-log=1

针对 mysql5.5启动慢查询有两种方法

bin\mysqld.exe - -safe-mode - -slow-query-log

也能够在my.ini 文件中配置:

[mysqld]
# The TCP/IP Port the MySQL Server will listen on
port=3306
slow-query-log 

经过慢查询日志定位执行效率较低的SQL语句。慢查询日志记录了全部执行时间超过long_query_time所设置的SQL语句。

show variables like 'long_query_time';
set long_query_time=2;

为dept表添加数据

desc dept;
ALTER table dept add id int PRIMARY key auto_increment;
CREATE PRIMARY KEY on dept(id);
create INDEX idx_dptno_dptname on dept(deptno,dname);
INSERT into dept(deptno,dname,loc) values(1,'研发部','康和盛大厦5楼501');
INSERT into dept(deptno,dname,loc) values(2,'产品部','康和盛大厦5楼502');
INSERT into dept(deptno,dname,loc) values(3,'财务部','康和盛大厦5楼503');UPDATE emp set deptno=1 where empno=100002;

****测试语句***[对emp表的记录能够为3600000 ,效果很明显慢]

select * from emp where empno=(select empno from emp where ename='研发部')

若是带上order by e.empno 速度就会更慢,有时会到1min多.

测试语句

select * from emp e,dept d where e.empno=100002 and e.deptno=d.deptno; 

查看慢查询日志:默认为数据目录data中的host-name-slow.log。低版本的mysql须要经过在开启mysql时使用- -log-slow-queries[=file_name]来配置

SQL语句优化-explain分析问题

Explain select * from emp where ename=“wsrcla”

会产生以下信息:

select_type:表示查询的类型。

table:输出结果集的表

type:表示表的链接类型

possible_keys:表示查询时,可能使用的索引

key:表示实际使用的索引

key_len:索引字段的长度

rows:扫描出的行数(估算的行数)

Extra:执行状况的描述和说明

explain select * from emp where ename='JKLOIP'

若是要测试Extra的filesort能够对上面的语句修改

explain select * from emp order by ename\G 

EXPLAIN详解

id

SELECT识别符。这是SELECT的查询序列号

id 示例

SELECT * FROM emp WHERE empno = 1 and ename = (SELECT ename FROM emp WHERE empno = 100001) \G; 

select_type

PRIMARY :子查询中最外层查询

SUBQUERY : 子查询内层第一个SELECT,结果不依赖于外部查询

DEPENDENT SUBQUERY:子查询内层第一个SELECT,依赖于外部查询

UNION :UNION语句中第二个SELECT开始后面全部SELECT,

SIMPLE

UNION RESULT UNION 中合并结果

Table

显示这一步所访问数据库中表名称

Type

对表访问方式

ALL:

SELECT * FROM emp \G

完整的表扫描 一般很差

SELECT * FROM (SELECT * FROM emp WHERE empno = 1) a ;

system:表仅有一行(=系统表)。这是const联接类型的一个特

const:表最多有一个匹配行

Possible_keys

该查询能够利用的索引,若是没有任何索引显示 null

Key

Mysql 从 Possible_keys 所选择使用索引

Rows

估算出结果集行数

Extra

查询细节信息

No tables :Query语句中使用FROM DUAL 或不含任何FROM子句

Using filesort :当Query中包含 ORDER BY 操做,并且没法利用索引完成排序,

Impossible WHERE noticed after reading const tables: MYSQL Query Optimizer

经过收集统计信息不可能存在结果

Using temporary:某些操做必须使用临时表,常见 GROUP BY ; ORDER BY

Using where:不用读取表中全部信息,仅经过索引就能够获取所需数据;

创建适当的索引

提及提升数据库性能,索引是最物美价廉的东西了。不用加内存,不用改程序,不用调sql,只要执行个正确的'create index',查询速度就可能提升百倍千倍,这可真有诱惑力。但是天下没有免费的午饭,查询速度的提升是以插入、更新、删除的速度为代价的,这些写操做,增长了大量的I/O。

是否是创建一个索引就能解决全部的问题?ename上没有创建索引会怎样?

select * from emp where ename='研发部'; 

---测试案例命令以下 (最好以 select * from emp e,dept d where e.empno=123451 )

*添加主键

ALTER TABLE emp ADD PRIMARY KEY(empno); 

*删除主键

alter table emp drop primary key; 

索引的原理说明

没有索引为何会慢?

使用索引为何会快?

索引的代价

一、磁盘占用

二、对dml(update delete insert)语句的效率影响

btree 方式检索,算法复杂度: log2N 次数

 

哪些列上适合添加索引

一、较频繁的做为查询条件字段应该建立索引

select * from emp where empno = 1; 

二、惟一性太差的字段不适合单首创建索引,即便频繁做为查询条件

select * from emp where sex = '男' 

三、更新很是频繁的字段不适合建立索引

select * from emp where logincount = 1 

四、不会出如今WHERE子句中的字段不应建立索引

索引的类型

•主键索引,主键自动的为主索引 (类型Primary)

•惟一索引 (UNIQUE)

•普通索引 (INDEX)

•全文索引 (FULLTEXT) [适用于MyISAM] ——》sphinx + 中文分词 coreseek [sphinx 的中文版 ]

•综合使用=>复合索引

简述mysql四种索引的区别

lPRIMARY 索引 =》在主键上自动建立

lUNIQUE 索引=> 只要是UNiQUE 就是Unique索引.(只能在字段内容不重复的状况下,才能建立惟一索引)

lINDEX 索引=>就是普通索引

lFULLTEXT => 只在MYISAM 存储引擎支持, 目的是全文索引,在内容系统中用的多, 在全英文网站用多(英文词独立). 中文数据不经常使用,意义不大,国内全文索引一般使用 sphinx来完成,全文索引只能在 char varchar text字段建立.

全文索引案例

1.建立表

create table news(id int , title varchar(32),con varchar(1024)) engine=MyISAM; 

2.创建全文索引

create fulltext index ful_inx on news (con); 

3.插入数据

这里要注意,对于常见的英文 fulltext 不会匹配,并且插入的语句自己是正确的.

'but it often happens that they are not above supporting themselves by dishonest means.which should be more disreputable.Cultivate poverty like a garden herb'

4.看看匹配度

mysql> select match(con) against('poverty') from news;
+-------------------------------+
| match(con) against('poverty') |
+-------------------------------+
| 0 |
| 0 |
| 0 |
| 0.9853024482727051 |
+------------------------------+ 

0表示没有匹配到,或者你的词是中止词,是不会创建索引的.

使用全文索引,不能使用like语句,这样就不会使用到全文索引了.

复合索引

create index 索引名 on 表名(列1,列2); 

索引的使用

创建索引

create [UNIQUE|FULLTEXT] index index_name on tbl_name (col_name [(length)] [ASC | DESC] , …..);
alter table table_name ADD INDEX [index_name] (index_col_name,...) 
添加主键(索引) ALTER TABLE 表名 ADD PRIMARY KEY(列名,..); 联合主键

删除索引

DROP INDEX index_name ON tbl_name;
alter table table_name drop index index_name; 
删除主键(索引)比较特别: alter table t_b drop primary key;

查询索引(都可)

show index(es) from table_name;
show keys from table_name;
desc table_Name; 

修改索引,咱们通常是先删除在从新建立.

查询要使用索引最重要的条件是查询条件中须要使用索引。

下列几种状况下有可能使用到索引:

1,对于建立的多列索引,只要查询条件使用了最左边的列,索引通常就会被使用。

2,对于使用like的查询,查询若是是 '%aaa' 不会使用到索引, 'aaa%' 会使用到索引。

下列的表将不使用索引:

1,若是条件中有or,即便其中有条件带索引也不会使用。

2,对于多列索引,不是使用的第一部分,则不会使用索引。

3,like查询是以%开头

4,若是列类型是字符串,那必定要在条件中将数据使用引号引用起来。不然不使用索引。(添加时,字符串必须'')

5,若是mysql估计使用全表扫描要比使用索引快,则不使用索引。

测试案例(就在前面的dept表上作演示.)

CREATE TABLE dept(
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
dname VARCHAR(20) NOT NULL DEFAULT "",
loc VARCHAR(13) NOT NULL DEFAULT ""
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ; 
--放入数据,前面应该已经添加了,若是没有则须要从新添加
--测试开始.

添加一个主键索引

alter table dept add primary key (deptno) 

--测试语句

explain select * from dept where deptno=1; 

结果是:

mysql> explain select * from dept where deptno=1;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: dept
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 3
ref: const
rows: 1
Extra:
1 row in set (0.00 sec) 

--建立多列索引

alter table dept add index myind (dname,loc); 

--证实对于建立的多列索引,只要查询条件使用了最左边的列,索引通常就会被使用

explain select * from dept where dname='研发部'; 会显示使用到了索引myind
explain select * from dept where loc='MsBDpMRX'; 不会显示使用到了索引myind

--对于使用like的查询

explain select * from dept where dname like '%研发部'; 不会显示使用到了索引myind
explain select * from dept where dname like '研发部%'; 会显示使用到了索引myind

--若是条件中有or,即便其中有条件带索引也不会使用

--为了演示,咱们把复合索引删除,而后只在dname上加入索引.

alter table dept drop index myind
alter table dept add index myind (dname)
explain select * from dept where dname='研发部' or loc='aa';-- 就不会使用到dname列上的 

--若是列类型是字符串,那必定要在条件中将数据使用引号引用起来。不然不使用索引

select * from dept from dname=1234; //不会使用到索引
select * from dept from dname='1234'; //会使用到索引

查看索引的使用状况

show status like 'Handler_read%';

你们能够注意:

handler_read_key:这个值越高越好,越高表示使用索引查询到的次数。

handler_read_rnd_next:这个值越高,说明查询低效。

* 这时咱们会看到handler_read_rnd_next值很高,为何,这是由于咱们前面没有加索引的时候,作过屡次查询的缘由.

经常使用SQL优化

大批量插入数据(MySql管理员) 了解

对于MyISAM:

alter table table_name disable keys;
loading data//insert语句;
alter table table_name enable keys; 

对于Innodb:

1,将要导入的数据按照主键排序

2,set unique_checks=0,关闭惟一性校验。

3,set autocommit=0,关闭自动提交。

优化group by 语句

默认状况,MySQL对全部的group by col1,col2进行排序。这与在查询中指定order by col1, col2相似。若是查询中包括group by但用户想要避免排序结果的消耗,则可使用order by

null禁止排序

有些状况下,可使用链接来替代子查询。

由于使用join,MySQL不须要在内存中建立临时表。(讲解)

若是想要在含有or的查询语句中利用索引,则or之间的每一个条件列都必须用到索引,若是没有索引,则应该考虑增长索引(与环境相关 讲解)

select * from 表名 where 条件1='' or 条件2='tt'
explaine select * from dept group by dname; =>这时显示 extra: using filesort 说明会进行排序
explaine select * from dept group by dname order by null =>这时不含有显示 extra: using filesort 说明不会进行排序

***有些状况下,可使用链接来替代子查询。由于使用join,MySQL不须要在内存中建立临时表

explain select * from emp , dept where emp.deptno=dept.deptno;

和下面比较就能够说明问题!!

explain select * from emp left join dept on emp.deptno=dept.deptno;

选择合适的存储引擎

MyISAM:默认的MySQL存储引擎。若是应用是以读操做和插入操做为主,只有不多的更新和删除操做,而且对事务的完整性要求不是很高。其优点是访问的速度快。

InnoDB:提供了具备提交、回滚和崩溃恢复能力的事务安全。可是对比MyISAM,写的处理效率差一些而且会占用更多的磁盘空间。

Memory:数据存在内存中,服务重启时,数据丢失

MyISAM: 在插入数据时,默认放在最后. ,删除数据后,空间不回收.(不支持事务和外键)

InnoDB 支持事务和外键

对应咱们程序员说,经常使用的存储引擎主要是 myisam / innodb / memory,heap 表

若是选用小原则:

1.若是追求速度,不在意数据是否一直把保存,也不考虑事务,请选择 memory 好比存放用户在线状态.

2.若是表的数据要持久保存,应用是以读操做和插入操做为主,只有不多的更新和删除操做,而且对事务的完整性要求不是很高。选用MyISAM

3.若是须要数据持久保存,并提供了具备提交、回滚和崩溃恢复能力的事务安全,请选用Innodb

选择合适的数据类型

在精度要求高的应用中,建议使用定点数来存储数值,以保证结果的准确性。deciaml 不要用float

对于存储引擎是MyISAM的数据库,若是常常作删除和修改记录的操做,要定时执行optimize table table_name;功能对表进行碎片整理。

日期类型要根据实际须要选择可以知足应用的最小存储的早期类型

create table bbs(id int ,con varchar(1024) , pub_time int);
date('Ymd',时间-3*24*60*60); 2038年-1-19

对于使用浮点数和定点数的案例说明

create table temp1( t1 float(10,2), t2 decimal(10,2));
insert into temp1 values(1000000.32,1000000,32); 发现 t1 成了 1000000.31 因此有问题.

对于optimize table 表名 演示

create table temp2( id int) engine=MyISAM;
insert into temp2 values(1); insert into temp2 values(2); insert into temp2 values(3);
insert into temp2 select * from temp2;--复制
delete from temp2 where id=1; 发现 该表对于的数据文件没有变小

按期执行 optimize table temp2 发现表大小变化,碎片整理完毕

&&对于InnoDB它的数据会存在data/ibdata1目录下,在data/数据库/只有一个 *.frm表结构文件.

 

对表进行水平划分          

若是一个表的记录数太多了,好比上千万条,并且须要常常检索,那么咱们就有必要化整为零了。若是我拆成100个表,那么每一个表只有10万条记录。固然这须要数据在逻辑上能够划分。一个好的划分依据,有利于程序的简单实现,也能够充分利用水平分表的优点。好比系统界面上只提供按月查询的功能,那么把表按月拆分红12个,每一个查询只查询一个表就够了。若是非要按照地域来分,即便把表拆的再小,查询仍是要联合全部表来查,还不如不拆了。因此一个好的拆分依据是 最重要的。关键字:UNION

例:

  • 订单表根据订单产生时间来分表(一年一张)
  • 学生状况表
  • 查询电话费,近三个月的数据放入一张表,一年内的放入到另外一张表

对表进行垂直划分 

有些表记录数并很少,可能也就二、3万条,可是字段却很长,表占用空间很大,检索表时须要执行大量I/O,严重下降了性能。这个时候须要把大的字段拆分到另外一个表,而且该表与原表是一对一的关系。 (JOIN)       

【试题内容】、【答案信息】两个表,最初是做为几个字段添加到【试题信息】里的,能够看到试题内容和答案这两个字段很长,在表里有3万记录时,表已经占 了1G的空间,在列试题列表时很是慢。通过分析,发现系统不少时候是根据【册】、【单元】、类型、类别、难易程度等查询条件,分页显示试题详细内容。而每 次检索都是这几个表作join,每次要扫描一遍1G的表。咱们彻底能够把内容和答案拆分红另外一个表,只有显示详细内容的时候才读这个大表,由此 就产生了【试题内容】、【答案信息】两个表。

选择适当的字段类型,特别是主键     

选择字段的通常原则是保小不保大,能用占用字节小的字段就不用大字段。好比主键, 建议使用自增类型,这样省空间,空间就是效率!按4个字节和按32个字节定位一条记录,谁快谁慢太明显了。涉及到几个表作join时,效果就更明显了。

文件、图片等大文件用文件系统存储

数据库只存储路径。图片和文件存放在文件系统,甚至单独放在一台服务器(图床 / 视频服务器 ).

数据库参数配置

最重要的参数就是内存,咱们主要用的innodb引擎,因此下面两个参数调的很大

innodb_additional_mem_pool_size = 64M
innodb_buffer_pool_size =1G

对于myisam,须要调整key_buffer_size,固然调整参数仍是要看状态,用show status语句能够看到当前状态,以决定改调整哪些参数

在my.ini修改端口3306,默认存储引擎和最大链接数

在my.ini中.
port=3306 [有两个地方修改]
default-storage-engine=INNODB 
max_connections=100

合理的硬件资源和操做系统

若是你的机器内存超过4G,那么毋庸置疑应当采用64位操做系统和64位mysql 5.5.19 or mysql5.6

读写分离

    若是数据库压力很大,一台机器支撑不了,那么能够用mysql复制实现多台机器同步,将数据库的压力分散。

    Master
  Slave1
  Slave2
  Slave3

主库master用来写入,slave1—slave3都用来作select,每一个数据库分担的压力小了不少。
要实现这种方式,须要程序特别设计,写都操做master,读都操做slave,给程序开发带来了额外负担。固然目前已经有中间件来实现这个代理,对程 序来读写哪些数据库是透明的。官方有个mysql-proxy,可是仍是alpha版本的。新浪有个amobe for mysql,也可达到这个目的,结构以下

定时完成数据库的备份

项目实际需求,请完成定时备份某个数据库,或者定时备份数据库的某些表的操做

windows 下每隔1小时,备份一次数据newsdb

windows 天天晚上2:00   备份 newsdb 下 某一张表

cmd> mysqldump –u root –p密码  数据库名 > 把数据库放入到某个目录

案例,备份 mydb 库的全部表

进入mysqldump所在的目录

cmd> mysqldump –u root –phsp shop> d:/shop.log   [把shop数据库的全部表所有导出]

cmd> mysqldump –u root –phsp shop temusers emp > d:/shop2.log [shop数据库的 temusers和emp导出]

如何恢复数据的表

进入的mysql操做界面

mysql>source  备份文件的全路径

定时备份:(把命令写入到my.bat 问中)

windows 如何定时备份 (天天凌晨2:00)

使用windows自带的计划任务,定时执行批处理命令。

增量备份和还原

定义:mysql数据库会以二进制的形式,自动把用户对mysql数据库的操做,记录到文件,当用户但愿恢复的时候,可使用备份文件进行恢复。

增量备份会记录dml语句、建立表的语句,不会记录select。记录的东西包括:sql语句自己、操做时间,位置

进行增量备份的步骤和恢复

注意:mysql5.0及以前的版本是不支持增量备份的

一、配置my.ini文件或者my.conf,启用二进制备份。

打开my.ini文件,查找log-bin,进行配置:log-bin=G:\Database\mysqlbinlog\mylog

在G:\Database目录下面新建目录mysqlbinlog

二、重启mysql服务

这个时候会在mysqlbinlog目录下面看到如下两个文件:

mylog.000001:日志备份文件。若是要查看这个日志文件里面的信息,咱们可使用mysqlbinlog程序查看,mysqlbinlog程序存放在mysql的bin目录下面(“C:\Program Files\MySQL\MySQL Server 5.6\bin”)。

执行sql语句

UPDATE emp set ename='zouqj' where empno=100003;

开始——运行——cmd,mysqlbinlog 备份文件路径

C:\Program Files\MySQL\MySQL Server 5.6\bin>mysqlbinlog G:\Database\mysqlbinlog\mylog.000001

mylog.index:日志索引文件,里面记录了因此的日志文件。(G:\Database\mysqlbinlog\mylog.000001)

三、假设如今问题来了,我这条update是误操做,如何进行恢复

在mysql日志中会记录每一次操做的时间和位置,因此咱们既能够根据时间来恢复,也能够根据位置来恢复。

那么,咱们如今立刻能够从上图看出,这条语句产生的时间是"2016-04-17 12:01:36",位置是614

按时间来恢复

咱们能够选择在语句产生时间的前一秒

执行cmd命令:mysqlbinlog --stop-datetime="2016-04-17 12:01:35" G:\Database\mysqlbinlog\mylog.000001 | mysql -uroot -p

这个时候我再执行SQL语句查看

SELECT * from emp where empno=100003;

结果变成了

按位置来恢复

执行cmd命令:mysqlbinlog --stop-position="614" G:\Database\mysqlbinlog\mylog.000001 | mysql -uroot -p

这个时候再执行SQL来查看结果,又变回来了。

 

MySQL 增量备份与还原

相关文章
相关标签/搜索