MySQL、索引优化&参数优化

1.对查询进行优化

应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

2.应尽量避免在 where 子句中对字段进行 null 值判断,

否则将导致引擎放弃使用索引而进行全表扫描,如:

select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:

select id from t where num=0
3.应尽量避免在 where 子句中使用!=或<>操作符,否则引擎将放弃使用索引而进行全表扫描。

SELECT id FROM employee WHERE id != “B%”
4.应尽量避免在 where 子句中使用or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:

select id from t where num=10 or num=20
可以这样查询:

select id from t where num=10 union all select id from t where num=20
5.in 和 not in 也要慎用,否则会导致全表扫描,

如:select id from t where num in(1,2,3) 对于连续的数值,能用 between 就不要用 in 了:

select id from t where num between 1 and 3
6.下面的查询也将导致全表扫描:

select id from t where name like ‘李%’
若要提高效率,可以考虑全文检索。

因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然 而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:

select id from t where num=@num
可以改为强制查询使用索引:

select id from t with(index(索引名)) where num=@num
8.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:

select id from t where num/2=100

应改为:

select id from t where num=100*2

9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:

select id from t where substring(name,1,3)=’abc’

name以abc开头的id,应改为:

select id from t where name like ‘abc%’

10.不要在 where 子句中的”=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

SELECT * FROM T1 WHERE processid+11=10

11.在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。

12.不要写一些没有意义的查询,如需要生成一个空表结构:

select col1,col2 into #t from t where 1=0

这类代码不会返回任何结果集,但是会消耗系统资源的,应改成这样:

create table #t(…)
13.很多时候用 exists 代替 in 是一个好的选择:

select num from a where num in(select num from b)

用下面的语句替换:

select num from a where exists(select 1 from b where num=a.num)

14.并不是所有索引对查询都有效,

SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。

索引固然可 以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。

因为 clustered 索引数据列的顺序就是表记录的物理存储顺序,一旦该列值改变将导致整个表记录的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新 clustered 索引数据列,那么需要考虑是否应将该索引建为 clustered 索引。

17.尽量使用数字型字段,

若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

18.尽可能的使用 varchar/nvarchar 代替 char/nchar ,

因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高些。

19.任何地方都不要使用 select * from t ,用具体的字段列表代替”*”,不要返回用不到的任何字段。

select * from user
20.尽量使用表变量来代替临时表。

如果表变量包含大量数据,请注意索引非常有限(只有主键索引)。

21.避免频繁创建和删除临时表,以减少系统表资源的消耗。

22.临时表并不是不可使用,适当地使用它们可以使某些例程更有效,

例如,当需要重复引用大型表或常用表中的某个数据集时。但是,对于一次性事件,最好使用导出表。

23.在新建临时表时,

如果一次性插入数据量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果数据量不大,为了缓和系统表的资源,应先create table,然后insert。

24.如果使用到了临时表,

在存储过程的最后务必将所有的临时表显式删除,先 truncate table ,然后 drop table ,这样可以避免系统表的较长时间锁定。

25.尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。

26.使用基于游标的方法或临时表方法之前,应先寻找基于集的解决方案来解决问题,基于集的方法通常更有效。

对小型数据集使用 FAST_FORWARD 游标通常要优于其他逐行处理方法,尤其是在必须引用几个表才能获得所需的数据时。在结果集中包括”合计”的例程通常要比使用游标执行的速度快。如果开发时 间允许,基于游标的方法和基于集的方法都可以尝试一下,看哪一种方法的效果更好。

28.在所有的存储过程和触发器的开始处设置 SET NOCOUNT ON ,在结束时设置 SET NOCOUNT OFF 。无需在执行存储过程和触发器的每个语句后向客户端发送DONE_IN_PROC 消息。

29.尽量避免大事务操作,提高系统并发能力。

30.尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

MySQL性能优化之参数配置
1、目的:

通过根据服务器目前状况,修改Mysql的系统参数,达到合理利用服务器现有资源,最大合理的提高MySQL性能。

2、服务器参数:

32G内存、4个CPU,每个CPU 8核。

3、MySQL目前安装状况。

MySQL&#x76EE;&#x524D;&#x5B89;&#x88C5;&#xFF0C;&#x7528;&#x7684;&#x662F;MySQL&#x9ED8;&#x8BA4;&#x7684;&#x6700;&#x5927;&#x652F;&#x6301;&#x914D;&#x7F6E;&#x3002;&#x62F7;&#x8D1D;&#x7684;&#x662F;my-huge.cnf.&#x7F16;&#x7801;&#x5DF2;&#x4FEE;&#x6539;&#x4E3A;UTF-8.&#x5177;&#x4F53;&#x4FEE;&#x6539;&#x53CA;&#x5B89;&#x88C5;MySQL,&#x53EF;&#x4EE5;&#x53C2;&#x8003;<<linux系统上安装mysql 5.5>>&#x5E2E;&#x52A9;&#x6587;&#x6863;&#x3002;
</linux系统上安装mysql>

4、修改MySQL配置

打开MySQL配置文件my.cnf

vi /etc/my.cnf

4.1 MySQL非缓存参数变量介绍及修改

4.1.1修改back_log参数值:由默认的50修改为500.(每个连接256kb,占用:125M)

      back_log=500

back_log&#x503C;&#x6307;&#x51FA;&#x5728;MySQL&#x6682;&#x65F6;&#x505C;&#x6B62;&#x56DE;&#x7B54;&#x65B0;&#x8BF7;&#x6C42;&#x4E4B;&#x524D;&#x7684;&#x77ED;&#x65F6;&#x95F4;&#x5185;&#x591A;&#x5C11;&#x4E2A;&#x8BF7;&#x6C42;&#x53EF;&#x4EE5;&#x88AB;&#x5B58;&#x5728;&#x5806;&#x6808;&#x4E2D;&#x3002;&#x4E5F;&#x5C31;&#x662F;&#x8BF4;&#xFF0C;&#x5982;&#x679C;MySql&#x7684;&#x8FDE;&#x63A5;&#x6570;&#x636E;&#x8FBE;&#x5230;max_connections&#x65F6;&#xFF0C;&#x65B0;&#x6765;&#x7684;&#x8BF7;&#x6C42;&#x5C06;&#x4F1A;&#x88AB;&#x5B58;&#x5728;&#x5806;&#x6808;&#x4E2D;&#xFF0C;&#x4EE5;&#x7B49;&#x5F85;&#x67D0;&#x4E00;&#x8FDE;&#x63A5;&#x91CA;&#x653E;&#x8D44;&#x6E90;&#xFF0C;&#x8BE5;&#x5806;&#x6808;&#x7684;&#x6570;&#x91CF;&#x5373;back_log&#xFF0C;&#x5982;&#x679C;&#x7B49;&#x5F85;&#x8FDE;&#x63A5;&#x7684;&#x6570;&#x91CF;&#x8D85;&#x8FC7;back_log&#xFF0C;&#x5C06;&#x4E0D;&#x88AB;&#x6388;&#x4E88;&#x8FDE;&#x63A5;&#x8D44;&#x6E90;&#x3002;&#x5C06;&#x4F1A;&#x62A5;&#xFF1A;unauthenticated user | xxx.xxx.xxx.xxx | NULL | Connect | NULL | login | NULL &#x7684;&#x5F85;&#x8FDE;&#x63A5;&#x8FDB;&#x7A0B;&#x65F6;.

back_log值不能超过TCP/IP连接的侦听队列的大小。若超过则无效,查看当前系统的TCP/IP连接的侦听队列的大小命令:cat /proc/sys/net/ipv4/tcp_max_syn_backlog目前系统为1024。对于Linux系统推荐设置为小于512的整数。

查看mysql 当前系统默认back_log值,命令:

show variables like ‘back_log’; 查看当前数量

4.1.2修改wait_timeout参数值,由默认的8小时,修改为30分钟。(本次不用)

      wait_timeout=1800&#xFF08;&#x5355;&#x4F4D;&#x4E3A;&#x5999;&#xFF09;

我对wait-timeout这个参数的理解:MySQL客户端的数据库连接闲置最大时间值。

说得比较通俗一点,就是当你的MySQL连接闲置超过一定时间后将会被强行关闭。MySQL默认的wait-timeout 值为8个小时,可以通过命令show variables like ‘wait_timeout’查看结果值;。

设置这个值是非常有意义的,比如你的网站有大量的MySQL链接请求(每个MySQL连接都是要内存资源开销的 ),由于你的程序的原因有大量的连接请求空闲啥事也不干,白白占用内存资源,或者导致MySQL超过最大连接数从来无法新建连接导致”Too many connections”的错误。在设置之前你可以查看一下你的MYSQL的状态(可用show processlist),如果经常发现MYSQL中有大量的Sleep进程,则需要 修改wait-timeout值了。

interactive_timeout:服务器关闭交互式连接前等待活动的秒数。交互式客户端定义为在mysql_real_connect()中使用CLIENT_INTERACTIVE选项的客户端。

wait_timeout:服务器关闭非交互连接之前等待活动的秒数。在线程启动时,根据全局wait_timeout值或全局 interactive_timeout值初始化会话wait_timeout值,取决于客户端类型(由mysql_real_connect()的连接选项CLIENT_INTERACTIVE定义).

这两个参数必须配合使用。否则单独设置wait_timeout无效

4.1.3修改max_connections参数值,由默认的151,修改为3000(750M)。

max_connections=3000

max_connections是指MySql的最大连接数,如果服务器的并发连接请求量比较大,建议调高此值,以增加并行连接数量,当然这建立在机器能支撑的情况下,因为如果连接数越多,介于MySql会为每个连接提供连接缓冲区,就会开销越多的内存,所以要适当调整该值,不能盲目提高设值。可以过’conn%’通配符查看当前状态的连接数量,以定夺该值的大小。

MySQL服务器允许的最大连接数16384;

查看系统当前最大连接数:

show variables like ‘max_connections’;

4.1..4修改max_user_connections值,由默认的0,修改为800

 max_user_connections=800

max_user_connections是指每个数据库用户的最大连接

针对某一个账号的所有客户端并行连接到MYSQL服务的最大并行连接数。简单说是指同一个账号能够同时连接到mysql服务的最大连接数。设置为0表示不限制。

目前默认值为:0不受限制。

这儿顺便介绍下Max_used_connections:它是指从这次mysql服务启动到现在,同一时刻并行连接数的最大值。它不是指当前的连接情况,而是一个比较值。如果在过去某一个时刻,MYSQL服务同时有1000个请求连接过来,而之后再也没有出现这么大的并发请求时,则Max_used_connections=1000.请注意与show variables 里的max_user_connections的区别。默认为0表示无限大。

查看max_user_connections值

show variables like ‘max_user_connections’;

4.1.5修改thread_concurrency值,由目前默认的8,修改为64

 thread_concurrency=64

thread_concurrency的值的正确与否, 对mysql的性能影响很大, 在多个cpu(或多核)的情况下,错误设置了thread_concurrency的值, 会导致mysql不能充分利用多cpu(或多核), 出现同一时刻只能一个cpu(或核)在工作的情况。

thread_concurrency应设为CPU核数的2倍. 比如有一个双核的CPU, 那thread_concurrency 的应该为4; 2个双核的cpu, thread_concurrency的值应为8.

比如:根据上面介绍我们目前系统的配置,可知道为4个CPU,每个CPU为8核,按照上面的计算规则,这儿应为:4 _8_2=64

查看系统当前thread_concurrency默认配置命令:

show variables like ‘thread_concurrency’;

4.1.6添加skip-name-resolve,默认被注释掉,没有该参数。

skip-name-resolve

skip-name-resolve:禁止MySQL对外部连接进行DNS解析,使用这一选项可以消除MySQL进行DNS解析的时间。但需要注意,如果开启该选项,则所有远程主机连接授权都要使用IP地址方式,否则MySQL将无法正常处理连接请求!

4.1.7 skip-networking,默认被注释掉。没有该参数。(本次无用)

skip-networking建议被注释掉,不要开启

开启该选项可以彻底关闭MySQL的TCP/IP连接方式,如果WEB服务器是以远程连接的方式访问MySQL数据库服务器则不要开启该选项!否则将无法正常连接!

4.1.8 default-storage-engine(设置MySQL的默认存储引擎)

default-storage-engine= InnoDB(设置InnoDB类型,另外还可以设置MyISAM类型)

设置创建数据库及表默认存储类型

show table status like ‘tablename’显示表的当前存储状态值

查看MySQL有哪些存储状态及默认存储状态

show engines;

创建表并指定存储类型

CREATE TABLE mytable (id int, title char(20)) ENGINE = INNODB;
修改表存储类型:

Alter table tableName engine =engineName
备注:设置完后把以下几个开启:

Uncomment the following if you are using InnoDB tables

innodb_data_home_dir = /var/lib/mysql

#innodb_data_file_path = ibdata1:1024M;ibdata2:10M:autoextend&#xFF08;&#x8981;&#x6CE8;&#x91CA;&#x6389;&#xFF0C;&#x5426;&#x5219;&#x4F1A;&#x521B;&#x5EFA;&#x4E00;&#x4E2A;&#x65B0;&#x7684;&#x628A;&#x539F;&#x6765;&#x7684;&#x66FF;&#x6362;&#x7684;&#x3002;&#xFF09;

innodb_log_group_home_dir = /var/lib/mysql

You can set .._buffer_pool_size up to 50 - 80 %

of RAM but beware of setting memory usage too high

innodb_buffer_pool_size = 1000M

innodb_additional_mem_pool_size = 20M

Set .._log_file_size to 25 % of buffer pool size

innodb_log_file_size = 500M

innodb_log_buffer_size = 20M

innodb_flush_log_at_trx_commit = 0

innodb_lock_wait_timeout = 50
设置完后一定记得把MySQL安装目录地址(我们目前是默认安装所以地址/var/lib/mysql/)下的ib_logfile0和ib_logfile1删除掉。否则重启MySQL起动失败。

4.2 MySQL缓存变量介绍及修改

数据库属于IO密集型的应用程序,其主职责就是数据的管理及存储工作。而我们知道,从内存中读取一个数据库的时间是微秒级别,而从一块普通硬盘上读取一个 IO是在毫秒级别,二者相差3个数量级。所以,要优化数据库,首先第一步需要优化的就是IO,尽可能将磁盘IO转化为内存IO。本文先从MySQL数据库 IO相关参数(缓存参数)的角度来看看可以通过哪些参数进行IO优化

4.2.1全局缓存

启动MySQL时就要分配并且总是存在的全局缓存。目前有:key_buffer_size(默认值:402653184,即384M)、innodb_buffer_pool_size(默认值:134217728即:128M)、innodb_additional_mem_pool_size(默认值:8388608即:8M)、innodb_log_buffer_size(默认值:8388608即:8M)、query_cache_size(默认值:33554432即:32M)等五个。总共:560M.

这些变量值都可以通过命令如:show variables like ‘变量名’;查看到。

4.2.1.1:key_buffer_size,本系统目前为384M,可修改为400M

key_buffer_size=400M

key_buffer_size&#x662F;&#x7528;&#x4E8E;&#x7D22;&#x5F15;&#x5757;&#x7684;&#x7F13;&#x51B2;&#x533A;&#x5927;&#x5C0F;&#xFF0C;&#x589E;&#x52A0;&#x5B83;&#x53EF;&#x5F97;&#x5230;&#x66F4;&#x597D;&#x5904;&#x7406;&#x7684;&#x7D22;&#x5F15;(&#x5BF9;&#x6240;&#x6709;&#x8BFB;&#x548C;&#x591A;&#x91CD;&#x5199;)&#xFF0C;&#x5BF9;MyISAM(MySQL&#x8868;&#x5B58;&#x50A8;&#x7684;&#x4E00;&#x79CD;&#x7C7B;&#x578B;&#xFF0C;&#x53EF;&#x4EE5;&#x767E;&#x5EA6;&#x7B49;&#x67E5;&#x770B;&#x8BE6;&#x60C5;)&#x8868;&#x6027;&#x80FD;&#x5F71;&#x54CD;&#x6700;&#x5927;&#x7684;&#x4E00;&#x4E2A;&#x53C2;&#x6570;&#x3002;&#x5982;&#x679C;&#x4F60;&#x4F7F;&#x5B83;&#x592A;&#x5927;&#xFF0C;&#x7CFB;&#x7EDF;&#x5C06;&#x5F00;&#x59CB;&#x6362;&#x9875;&#x5E76;&#x4E14;&#x771F;&#x7684;&#x53D8;&#x6162;&#x4E86;&#x3002;&#x4E25;&#x683C;&#x8BF4;&#x662F;&#x5B83;&#x51B3;&#x5B9A;&#x4E86;&#x6570;&#x636E;&#x5E93;&#x7D22;&#x5F15;&#x5904;&#x7406;&#x7684;&#x901F;&#x5EA6;&#xFF0C;&#x5C24;&#x5176;&#x662F;&#x7D22;&#x5F15;&#x8BFB;&#x7684;&#x901F;&#x5EA6;&#x3002;&#x5BF9;&#x4E8E;&#x5185;&#x5B58;&#x5728;4GB&#x5DE6;&#x53F3;&#x7684;&#x670D;&#x52A1;&#x5668;&#x8BE5;&#x53C2;&#x6570;&#x53EF;&#x8BBE;&#x7F6E;&#x4E3A;256M&#x6216;384M.

怎么才能知道key_buffer_size的设置是否合理呢,一般可以检查状态值Key_read_requests和Key_reads ,比例key_reads / key_read_requests应该尽可能的低,比如1:100,1:1000 ,1:10000。其值可以用以下命令查得:show status like ‘key_read%’;

比如查看系统当前key_read和key_read_request值为:

+——————-+——-+

| Variable_name | Value |

+——————-+——-+

| Key_read_requests | 28535 |

| Key_reads | 269 |

+——————-+——-+

可知道有28535个请求,有269个请求在内存中没有找到直接从硬盘读取索引.

未命中缓存的概率为:0.94%=269/28535*100%. 一般未命中概率在0.1之下比较好。目前已远远大于0.1,证明效果不好。若命中率在0.01以下,则建议适当的修改key_buffer_size值。

MyISAM、InnoDB、MyISAM Merge引擎、InnoDB、memory(heap)、archive

4.2.1.2:innodb_buffer_pool_size(默认128M)

innodb_buffer_pool_size=1024M(1G)

innodb_buffer_pool_size:主要针对InnoDB表性能影响最大的一个参数。功能与Key_buffer_size一样。InnoDB占用的内存,除innodb_buffer_pool_size用于存储页面缓存数据外,另外正常情况下还有大约8%的开销,主要用在每个缓存页帧的描述、adaptive hash等数据结构,如果不是安全关闭,启动时还要恢复的话,还要另开大约12%的内存用于恢复,两者相加就有差不多21%的开销。假设:12G的innodb_buffer_pool_size,最多的时候InnoDB就可能占用到14.5G的内存。若系统只有16G,而且只运行MySQL,且MySQL只用InnoDB,

那么为MySQL开12G,是最大限度地利用内存了。

另外InnoDB和 MyISAM 存储引擎不同, MyISAM 的 key_buffer_size 只能缓存索引键,而 innodb_buffer_pool_size 却可以缓存数据块和索引键。适当的增加这个参数的大小,可以有效的减少 InnoDB 类型的表的磁盘 I/O 。

当我们操作一个 InnoDB 表的时候,返回的所有数据或者去数据过程中用到的任何一个索引块,都会在这个内存区域中走一遭。

可以通过 (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads) / Innodb_buffer_pool_read_requests * 100% 计算缓存命中率,并根据命中率来调整 innodb_buffer_pool_size 参数大小进行优化。值可以用以下命令查得:show status like ‘Innodb_buffer_pool_read%’;

比如查看当前系统中系统中

| Innodb_buffer_pool_read_requests | 1283826 |

| Innodb_buffer_pool_reads | 519 |

+—————————————+———+

其命中率99.959%=(1283826-519)/1283826*100% 命中率越高越好。

4.2.1.3:innodb_additional_mem_pool_size(默认8M)

innodb_additional_mem_pool_size=20M

 innodb_additional_mem_pool_size &#x8BBE;&#x7F6E;&#x4E86;InnoDB&#x5B58;&#x50A8;&#x5F15;&#x64CE;&#x7528;&#x6765;&#x5B58;&#x653E;&#x6570;&#x636E;&#x5B57;&#x5178;&#x4FE1;&#x606F;&#x4EE5;&#x53CA;&#x4E00;&#x4E9B;&#x5185;&#x90E8;&#x6570;&#x636E;&#x7ED3;&#x6784;&#x7684;&#x5185;&#x5B58;&#x7A7A;&#x95F4;&#x5927;&#x5C0F;&#xFF0C;&#x6240;&#x4EE5;&#x5F53;&#x6211;&#x4EEC;&#x4E00;&#x4E2A;MySQL Instance&#x4E2D;&#x7684;&#x6570;&#x636E;&#x5E93;&#x5BF9;&#x8C61;&#x975E;&#x5E38;&#x591A;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x662F;&#x9700;&#x8981;&#x9002;&#x5F53;&#x8C03;&#x6574;&#x8BE5;&#x53C2;&#x6570;&#x7684;&#x5927;&#x5C0F;&#x4EE5;&#x786E;&#x4FDD;&#x6240;&#x6709;&#x6570;&#x636E;&#x90FD;&#x80FD;&#x5B58;&#x653E;&#x5728;&#x5185;&#x5B58;&#x4E2D;&#x63D0;&#x9AD8;&#x8BBF;&#x95EE;&#x6548;&#x7387;&#x7684;&#x3002;

查看当前系统mysql的error日志 cat /var/lib/mysql/机器名.error 发现有很多waring警告。所以要调大为20M.

根据MySQL手册,对于2G内存的机器,推荐值是20M。

32G&#x5185;&#x5B58;&#x7684; 100M

4.2.1.4:innodb_log_buffer_size(默认8M)

innodb_log_buffer_size=20M

innodb_log_buffer_size  &#x8FD9;&#x662F;InnoDB&#x5B58;&#x50A8;&#x5F15;&#x64CE;&#x7684;&#x4E8B;&#x52A1;&#x65E5;&#x5FD7;&#x6240;&#x4F7F;&#x7528;&#x7684;&#x7F13;&#x51B2;&#x533A;&#x3002;&#x7C7B;&#x4F3C;&#x4E8E;Binlog Buffer&#xFF0C;InnoDB&#x5728;&#x5199;&#x4E8B;&#x52A1;&#x65E5;&#x5FD7;&#x7684;&#x65F6;&#x5019;&#xFF0C;&#x4E3A;&#x4E86;&#x63D0;&#x9AD8;&#x6027;&#x80FD;&#xFF0C;&#x4E5F;&#x662F;&#x5148;&#x5C06;&#x4FE1;&#x606F;&#x5199;&#x5165;Innofb Log Buffer&#x4E2D;&#xFF0C;&#x5F53;&#x6EE1;&#x8DB3;innodb_flush_log_trx_commit&#x53C2;&#x6570;&#x6240;&#x8BBE;&#x7F6E;&#x7684;&#x76F8;&#x5E94;&#x6761;&#x4EF6;(&#x6216;&#x8005;&#x65E5;&#x5FD7;&#x7F13;&#x51B2;&#x533A;&#x5199;&#x6EE1;)&#x4E4B;&#x540E;&#xFF0C;&#x624D;&#x4F1A;&#x5C06;&#x65E5;&#x5FD7;&#x5199;&#x5230;&#x6587;&#x4EF6; (&#x6216;&#x8005;&#x540C;&#x6B65;&#x5230;&#x78C1;&#x76D8;)&#x4E2D;&#x3002;&#x53EF;&#x4EE5;&#x901A;&#x8FC7;innodb_log_buffer_size &#x53C2;&#x6570;&#x8BBE;&#x7F6E;&#x5176;&#x53EF;&#x4EE5;&#x4F7F;&#x7528;&#x7684;&#x6700;&#x5927;&#x5185;&#x5B58;&#x7A7A;&#x95F4;&#x3002;

InnoDB 将日志写入日志磁盘文件前的缓冲大小。理想值为 1M 至 8M。大的日志缓冲允许事务运行时不需要将日志保存入磁盘而只到事务被提交(commit)。 因此,如果有大的事务处理,设置大的日志缓冲可以减少磁盘I/O。 在 my.cnf中以数字格式设置。

默认是8MB,系的如频繁的系统可适当增大至4MB~8MB。当然如上面介绍所说,这个参数实际上还和另外的flush参数相关。一般来说不建议超过32MB

注:innodb_flush_log_trx_commit参数对InnoDB Log的写入性能有非常关键的影响,默认值为1。该参数可以设置为0,1,2,解释如下:

0:log buffer中的数据将以每秒一次的频率写入到log file中,且同时会进行文件系统到磁盘的同步操作,但是每个事务的commit并不会触发任何log buffer 到log file的刷新或者文件系统到磁盘的刷新操作;

1:在每次事务提交的时候将log buffer 中的数据都会写入到log file,同时也会触发文件系统到磁盘的同步;

2:事务提交会触发log buffer到log file的刷新,但并不会触发磁盘文件系统到磁盘的同步。此外,每秒会有一次文件系统到磁盘同步操作。

实际测试发现,该值对插入数据的速度影响非常大,设置为2时插入10000条记录只需要2秒,设置为0时只需要1秒,而设置为1时则需要229秒。因此,MySQL手册也建议尽量将插入操作合并成一个事务,这样可以大幅提高速度。根据MySQL手册,在存在丢失最近部分事务的危险的前提下,可以把该值设为0。

4.5.1.5:query_cache_size(默认32M)

query_cache_size=40M

 query_cache_size: &#x4E3B;&#x8981;&#x7528;&#x6765;&#x7F13;&#x5B58;MySQL&#x4E2D;&#x7684;ResultSet&#xFF0C;&#x4E5F;&#x5C31;&#x662F;&#x4E00;&#x6761;SQL&#x8BED;&#x53E5;&#x6267;&#x884C;&#x7684;&#x7ED3;&#x679C;&#x96C6;&#xFF0C;&#x6240;&#x4EE5;&#x4EC5;&#x4EC5;&#x53EA;&#x80FD;&#x9488;&#x5BF9;select&#x8BED;&#x53E5;&#x3002;&#x5F53;&#x6211;&#x4EEC;&#x6253;&#x5F00;&#x4E86; Query Cache&#x529F;&#x80FD;&#xFF0C;MySQL&#x5728;&#x63A5;&#x53D7;&#x5230;&#x4E00;&#x6761;select&#x8BED;&#x53E5;&#x7684;&#x8BF7;&#x6C42;&#x540E;&#xFF0C;&#x5982;&#x679C;&#x8BE5;&#x8BED;&#x53E5;&#x6EE1;&#x8DB3;Query Cache&#x7684;&#x8981;&#x6C42;(&#x672A;&#x663E;&#x5F0F;&#x8BF4;&#x660E;&#x4E0D;&#x5141;&#x8BB8;&#x4F7F;&#x7528;Query Cache&#xFF0C;&#x6216;&#x8005;&#x5DF2;&#x7ECF;&#x663E;&#x5F0F;&#x7533;&#x660E;&#x9700;&#x8981;&#x4F7F;&#x7528;Query Cache)&#xFF0C;MySQL&#x4F1A;&#x76F4;&#x63A5;&#x6839;&#x636E;&#x9884;&#x5148;&#x8BBE;&#x5B9A;&#x597D;&#x7684;HASH&#x7B97;&#x6CD5;&#x5C06;&#x63A5;&#x53D7;&#x5230;&#x7684;select&#x8BED;&#x53E5;&#x4EE5;&#x5B57;&#x7B26;&#x4E32;&#x65B9;&#x5F0F;&#x8FDB;&#x884C;hash&#xFF0C;&#x7136;&#x540E;&#x5230;Query Cache&#x4E2D;&#x76F4;&#x63A5;&#x67E5;&#x627E;&#x662F;&#x5426;&#x5DF2;&#x7ECF;&#x7F13;&#x5B58;&#x3002;&#x4E5F;&#x5C31;&#x662F;&#x8BF4;&#xFF0C;&#x5982;&#x679C;&#x5DF2;&#x7ECF;&#x5728;&#x7F13;&#x5B58;&#x4E2D;&#xFF0C;&#x8BE5;select&#x8BF7;&#x6C42;&#x5C31;&#x4F1A;&#x76F4;&#x63A5;&#x5C06;&#x6570;&#x636E;&#x8FD4;&#x56DE;&#xFF0C;&#x4ECE;&#x800C;&#x7701;&#x7565;&#x4E86;&#x540E;&#x9762;&#x6240;&#x6709;&#x7684;&#x6B65;&#x9AA4;(&#x5982;SQL&#x8BED;&#x53E5;&#x7684;&#x89E3;&#x6790;&#xFF0C;&#x4F18;&#x5316;&#x5668;&#x4F18;&#x5316;&#x4EE5;&#x53CA;&#x5411;&#x5B58;&#x50A8;&#x5F15;&#x64CE;&#x8BF7;&#x6C42;&#x6570;&#x636E;&#x7B49;)&#xFF0C;&#x6781;&#x5927;&#x7684;&#x63D0;&#x9AD8;&#x6027;&#x80FD;&#x3002;&#x6839;&#x636E;MySQL&#x7528;&#x6237;&#x624B;&#x518C;&#xFF0C;&#x4F7F;&#x7528;&#x67E5;&#x8BE2;&#x7F13;&#x51B2;&#x6700;&#x591A;&#x53EF;&#x4EE5;&#x8FBE;&#x5230;238%&#x7684;&#x6548;&#x7387;&#x3002;

当然,Query Cache也有一个致命的缺陷,那就是当某个表的数据有任何任何变化,都会导致所有引用了该表的select语句在Query Cache中的缓存数据失效。所以,当我们的数据变化非常频繁的情况下,使用Query Cache可能会得不偿失

Query Cache的使用需要多个参数配合,其中最为关键的是query_cache_size和query_cache_type,前者设置用于缓存 ResultSet的内存大小,后者设置在何场景下使用Query Cache。在以往的经验来看,如果不是用来缓存基本不变的数据的MySQL数据库,query_cache_size一般256MB是一个比较合适的大小。当然,这可以通过计算Query Cache的命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))来进行调整。 query_cache_type可以设置为0(OFF),1(ON)或者2(DEMOND),分别表示完全不使用query cache,除显式要求不使用query cache(使用sql_no_cache)之外的所有的select都使用query cache,只有显示要求才使用query cache(使用sql_cache)。如果Qcache_lowmem_prunes的值非常大,则表明经常出现缓冲. 如果Qcache_hits的值也非常大,则表明查询缓冲使用非常频繁,此时需要增加缓冲大小;

根据命中率(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))进行调整,一般不建议太大,256MB可能已经差不多了,大型的配置型静态数据可适当调大.

可以通过命令:show status like ‘Qcache_%’;查看目前系统Query catch使用大小

| Qcache_hits | 1892463 |

| Qcache_inserts | 35627

命中率98.17%=1892463/(1892463 +35627 )*100

4.2.2局部缓存

除了全局缓冲,MySql还会为每个连接发放连接缓冲。个连接到MySQL服务器的线程都需要有自己的缓冲。大概需要立刻分配256K,甚至在线程空闲时,它们使用默认的线程堆栈,网络缓存等。事务开始之后,则需要增加更多的空间。运行较小的查询可能仅给指定的线程增加少量的内存消耗,然而如果对数据表做复杂的操作例如扫描、排序或者需要临时表,则需分配大约read_buffer_size,

sort_buffer_size,read_rnd_buffer_size,tmp_table_size 大小的内存空间. 不过它们只是在需要的时候才分配,并且在那些操作做完之后就释放了。有的是立刻分配成单独的组块。tmp_table_size 可能高达MySQL所能分配给这个操作的最大内存空间了

时需要分配 bulk_insert_buffer_size 大小的内存;执行 ALTER TABLE, OPTIMIZE TABLE, REPAIR TABLE 命令时需要分配 myisam_sort_buffer_size 大小的内存。

4.2.2.1:read_buffer_size(默认值:2097144即2M)

read_buffer_size=4M

   read_buffer_size &#x662F;MySql&#x8BFB;&#x5165;&#x7F13;&#x51B2;&#x533A;&#x5927;&#x5C0F;&#x3002;&#x5BF9;&#x8868;&#x8FDB;&#x884C;&#x987A;&#x5E8F;&#x626B;&#x63CF;&#x7684;&#x8BF7;&#x6C42;&#x5C06;&#x5206;&#x914D;&#x4E00;&#x4E2A;&#x8BFB;&#x5165;&#x7F13;&#x51B2;&#x533A;&#xFF0C;MySql&#x4F1A;&#x4E3A;&#x5B83;&#x5206;&#x914D;&#x4E00;&#x6BB5;&#x5185;&#x5B58;&#x7F13;&#x51B2;&#x533A;&#x3002;read_buffer_size&#x53D8;&#x91CF;&#x63A7;&#x5236;&#x8FD9;&#x4E00;

缓冲区的大小。如果对表的顺序扫描请求非常频繁,并且你认为频繁扫描进行得太慢,可以通过增加该变量值以及内存缓冲区大小提高其性能.

4.2.2.2:sort_buffer_size(默认值:2097144即2M)

sort_buffer_size=4M

sort_buffer_size&#x662F;MySql&#x6267;&#x884C;&#x6392;&#x5E8F;&#x4F7F;&#x7528;&#x7684;&#x7F13;&#x51B2;&#x5927;&#x5C0F;&#x3002;&#x5982;&#x679C;&#x60F3;&#x8981;&#x589E;&#x52A0;ORDER BY&#x7684;&#x901F;&#x5EA6;&#xFF0C;&#x9996;&#x5148;&#x770B;&#x662F;&#x5426;&#x53EF;&#x4EE5;&#x8BA9;MySQL&#x4F7F;&#x7528;&#x7D22;&#x5F15;&#x800C;&#x4E0D;&#x662F;&#x989D;&#x5916;&#x7684;&#x6392;&#x5E8F;&#x9636;&#x6BB5;&#x3002;&#x5982;&#x679C;&#x4E0D;&#x80FD;&#xFF0C;&#x53EF;&#x4EE5;&#x5C1D;&#x8BD5;&#x589E;&#x52A0;sort_buffer_size&#x53D8;&#x91CF;&#x7684;&#x5927;&#x5C0F;

4.2.2.3: read_rnd_buffer_size(默认值:8388608即8M)

read_rnd_buffer_size=8M

read_rnd_buffer_size 是MySql的随机读缓冲区大小。当按任意顺序读取行时(例如,按照排序顺序),将分配一个随机读缓存区。进行排序查询时,MySql会首先扫描一遍该缓冲,以避免磁盘搜索,提高查询速度,如果需要排序大量数据,可适当调高该值。但MySql会为每个客户连接发放该缓冲空间,所以应尽量适当设置该值,以避免内存开

销过大。

4.2.2.4: tmp_table_size(默认值:8388608 即:16M)

tmp_table_size=16M

tmp_table_size是MySql的heap (堆积)表缓冲大小。所有联合在一个DML指令内完成,并且大多数联合甚至可以不用临时表即可以完成。大多数临时表是基于内

存的(HEAP)表。具有大的记录长度的临时表 (所有列的长度的和)或包含BLOB列的表存储在硬盘上。如果某个内部heap(堆积)表大小超过tmp_table_size,MySQL可以根据需要自

动将内存中的heap表改为基于硬盘的MyISAM表。还可以通过设置tmp_table_size选项来增加临时表的大小。也就是说,如果调高该值,MySql同时将增加heap表的大小,可达到提高

联接查询速度的效果。

4.2.2.5:record_buffer:(默认值:)

record_buffer每个进行一个顺序扫描的线程为其扫描的每张表分配这个大小的一个缓冲区。如果你做很多顺序扫描,你可能想要增加该值。默认数值是131072

(128K)

4.2.3其它缓存:

4.2.3.1:table_cache(默认值:512)

TABLE_CACHE(5.1.3及以后版本又名TABLE_OPEN_CACHE)

table_cache指定表高速缓存的大小。每当MySQL访问一个表时,如果在表缓冲区中还有空间,该表就被打开并放入其中,这样可以更快地访问表内容。通过检查峰值时间的状态值Open_tables和Opened_tables,可以决定是否需要增加table_cache的值。如果你发现open_tables等于table_cache,并且opened_tables在不断增长,那么你就需要增加table_cache的值了(上述状态值可以使用SHOW STATUS LIKE ‘Open%tables’获得)。注意,不能盲目地把table_cache设置成很大的值。如果设置得太高,可能会造成文件描述符不足,从而造成性能不稳定或者连接失败。

SHOW STATUS LIKE ‘Open%tables’;

+—————+——-+

| Variable_name | Value |

+—————+——-+

| Open_tables | 356 |

| Opened_tables | 0 |

+—————+——-+

2 rows in set (0.00 sec)

open_tables表示当前打开的表缓存数,如果执行flush tables操作,则此系统会关闭一些当前没有使用的表缓存而使得此状态值减小;

opend_tables表示曾经打开的表缓存数,会一直进行累加,如果执行flush tables操作,值不会减小。

在mysql默认安装情况下,table_cache的值在2G内存以下的机器中的值默认时256到512,如果机器有4G内存,则默认这个值 是2048,但这决意味着机器内存越大,这个值应该越大,因为table_cache加大后,使得mysql对SQL响应的速度更快了,不可避免的会产生 更多的死锁(dead lock),这样反而使得数据库整个一套操作慢了下来,严重影响性能。所以平时维护中还是要根据库的实际情况去作出判断,找到最适合你维护的库的 table_cache值。

由于MySQL是多线程的机制,为了提高性能,每个线程都是独自打开自己需要的表的文件描 述符,而不是通过共享已经打开的.针对不同存储引擎处理的方法当然也不一样

在myisam表引擎中,数据文件的描述符 (descriptor)是不共享的,但是索引文件的描述符却是所有线程共享的.Innodb中和使用表空间类型有关,假如是共享表空间那么实际就一个数 据文件,当然占用的数据文件描述符就会比独立表空间少.

mysql手册上给的建议大小 是:table_cache=max_connections*n

n表示查询语句中最大表数, 还需要为临时表和文件保留一些额外的文件描述符。

table_cache:所有线程打开的表的数目。增大该值可以增加mysqld需要的文件描述符的数量。默认值是64.

4.2.3.2 thread_cache_size (服务器线程缓存)

thread_cache_size=64

默认的thread_cache_size=8,但是看到好多配置的样例里的值一般是32,64,甚至是128,感觉这个参数对优化应该有帮助,于是查了下:
根据调查发现以上服务器线程缓存thread_cache_size没有进行设置,或者设置过小,这个值表示可以重新利用保存在缓存中线程的数量,当断开连接时如果缓存中还有空间,那么客户端的线程将被放到缓存中,如果线程重新被请求,那么请求将从缓存中读取,如果缓存中是空的或者是新的请求,那么这个线程将被重新创建,如果有很多新的线程,增加这个值可以改善系统性能.通过比较 Connections 和 Threads_created 状态的变量,可以看到这个变量的作用。(–>表示要调整的值) 根据物理内存设置规则如下:
1G —> 8
2G —> 16
3G —> 32 >3G —> 64

mysql> show status like ‘thread%’;
+——————-+——-+
| Variable_name | Value |
+——————-+——-+
| Threads_cached | 0 |

查看开机起来数据库被连接了多少次?

mysql> show status like ‘%connection%’;
+———————-+——-+
| Variable_name | Value |
+———————-+——-+
| Connections | 1504 | –>服务启动以来,历史连接数
| Max_used_connections | 2 |
+———————-+——-+

通过连接线程池的命中率来判断设置值是否合适?命中率超过90%以上,设定合理。

(Connections – Threads_created) / Connections * 100 %

Original: https://www.cnblogs.com/wei3306/p/16214553.html
Author: N暖阳_李维宁
Title: MySQL、索引优化&参数优化

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/597146/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球