Mysql经常使用配置参数、存储引擎的选择及sql优化

1、存储引擎

在mysql客户端中,使用如下命令能够查看MySQL支持的引擎。html

show engines;

几个经常使用存储引擎的特色

下面咱们重点介绍几种经常使用的存储引擎并对比各个存储引擎之间的区别和推荐使用方式。mysql

特色 Myisam BDB Memory InnoDB Archive
存储限制 没有 没有 64TB 没有
事务安全   支持   支持  
锁机制 表锁 页锁 表锁 行锁 行锁
B树索引 支持 支持 支持 支持  
哈希索引     支持 支持  
全文索引 支持        
集群索引       支持  
数据缓存     支持 支持  
索引缓存 支持   支持 支持  
数据可压缩 支持       支持
空间使用 N/A 很是低
内存使用 中等
批量插入的速度 很是高
支持外键       支持  


最常使用的2种存储引擎:算法

  • Myisam是Mysql的默认存储引擎。当create建立新表时,未指定新表的存储引擎时,默认使用Myisam。每一个MyISAM在磁盘上存储成三个文件。文件名都和表名相同,扩展名分别是.frm(存储表定义)、.MYD (MYData,存储数据)、.MYI (MYIndex,存储索引)。数据文件和索引文件能够放置在不一样的目录,平均分布io,得到更快的速度。   
  • InnoDB存储引擎提供了具备提交、回滚和崩溃恢复能力的事务安全。可是对比Myisam的存储引擎,InnoDB写的处理效率差一些而且会占用更多的磁盘空间以保留数据和索引。

如何选择合适的存储引擎

选择标准能够分为:
(1)是否须要支持事务;
(2)是否须要使用热备
(3)崩溃恢复:可否接受崩溃;
(4)是否须要外键支持;sql

根据应用特色选择合适的存储引擎,对于复杂的应用系统能够根据实际状况选择多种存储引擎进行组合。

下面是经常使用存储引擎的适用环境:数据库

  1. MyISAM:默认的MySQL插件式存储引擎,它是在Web、数据仓储和其余应用环境下最常使用的存储引擎之一;拥有较高的插入,查询速度,但不支持事务。
  2. InnoDB:用于事务处理应用程序;5.5版本后Mysql的默认数据库,事务型数据库的首选引擎,支持ACID事务,支持行级锁定。
  3. Memory:全部数据置于内存的存储引擎,拥有极高的插入,更新和查询效率。可是会占用和数据量成正比的内存空间。而且其内容会在Mysql从新启动时丢失。
  4. Merge:容许MySQL DBA或开发人员将一系列等同的MyISAM表以逻辑方式组合在一块儿,并做为1个对象引用它们。对于诸如数据仓储等VLDB环境十分适合,且在超大规模数据存储时颇有用。
  5. BDB:源自Berkeley DB,事务型数据库的另外一种选择,支持COMMIT和ROLLBACK等其余事务特性。
  6. Archive :很是适合存储大量的独立的,做为历史记录的数据。由于它们不常常被读取。Archive拥有高效的插入速度,但其对查询的支持相对较差。
  7. Federated: 将不一样的Mysql服务器联合起来,逻辑上组成一个完整的数据库。很是适合分布式应用
  8. Cluster/NDB :高冗余的存储引擎,用多台数据机器联合提供服务以提升总体性能和安全性。适合数据量大,安全和性能要求高的应用。
  9. CSV: 逻辑上由逗号分割数据的存储引擎。它会在数据库子目录里为每一个数据表建立一个.CSV文件。这是一种普通文本文件,每一个数据行占用一个文本行。CSV存储引擎不支持索引。
  10. BlackHole :黑洞引擎,写入的任何数据都会消失,通常用于记录binlog作复制的中继。

2、mysql经常使用配置参数

基本配置:编程

datadir:指定mysql的数据目录位置,用于存放mysql数据库文件、日志文件等。缓存

配置示例:datadir=D:/wamp/mysqldata/Data安全

default-character-set:mysql服务器默认字符集设置。服务器

配置示例:default-character-set=utf8网络

skip-grant-tables:当忘记mysql用户密码的时候,能够在mysql配置文件中配置该参数,跳过权限表验证,不须要密码便可登陆mysql。

日志相关:

log-error:指定错误日志文件名称,用于记录当mysqld启动和中止时,以及服务器在运行过程当中发生任何严重错误时的相关信息。

配置示例:log-error="WJT-PC.err"(默认在mysql数据目录下)

log-bin:指定二进制日志文件名称,用于记录对数据形成更改的全部查询语句。

配置示例:log-bin="WJT-PC-bin.log"(默认在mysql数据目录下)

binlog-do-db:指定将更新记录到二进制日志的数据库,其余全部没有显式指定的数据库更新将被忽略,不记录在日志中。

配置示例:binlog-do-db=db_name

binlog-ignore-db:指定不将更新记录到二进制日志的数据库,其余没有显式忽略的数据库都将进行记录。

配置示例:binlog-ignore-db=db_name

若是想记录或忽略多个数据库,能够对上面两个选项分别使用屡次。

sync-binlog:指定多少次写日志后同步磁盘。

配置示例:sync-binlog=N

general-log:是否开启查询日志记录。

配置示例:general-log=1

general_log_file:指定查询日志文件名,用于记录全部的查询语句。

配置示例:general_log_file="WJT-PC.log"(默认在mysql数据目录下)

slow-query-log:是否开启慢查询日志记录。

配置示例:slow-query-log=1

slow_query_log_file:指定慢查询日志文件名称,用于记录消耗时间较长的查询语句。

配置示例:slow_query_log_file="WJT-PC-slow.log"(默认在mysql数据目录下)

long_query_time:设置慢查询的时间,超过这个时间的查询语句才记录日志。

配置示例:long_query_time=10(单位:秒)

log-slow-admin-statements:是否将慢管理语句(例如OPTIMIZE TABLE、ANALYZE TABLE和ALTER TABLE)写入慢查询日志。

存储引擎相关:

default-table-type:设置mysql的默认存储引擎。

innodb_data_home_dir:InnoDB引擎的共享表空间数据文件根目录。若没有设置,则使用mysql的datadir目录做为缺省目录。

innodb_data_file_path:单独指定共享表空间数据文件的路径与大小。数据文件的完整路径由innodb_data_home_dir与这里配置的值组合起来,文件大小以MB单位指定。

配置示例:innodb_data_home_dir=

innodb_data_file_path=ibdata1:12M;/data/mysql/mysql3306/data1/ibdata2:12M:autoextend

若是想为innodb表空间指定不一样目录下的文件,必须指定 innodb_data_home_dir =。这个例子中会在datadir下创建ibdata1,在/data/MySQL/mysql3306/data1/目录下建立ibdata2。

innodb_file_per_table:是否开启独立表空间,若开启,InnoDB将使用独立的.idb文件建立新表而不是在共享表空间中建立。

配置示例:innodb_file_per_table=1

innodb_autoinc_lock_mode:配置在向有着auto_increment列的表插入数据时,相关锁的行为。该参数有3个取值,0:tradition传统,全部的insert语 句开始的时候获得一个表级的auto_inc锁,在语句结束的时候才能释放 这个锁,影响了并发的插入。1:consecutive连续,mysql能够一次生成 几个连续的auto_inc的值,auto_inc不须要一直保持到语句结束,只要 语句获得了相应的值后就能够提早释放锁(这也是mysql的默认模式)。 2:interleaved交错,这个模式下已经没有了auto_inc锁,因此性能是最好的,可是对于同一个语句来讲它获得的auto_inc的值可能不是连续的。

配置示例:innodb_autoinc_lock_mode=1

low_priority_updates:在myisam引擎锁使用中,默认状况下写请求优先于读请求,能够经过将该参数设置为1来使myisam引擎给予读请求优先权限, 全部的insert、update、delete和lock table write语句将等待直到受影响 的表没有挂起的select或lock table read。

配置示例:low_priority_updates=0(默认配置)

max_write_lock_count:当一个myisam表的写锁定达到这个值后,mysql就暂时 将写请求优先级下降,给部分读请求得到锁的机会。

innodb_lock_wait_timeout:InnoDB锁等待超时参数,若事务在该时间内没有获 得须要的锁,则发生回滚。

配置示例:innodb_lock_wait_timeout=50(默认50秒)

max_heap_table_size:设置memory表的最大空间大小,该变量能够用来计算 memory表的max_rows值。在已有memory表上设置该参数是没有效果 的,除非重建表。

查询相关:

max_sort_length:配置对blob或text类型的列进行排序时使用的字节数(只对配置的前max_sort_length个字节进行排序,其余的被忽略)

max_length_for_sort:mysql有两种排序算法,两次传输排序和单次传输排序。当查询须要全部列的总长度不超过max_length_for_sort时,mysql使用 单次传输排序,不然使用两次传输排序。

optimizer_search_depth:在关联查询中,当须要关联的表数量超过optimizer_search_depth的时候,优化器会使用“贪婪”搜索的方式查找“最优”的关联顺序。

补充

热备:国内大部分采用的是双机热备的方式

组成双机热备的方案主要的三种方式分别为:基于共享存储(磁盘阵列)的方式,全冗余方式和复制方式。

基于共享存储(磁盘阵列)的方式

传统的单存储方式

共享存储方式主要经过磁盘阵列提供切换后,对数据完整性和连续性的保障。用户数据通常会放在磁盘阵列上,当主机宕机后,备机继续从磁盘阵列上取得原有数据。以下图所示传统的单存储方式这种方式由于使用一台存储设备,每每被业内人士称为磁盘单点故障。但通常来说存储的安全性较高。因此若是忽略存储设备故障的状况下,这种方式也是业内采用最多的热备方式。

全冗余方式

存储热备方式

全冗余方式就是双机双存储,基于单台存储的传统双机热备方式,确实存在存储单点故障的状况,为实现存储冗余,存储高可用也已经愈来愈多的被用户接受。咱们从理解上能够看出,双机热备最先是为解决服务器的计划性停机与非计划性宕机的解决方案,可是咱们没法实现存储的计划性停机与非计划性宕机带来的服务器停机,而存储做为双机热备中惟一存储数据的设备,它一旦发生故障每每会形成双机热备系统全面崩溃。存储热备方式随着科技的进步,云存储云计算发展,对于存储热备已经进入了成熟及快速发展阶段,双机热备也随着技术的进步,进入到了没有单点故障的全冗余双机热备方式。

这种方式的特色在于:

一、存储之间的数据复制不通过网络,而是由存储之间进行复制。

二、两个存储之间的复制是彻底实时的,不存在任什么时候间延时。

三、主备存储之间的切换时间小于500ms,以确保系统存储时不产生延时。

四、硬盘盘符及分区不由于主备存储之间的切换而改变。

五、服务器的切换,不影响存储之间的初始化,增量同步及数据复制。

六、某一存储设备的计划性停机,不影响整个服务器双机热备系统的工做。

七、存储设备之间使用重复数据删除技术,完成增量同步工做。

八、真正的7X24小时或切换的全冗余方案。

复制方式

数据同步方式

这种方式主要利用数据的同步方式,保证主备服务器的数据一致性。

基于数据复制的方式有多种方法,其性能和安全也不尽相同,其主要方法有如下几种:

A、单纯的文件方式的拷贝不适用于数据库等应用,由于打开的文件是不能被复制的,若是要复制必须将数据库关闭,这显然是不能够的。以文件方式的复制主要适用于WEB页的更新,FTP上传应用,对主备机数据完整性,连续性要数据同步方式求不高的状况下使用。

B、利用数据库所带有复制功能,好比SQLServer2000或2005所带的定阅复制,这种方式用户要根据本身的应用当心使用,缘由主要是:

(1)SQLServer的定阅复制会在用户表上增长字段,对那些应用软件编程要求较高,若是在应用软件端书写时未明确指定字段的用户,而使用此功能会形成应用程序没法正常工做。

(2)数据滞留,这个限制怕也是最要命的,由于SQLServer在数据传输过程当中数据并不是实时的到达主备机,而是数据先写到主机,再写到备机,如此一来,备机的数据每每来不及更新,此时若是发生切换,备机的数据将不完整,也不连续,若是用户发现已写入的数据在备机找不到,从新写入的话,则主机修复后,就会发生主备机数据严重冲突,数据库会乱掉。

(3)复杂应用切莫使用定阅复制来作双机热备,包括数据结构中存储过程的处理,触发器和序列,一旦发生冲突,修改起来很是麻烦。

(4)服务器性能下降,对于大一点的数据库,SQLServer2000或2005所带的定阅复制会形成服务器数据库运行缓慢。

总之SQLServer2000或2005所带的定阅复制主要仍是应用于数据快照服务,切莫用他来作双机热备中的数据同步。

C:硬盘数据拦截,目前国际国内,比较成熟的双机热备软件一般会使用硬盘数据拦截的技术,一般称为镜像软件即Mirror软件,这种技术当前已很是成熟,拦截的方式也不尽相同。

(1)分区拦截技术,以Pluswell热备份产品为例,他采用的是一种分区硬盘扇区拦截的技术,经过驱动级的拦截方式,将数据写往硬盘的数据提取,并首先写到备用服务器,以保证备用服务器的数据最新,而后再将数据回写到主机硬盘。这种方式将绝对保证,主备机数据库的数据彻底一致,不管发生哪一种切换,都能保证数据库的完整性与连续性。因为采用分区拦截技术,因此用户能够根据须要在一块硬盘上划分适合大小的分区来完成数据同步工做。

(2)硬盘拦截技术,以Symantec的Co-Standby为例,也是一种有效的硬盘拦截软件,他的拦截主要基于一整块硬盘,每每在硬盘初始化时须要消耗大量的时间。

3、优化目标

  1.减小 IO 次数

  IO永远是数据库最容易瓶颈的地方,这是由数据库的职责所决定的,大部分数据库操做中超过90%的时间都是 IO 操做所占用的,减小 IO 次数是 SQL 优化中须要第一优先考虑,固然,也是收效最明显的优化手段。

  2.下降 CPU 计算

  除了 IO 瓶颈以外,SQL优化中须要考虑的就是 CPU 运算量的优化了。order by, group by,distinct … 都是消耗 CPU 的大户(这些操做基本上都是 CPU 处理内存中的数据比较运算)。当咱们的 IO 优化作到必定阶段以后,下降 CPU 计算也就成为了咱们 SQL 优化的重要目标

 

优化方法

  改变 SQL 执行计划

  明确了优化目标以后,咱们须要肯定达到咱们目标的方法。对于 SQL 语句来讲,达到上述2个目标的方法其实只有一个,那就是改变 SQL 的执行计划,让他尽可能“少走弯路”,尽可能经过各类“捷径”来找到咱们须要的数据,以达到 “减小 IO 次数” 和 “下降 CPU 计算” 的目标

 

常见误区

 

1.count(1)和count(primary_key) 优于 count(*)

  不少人为了统计记录条数,就使用 count(1) 和 count(primary_key) 而不是 count(*) ,他们认为这样性能更好,其实这是一个误区。对于有些场景,这样作可能性能会更差,应为数据库对 count(*) 计数操做作了一些特别的优化。

 

2.count(column) 和 count(*) 是同样的

  这个误区甚至在不少的资深工程师或者是 DBA 中都广泛存在,不少人都会认为这是理所固然的。实际上,count(column) 和 count(*) 是一个彻底不同的操做,所表明的意义也彻底不同。

  count(column) 是表示结果集中有多少个column字段不为空的记录

  count(*) 是表示整个结果集有多少条记录

 

3.select a,b from … 比 select a,b,c from … 可让数据库访问更少的数据量

  这个误区主要存在于大量的开发人员中,主要缘由是对数据库的存储原理不是太了解。

  实际上,大多数关系型数据库都是按照行(row)的方式存储,而数据存取操做都是以一个固定大小的IO单元(被称做 block 或者 page)为单位,通常为4KB,8KB… 大多数时候,每一个IO单元中存储了多行,每行都是存储了该行的全部字段(lob等特殊类型字段除外)。

  因此,咱们是取一个字段仍是多个字段,实际上数据库在表中须要访问的数据量实际上是同样的。

  固然,也有例外状况,那就是咱们的这个查询在索引中就能够完成,也就是说当只取 a,b两个字段的时候,不须要回表,而c这个字段不在使用的索引中,须要回表取得其数据。在这样的状况下,两者的IO量会有较大差别。

 

4.order by 必定须要排序操做

  咱们知道索引数据其实是有序的,若是咱们的须要的数据和某个索引的顺序一致,并且咱们的查询又经过这个索引来执行,那么数据库通常会省略排序操做,而直接将数据返回,由于数据库知道数据已经知足咱们的排序需求了。

  实际上,利用索引来优化有排序需求的 SQL,是一个很是重要的优化手段

  延伸阅读:MySQL ORDER BY 的实现分析,MySQL 中 GROUP BY 基本实现原理以及 MySQL DISTINCT 的基本实现原理这3篇文章中有更为深刻的分析,尤为是第一篇

 

5.执行计划中有 filesort 就会进行磁盘文件排序

  有这个误区其实并不能怪咱们,而是由于 MySQL 开发者在用词方面的问题。filesort 是咱们在使用 explain 命令查看一条 SQL 的执行计划的时候可能会看到在 “Extra” 一列显示的信息。

  实际上,只要一条 SQL 语句须要进行排序操做,都会显示“Using filesort”,这并不表示就会有文件排序操做。

 

基本原则

1.尽可能少 join

  MySQL 的优点在于简单,但这在某些方面其实也是其劣势。MySQL 优化器效率高,可是因为其统计信息的量有限,优化器工做过程出现误差的可能性也就更多。对于复杂的多表 Join,一方面因为其优化器受限,再者在 Join 这方面所下的功夫还不够,因此性能表现离 Oracle 等关系型数据库前辈仍是有必定距离。但若是是简单的单表查询,这一差距就会极小甚至在有些场景下要优于这些数据库前辈。

 

2.尽可能少排序

  排序操做会消耗较多的 CPU 资源,因此减小排序能够在缓存命中率高等 IO 能力足够的场景下会较大影响 SQL 的响应时间。

  对于MySQL来讲,减小排序有多种办法,好比:

  上面误区中提到的经过利用索引来排序的方式进行优化

  减小参与排序的记录条数

  非必要不对数据进行排序

  …

3.尽可能避免 select *

  不少人看到这一点后以为比较难理解,上面不是在误区中刚刚说 select 子句中字段的多少并不会影响到读取的数据吗?

  是的,大多数时候并不会影响到 IO 量,可是当咱们还存在 order by 操做的时候,select 子句中的字段多少会在很大程度上影响到咱们的排序效率,这一点能够经过我以前一篇介绍 MySQL ORDER BY 的实现分析的文章中有较为详细的介绍。

  此外,上面误区中不是也说了,只是大多数时候是不会影响到 IO 量,当咱们的查询结果仅仅只须要在索引中就能找到的时候,仍是会极大减小 IO 量的。

 

4.尽可能用 join 代替子查询

  虽然 Join 性能并不佳,可是和 MySQL 的子查询比起来仍是有很是大的性能优点。MySQL 的子查询执行计划一直存在较大的问题,虽然这个问题已经存在多年,可是到目前已经发布的全部稳定版本中都广泛存在,一直没有太大改善。虽然官方也在很早就认可这一问题,而且承诺尽快解决,可是至少到目前为止咱们尚未看到哪个版本较好的解决了这一问题。

 

5.尽可能少 or

  当 where 子句中存在多个条件以“或”并存的时候,MySQL 的优化器并无很好的解决其执行计划优化问题,再加上 MySQL 特有的 SQL 与 Storage 分层架构方式,形成了其性能比较低下,不少时候使用 union all 或者是union(必要的时候)的方式来代替“or”会获得更好的效果。

 

6.尽可能用 union all 代替 union

  union 和 union all 的差别主要是前者须要将两个(或者多个)结果集合并后再进行惟一性过滤操做,这就会涉及到排序,增长大量的 CPU 运算,加大资源消耗及延迟。因此当咱们能够确认不可能出现重复结果集或者不在意重复结果集的时候,尽可能使用 union all 而不是 union。

 

7.尽可能早过滤

  这一优化策略其实最多见于索引的优化设计中(将过滤性更好的字段放得更靠前)。

  在 SQL 编写中一样可使用这一原则来优化一些 Join 的 SQL。好比咱们在多个表进行分页数据查询的时候,咱们最好是可以在一个表上先过滤好数据分好页,而后再用分好页的结果集与另外的表 Join,这样能够尽量多的减小没必要要的 IO 操做,大大节省 IO 操做所消耗的时间。

 

8.避免类型转换

  这里所说的“类型转换”是指 where 子句中出现 column 字段的类型和传入的参数类型不一致的时候发生的类型转换:

  人为在column_name 上经过转换函数进行转换

  直接致使 MySQL(实际上其余数据库也会有一样的问题)没法使用索引,若是非要转换,应该在传入的参数上进行转换

  由数据库本身进行转换

  若是咱们传入的数据类型和字段类型不一致,同时咱们又没有作任何类型转换处理,MySQL 可能会本身对咱们的数据进行类型转换操做,也可能不进行处理而交由存储引擎去处理,这样一来,就会出现索引没法使用的状况而形成执行计划问题。

 

9.优先优化高并发的 SQL,而不是执行频率低某些“大”SQL

  对于破坏性来讲,高并发的 SQL 老是会比低频率的来得大,由于高并发的 SQL 一旦出现问题,甚至不会给咱们任何喘息的机会就会将系统压跨。而对于一些虽然须要消耗大量 IO 并且响应很慢的 SQL,因为频率低,即便遇到,最多就是让整个系统响应慢一点,但至少可能撑一下子,让咱们有缓冲的机会。

 

10.从全局出发优化,而不是片面调整

  SQL 优化不能是单独针对某一个进行,而应充分考虑系统中全部的 SQL,尤为是在经过调整索引优化 SQL 的执行计划的时候,千万不能顾此失彼,因小失大。

 

11.尽量对每一条运行在数据库中的SQL进行 explain

  优化 SQL,须要作到心中有数,知道 SQL 的执行计划才能判断是否有优化余地,才能判断是否存在执行计划问题。在对数据库中运行的 SQL 进行了一段时间的优化以后,很明显的问题 SQL 可能已经不多了,大多都须要去发掘,这时候就须要进行大量的 explain 操做收集执行计划,并判断是否须要进行优化。

相关文章
相关标签/搜索