终于来到了这个系列的终章,到这里整个myisam引擎就介绍的七七八八了。感慨一下,下面继续。
首先从系统变量层面:
myisam最重要的配置就是
1,key_buffer_size。配置myisam表索引使用的共享内存大小,如果你的数据库较多使用了myisam引擎表,那就需要增大这个配置。这块区域类似innodb的innodb_buffer_pool,数据库对于myisam表的索引数据是共享访问的,所有的索引key都需要先通过物理读读入这个区域,然后再由各个线程来进行读写操作(如果在key buffer区域重建的时候,是线程直接读取的。)。如果设置的过小,会造成频繁的物理读或者物理写,而一个请求如果不能直接从key buffer中命中block,则整个请求时间还要加上物理读的时间,大大降低了性能。与key cache读写有关的四个状态变量:
Key_read_requests:The number of requests to read a key block from the MyISAM
key cache.线程从key cache读取的block数,可理解为逻辑读;
Key_reads:The number of physical reads of a key block from disk into the MyISAM
key cache.线程从磁盘上将block读取到key cache的block数,可理解为物理读;
Key_write_requests:The number of requests to write a key block to the MyISAM
key cache.写一个block到key cache的请求数,可理解为逻辑写;
Key_writes:The number of physical writes of a key block from the MyISAM
key cache to disk.将一个block从key cache写出到磁盘的请求数,可理解为物理写;
有这样一个隐含逻辑,即一次Key_reads必然伴随一次Key_read_requests,但是一次Key_read_requests却不一定会发生Key_reads。
key_buffer命中率=1 - (Key_reads/(Key_read_requests+Key_reads)),这个指标可以用来判断key buffer大小是否合适。通常这个指标要越大越好,最好保持在99.9%以上,如果过小,首先考虑key_buffer_size是否过小,其次考虑是否有sql性能较差,有过多不必要的读取。
https://www.percona.com/blog/2010/02/28/why-you-should-ignore-mysqls-key-cache-hit-ratio/这里提出了另外一种方法,Key_reads/Up_time观察物理读的绝对量变化趋势。个人理解,这个指标侧重于反映具体某一时间段的情况。对于结合历史基线来判断某一时刻的问题会比较有效。
2,myisam-block-size/key_block_size。这两个参数都是用来设置MYI文件块大小的,默认值1k,区别在于一个是全局设置,另外一个可以在单个索引上设置。myisam-block-size设置后,如果不单独指定key_block_size,则新建的索引块大小以myisam-block-size为准,key_block_size可以覆盖myisam-block-size的设置。通常这两个参数大小应该与操作系统物理IO块大小一致,避免read before modify问题。在我的测试中,正确设置可以提升约20%左右的性能。关于这两个参数的详细解释,可参考我的另一篇文章 我理解的myisam引擎之一 myisam表特征 。其中有详细解释。
3,bulk_insert_buffer_size。批量插入缓冲区大小。为了提升myisam写入性能,通常应该使用批量insert。同样看这里。
4,concurrent_insert。
5,delay_key_write。这个大部分文章都会提到,但是大部分都有误解。保持默认值就好,不要期待太多。同样看这里。
6,tmp_table_size。同样看这里。
7,key_cache_block_size。设置key buffer内存块大小,建议与key_block_size保持一致。
8,其他关于key cache内存设置的参数,看我理解的myisam引擎之五 MyISAM key cache实现细节
接着从使用层面来讲:
1,使用多cache池。如果有表访问特别频繁,为了将整个索引key缓存到内存中,并避免被挤出,可以考虑将表放在单独创建key的缓冲区中。
2,观察临时内存表转为临时磁盘表的比率Created_tmp_disk_tables/Created_tmp_tables。tmp_table_size:mysql内部内存中临时表大小。对用户创建的memory表不起作用。在实际使用中通常与 max_heap_table_size 是min的关系,即实际生效的值为min(tmp_table_size,max_heap_table_size )。实际使用中,当有较大数据量的group by、order by操作时,如果tmp_table_size太小,mysql会将内存临时表转为磁盘临时表,会降低性能。可以通过Created_tmp_disk_tables 和Created_tmp_tables两个status 变量观察Created_tmp_disk_tables/Created_tmp_tables比值,越小越好。
3,dynamic行格式的myisam表随着不断的插入删除更新,会产生大量碎片,其中包括了大量的link,相同的行可能link到多个地址,造成读取一条记录可能多次io,可以通过myisamchk收集此类信息,并确定是否需要调整。有关myisamchk的使用,参考我理解的MYISAM引擎之七 check、analyze、optimize、repair 与myisamchk。
4,MYISAMCHK可以根据特定索引的顺序,排序MYD中存储数据的顺序,对于大部分查询使用特定索引的情况,可提升索引顺序读性能。
5,观察table_open_cache命中率,Table_open_cache_hits/(Table_open_cache_hits+Table_open_cache_misses),可调整table_open_cache,table_open_cache_instances。
6,预留充足机器物理内存给操作系统文件缓存。myisam表数据以来操作系统文件缓存提升性能。
7,使用bulk insert或者insert values(),(),(),一次insert插入多条记录。批量大小不要太小,也不能太大。太小达不到批量的效果,太大要考虑网络传输速度。我测试通过网络的bulk到200条左右每次,在本机的最大到了1000条左右每次。
8,批量数据加载的时候,考虑disable keys,加载完成后再enable keys。只对非唯一索引有效。
9,如果不使用insert values(),(),()这种形式,那么考虑使用lock table .. write 和unlock table包裹多条insert。这是基于这样一个事实:myisam 表使用表锁,在每次insert时候都获取了表锁,insert完成后释放表锁,释放表锁前会flush index buffer到磁盘。而磁盘操作是比较慢的。如果将多个insert包裹在lock中,那么多个insert完成后只flush一次。