Mysql性能优化二

接上一篇Mysql性能优化一html

创建适当的索引     

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

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

UPDATE emp set ename='zhangsan' where empno=100002;
select
* from emp where ename='zhangsan';

我emp表中有2446297条记录,empno建立索引前,执行查询花了16秒钟,进行了全表扫描算法

explain SELECT * from emp where empno=100002;

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

*添加主键数据库

ALTER TABLE emp ADD PRIMARY KEY(empno);

再执行查询,执行时间显示0,用explain分析安全

*删除主键性能优化

alter table emp drop primary key;

索引的原理说明     

没有索引为何会慢?app

使用索引为何会快?post

btree类型的索引,就是使用的二分查找法,确定快啊,算法复杂度是log2N,也就是说16条数据查4次,32条数据查5次,64条数据查6次....依次类推。

使用索引跟没使用索引的区别,就跟咱们使用新华字典查字,一个是根据拼音或者笔画查找,一个是从头至尾一页一页翻。

索引的代价

一、磁盘占用

二、对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四种索引的区别

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

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

INDEX 索引=>就是普通索引

FULLTEXT => 只在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'

explain select * from dept group by dname; =>这时显示 extra: using filesort 说明会进行排序

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

InnoDB:Mysql5.6默认的MySQL存储引擎,提供了具备提交、回滚和崩溃恢复能力的事务安全。可是对比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表结构文件.

相关文章
相关标签/搜索