欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MySQL数据库优化方法

程序员文章站 2022-06-02 12:17:19
...

一、表类型MyISAM 和 InnoDB的区别

作者:Oscarwin
链接:https://www.zhihu.com/question/20596402/answer/211492971
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

区别:

1. InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;

2. InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;

3. InnoDB是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而MyISAM是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。

4. InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;

5. Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;

 

如何选择:

1. 是否要支持事务,如果要请选择innodb,如果不需要可以考虑MyISAM;

2. 如果表中绝大多数都只是读查询,可以考虑MyISAM,如果既有读写也挺频繁,请使用InnoDB。

3. 系统奔溃后,MyISAM恢复起来更困难,能否接受;

4. MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM),说明其优势是有目共睹的,如果你不知道用什么,那就用InnoDB,至少不会差。

 

二、数据表的优化

一般来说数据表越小,执行查询的速度就越快。

1、垂直拆分。就是把一个表的字段拆分成多个表。例如文章或新闻表中,放置内容的字段通常非常大,那么就可以将内容字段拆分开来,放到一张表中。在查询的时候可以使用join查询。

2.水平拆分。就是按行拆分表,例如用户表,假定一个表中只存放一百万条数据,当用户数量每多一百万时就新建一张表。

3、字段设置。例如能设置成NOT NULL就不要保持默认的NULL,当执行查询的时候,数据库就不用去比较NULL值,从而提高效率;变长类型长度设置够用就好,比如能设置成varchar(20)的就不要设置成varchar(200);对于某些只有固定几个值可选的字段,例如“状态”,“性别”等,可以将它们定义为tinyint或int类型,因为在MySQL中,数值型数据被处理起来的速度要比文本类型快得多。

三、SQL语句优化

1、对查询进行优化,主要是尽量避免执行全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

2、MySQL只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及LIKE 'ABC%'类型的LIKE语句;!=,<>操作符,将使引擎放弃使用索引而进行全表扫描。

3、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描。

4、应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,可以使用UNION 操作符合并两个或多个 SELECT 语句的结果集

5、作用LIKE '%ABC'或LIKE '%ABC%'类型的查询也将导致全表扫描。若要提高效率,可以考虑使用全文检索,在MySQL5.6以下只有MyISAM类型的表支持,在MySQL5.6以上Innodb引擎表也提供支持全文检索,语句格式:

SELECT * FROM tab_name 
WHERE MATCH (列名1,列名2...列名n) 
AGAINST('词1 词2 词3 ... 词m'[ IN NATURAL LANGUAGE MODE| IN BOOLEAN MODE]);
方括号[]里的内容表示可选内容,自然语言检索: IN NATURAL LANGUAGE MODE,布尔检索: IN BOOLEAN MODE,查询扩展检索: WITH QUERY EXPANSION。要执行查询前先分别建立全文索引(FULLTEXT索引)在(列名1,列名2...列名n)上
搜索语法规则:
         +   一定要有(不含有该关键词的数据条均被忽略)。
         -   不可以有(排除指定关键词,含有该关键词的均被忽略)。 
         >   提高该条匹配数据的权重值。
         <   降低该条匹配数据的权重值。
         ~   将其相关性由正转负,表示拥有该字会降低相关性(但不像 - 将之排除),只是排在较后面权重值降低。
         *   万用字,不像其他语法放在前面,这个要接在字符串后面。
         " " 用双引号将一段句子包起来表示要完全相符,不可拆字。
 
6.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
7、不要使用 select * from table ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
8。避免频繁创建和删除临时表,以减少系统表资源的消耗。
9、尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
10、尽量避免大事务操作,提高系统并发能力。
 
11、Update 语句,如果只更改1、2个字段,不要Update全部字段,否则频繁调用会引起明显的性能消耗,同时带来大量日志。
12、对于多张大数据量(这里几百条就算大了)的表JOIN,要先分页再JOIN,否则逻辑读会很高,性能很差。
13、select count(*) from table;这样不带任何条件的count会引起全表扫描,并且没有任何业务意义,是一定要杜绝的。