MySQL database performance optimization, the first article of cache parameter optimization
The most frequently asked question is about MySQL database performance optimization, so I recently planned to write a series of articles on MySQL database performance optimization . I hope that those who are interested in the junior and intermediate MySQL DBAs and other friends who are interested in MySQL performance optimization will have Helped.
This is the first article of the MySQL database performance optimization topic series: MySQL database performance optimization cache parameter optimization
The database is an IO-intensive application, and its main responsibility is data management and storage. And we know that the time to read a database from memory is at the level of microseconds, while reading an IO from an ordinary hard disk is at the level of milliseconds. The difference between the two is 3 orders of magnitude. Therefore, to optimize the database, the first step that needs to be optimized is IO, as much as possible to convert disk IO into memory IO. This article first looks at which parameters can be used to optimize IO from the perspective of MySQL database IO related parameters (cache parameters) :
- query_cache_size/query_cache_type (global)
Query cache acts on the entire MySQL Instance and is mainly used to cache the ResultSet in MySQL, which is the result set of a SQL statement execution, so it can only be used for select statements. When we turn on the Query Cache function, after MySQL receives a request for a select statement, if the statement meets the requirements of Query Cache (not explicitly stated that Query Cache is not allowed, or that the use of Query Cache has been explicitly stated), MySQL It will directly hash the received select statement as a string according to the preset HASH algorithm, and then directly check whether it has been cached in the Query Cache. In other words, if it is already in the cache, the select request will directly return the data, thereby omitting all subsequent steps (such as SQL statement parsing, optimizer optimization, and requesting data from the storage engine, etc.), which greatly improves performance.
Of course, Query Cache also has a fatal flaw, that is, any change in the data of a table will cause all select statements that reference the table to invalidate the cached data in the Query Cache. Therefore, when our data changes very frequently, the use of Query Cache may outweigh the gains.
The use of Query Cache requires the cooperation of multiple parameters. The most important of which is query_cache_size and query_cache_type. The former sets the memory size for caching the ResultSet, and the latter sets the context in which Query Cache is used. In the past experience, if it is not a MySQL database for caching basically unchanged data, query_cache_size is generally 256MB is a more appropriate size. Of course, this can be adjusted by calculating the hit rate of Query Cache (Qcache_hits/(Qcache_hits+Qcache_inserts)*100)). The query_cache_type can be set to 0 (OFF), 1 (ON) or 2 (DEMOND), respectively, which means that the query cache is not used at all. All the selects except the explicit request not to use the query cache (using sql_no_cache) use the query cache. Use query cache (using sql_cache) only if required for display.
- binlog_cache_size (global)
Binlog Cache is used in the environment where the binary log (binlog) recording function is turned on. It is a memory area designed by MySQL to improve the efficiency of binlog recording and temporarily cache binlog data in a short time.
Generally speaking, if there are no big transactions in our database and writes are not particularly frequent, 2MB to 4MB is a suitable choice. But if our database has a lot of big transactions and writes a lot, we can increase binlog_cache_size appropriately. At the same time, we can use binlog_cache_use and binlog_cache_disk_use to analyze whether the set binlog_cache_size is sufficient, and whether a large amount of binlog_cache is cached using temporary files (binlog_cache_disk_use) due to insufficient memory size.
- key_buffer_size (global)
Key Buffer may be the most familiar MySQL cache parameter, especially when MySQL does not change the default storage engine, many friends may find that this parameter is the largest memory parameter set in the default MySQL configuration file. The key_buffer_size parameter is used to set the size of the memory area used to cache index files in the MyISAM storage engine. If we have enough memory, this cache area should be able to store all the indexes of all our MyISAM engine tables to improve performance as much as possible.
In addition, when we use MyISAM storage, there is an extremely important point to note. Due to the characteristics of the MyISAM engine, it only caches index blocks into memory, not table database blocks. Therefore, our SQL must make the filter conditions in the index as much as possible, so that the cache can help us improve query efficiency.
- bulk_insert_buffer_size (thread)
Like key_buffer_size, this parameter also only applies to the MyISAM storage engine, which is used to temporarily cache write data when inserting data in batches. When we use the following types of data write statements, this memory area will be used to cache the data of the batch structure to help batch write data files:
insert… select…
insert… values (…) ,(…),(…)…
load data infile… into… (non-empty table) - innodb_buffer_pool_size (global)
When we use the InnoDB storage engine, the innodb_buffer_pool_size parameter may be the most critical parameter that affects our performance. It is used to set the size of the memory area used to cache InnoDB indexes and data blocks, similar to the key_buffer_size parameter of the MyISAM storage engine. Of course, it may be more like Oracle's db_cache_size. Simply put, when we operate an InnoDB table, all the returned data or any index block used in the process of data removal will go through this memory area.
Like key_buffer_size for the MyISAM engine, innodb_buffer_pool_size sets the size of the memory area that the InnoDB storage engine needs the most, which is directly related to the performance of the InnoDB storage engine. So if we have enough memory, we can set this parameter to a sufficient size. As many InnoDB indexes and data are put into this cache area, up to all.
We can calculate the cache hit rate by (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads)/Innodb_buffer_pool_read_requests * 100%, and adjust the innodb_buffer_pool_size parameter size for optimization based on the hit rate.
- innodb_additional_mem_pool_size (global)
We may not usually adjust this parameter too much. Many people use the default value. Maybe many people are not too familiar with the function of this parameter. innodb_additional_mem_pool_size sets the size of the memory space used by the InnoDB storage engine to store data dictionary information and some internal data structures, so when we have a lot of database objects in a MySQL Instance, we need to adjust the size of this parameter appropriately to ensure that all data is Can be stored in memory to improve access efficiency.
It is easy to know whether the size of this parameter is sufficient, because when it is too small, MySQL will record Warning information in the error log of the database. At this time, you know it is time to adjust the size of this parameter.
- innodb_log_buffer_size (global)
This is the buffer used by the InnoDB storage engine's transaction log. Similar to Binlog Buffer, when InnoDB writes the transaction log, in order to improve performance, it also writes the information to the Innofb Log Buffer first, and only after the corresponding conditions set by the innodb_flush_log_trx_commit parameter (or the log buffer is full) Logs are written to files (or synchronized to disk). The maximum memory space that can be used can be set through the innodb_log_buffer_size parameter.
Note: The innodb_flush_log_trx_commit parameter has a very critical impact on the write performance of InnoDB Log. This parameter can be set to 0, 1, 2, and the explanation is as follows:0: The data in the log buffer will be written to the log file at a frequency of once per second, and the file system will be synchronized to the disk at the same time, but the commit of each transaction will not trigger any log buffer to log file. Refresh or file system to disk refresh operation;
1: The data in the log buffer will be written to the log file every time a transaction is committed, and it will also trigger the synchronization of the file system to the disk;
2: Transaction commit will trigger the log The flush from buffer to log file does not trigger the synchronization of the disk file system to the disk. In addition, there will be a file system to disk synchronization operation every second.In addition, the MySQL documentation also mentions that the synchronization once per second mechanism in these settings may not completely ensure that synchronization will occur every second at a very accurate rate. It also depends on process scheduling issues. In fact, whether InnoDB can really meet the meaning of the value set by this parameter. Normal Recovery is still limited by the file system under different OSs and the disk itself. It may sometimes tell mysqld that it has been synchronized without actually completing the disk synchronization. Disk synchronization is completed.
- innodb_max_dirty_pages_pct (global)
This parameter is different from the above parameters. It is not a parameter used to set the memory size used to cache certain data, but to control the proportion of Dirty Pages in the InnoDB Buffer Pool that do not need to be written to the data file ( Dirty data that has been repaired but has not been written to the data file from memory). The larger this ratio is, the write operations from memory to disk will be relatively reduced, so disk IO for write operations can be reduced to a certain extent.
However, if this ratio is too large, the restart time after the database crash may be very long, because a large amount of transaction data needs to be recovered from the log file and written into the data file. At the same time, an excessively large ratio value may also cause the “excessive” flush operation after reaching the upper limit of the ratio setting, resulting in large performance fluctuations.
- query_cache_type: If you use the innodb storage engine, it is recommended to be 0, if you use the MyISAM storage engine, it is recommended to be 2, and at the same time explicitly control whether it is your gquery cache in the SQL statement
- query_cache_size: Adjust according to the hit rate (Qcache_hits/(Qcache_hits+Qcache_inserts)*100)). Generally, it is not recommended to be too large. 256MB may be almost the same. Large configuration static data can be adjusted appropriately
- binlog_cache_size: 2MB~4MB is a suitable choice for general environment, the database environment with large transactions and frequent writes can be adjusted larger, but it is not recommended to exceed 32MB
- key_buffer_size: If the MyISAM storage engine is not used, 16MB is enough to cache some system table information, etc. If you use the MyISAM storage engine, if memory allows, put all indexes in memory as much as possible. Simply put, "the bigger the better"
- bulk_insert_buffer_size: If you frequently need to use the special statement of bulk insert (explained above) to insert data, you can appropriately increase this parameter to 16MB~32MB. It is not recommended to continue to increase it. Someone 8MB
- innodb_buffer_pool_size: If you don’t use the InnoDB storage engine, you don’t need to adjust this parameter. If you need to use it, if memory allows, store all InnoDB data files in memory as much as possible, but also "the bigger the better"
- innodb_additional_mem_pool_size: The general database is recommended to be adjusted to 8MB~16MB. If there are too many tables, it can be adjusted to 32MB. You can judge whether it needs to be increased according to the information in the error log
- innodb_log_buffer_size: The default is 1MB. For frequent systems, it can be appropriately increased to 4MB~8MB. Of course, as mentioned above, this parameter is actually related to other flush parameters. Generally speaking, it is not recommended to exceed 32MB
- innodb_max_dirty_pages_pct: According to past experience, if the data recovered by restart exceeds 1GB, the startup speed will be slower and almost unacceptable, so it is recommended not to exceed 1GB/innodb_buffer_pool_size(GB)*100. Of course, if you can tolerate a long startup time and want to minimize the flush from memory to disk, you can adjust this value to 90, but it is not recommended to exceed 90
Note: The above value range is just some optimization experience values obtained based on the database scenarios I encountered in the past, and may not be applicable to all scenarios, so in the actual optimization process, you need to continuously adjust and analyze by yourself, and welcome You can contact me at any time through Mail to communicate about optimization or architecture technology, and discuss and learn from each other together.
译文:
MySQL数据库性能优化,缓存参数优化第一篇
最常被问到的问题是关于 MySQL 数据库 性能优化,所以最近打算写一篇关于 MySQL 数据库性能优化 。 希望对初级和中级 MySQL DBA 感兴趣的朋友和其他对 MySQL 性能优化感兴趣的朋友有所帮助。
这是 MySQL数据库性能优化专题 系列的第一篇: MySQL数据库性能优化缓存参数优化
数据库是一个IO密集型的应用,它的主要职责是数据的管理和存储。 而我们知道,从内存读取数据库的时间是微秒级的,而从普通硬盘读取一个IO的时间是毫秒级的。 两者相差3个数量级。 所以要优化数据库,首先需要优化的就是IO,尽可能的将磁盘IO转化为内存IO。 本文首先从MySQL数据库IO相关参数(缓存参数)的角度来看看哪些参数可以用来优化IO :
- query_cache_size/query_cache_type(全局)
查询缓存作用于整个 MySQL Instance,主要用于缓存 MySQL 中的 ResultSet,它是一条 SQL 语句执行的结果集,所以只能用于 select 语句。 当我们开启Query Cache功能时,MySQL收到一个select语句的请求后,如果该语句满足Query Cache的要求(没有明确说明不允许Query Cache,或者已经明确说明使用Query Cache ), MySQL 会直接将接收到的 select 语句按照预设的 HASH 算法哈希为字符串,然后直接检查是否已经缓存在 Query Cache 中。 也就是说,如果已经在缓存中,那么选择请求会直接返回数据,从而省略了所有后续步骤(如SQL语句解析、优化器优化、向存储引擎请求数据等),极大地提高性能。
当然,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),这意味着根本不使用查询缓存。 除了显式请求不使用查询缓存(使用 sql_no_cache)之外的所有选择都使用查询缓存。 仅在显示需要时才使用查询缓存(使用 sql_cache)。
- binlog_cache_size(全局)
Binlog Cache用于开启二进制日志(binlog)记录功能的环境。 它是 MySQL 为提高 binlog 记录效率和在短时间内临时缓存 binlog 数据而设计的内存区域。
一般来说,如果我们的数据库中没有大的事务并且写入不是特别频繁,2MB到4MB是一个合适的选择。 但是如果我们的数据库有很多大事务,写入很多,我们可以适当增加binlog_cache_size。 同时,我们可以使用binlog_cache_use和binlog_cache_disk_use来分析设置的binlog_cache_size是否足够,以及是否由于内存不足而使用临时文件(binlog_cache_disk_use)缓存了大量的binlog_cache。
- key_buffer_size(全局)
Key Buffer 可能是大家最熟悉的 MySQL 缓存参数了,尤其是在 MySQL 不改变默认存储引擎的情况下,很多朋友可能会发现这个参数是 MySQL 默认配置文件中设置的最大内存参数。 key_buffer_size 参数用于设置 MyISAM 存储引擎中用于缓存索引文件的内存区域大小。 如果我们有足够的内存,这个缓存区应该可以存储我们所有的 MyISAM 引擎表的所有索引,以尽可能提高性能。
另外,我们在使用MyISAM存储的时候,还有一个极其重要的一点需要注意。 由于 MyISAM 引擎的特性,它只将索引块缓存到内存中,而不是表数据库块。 因此,我们的SQL必须尽可能的在索引中做过滤条件,这样缓存才能帮助我们提高查询效率。
- bulk_insert_buffer_size(线程)
和key_buffer_size一样,这个参数也只适用于MyISAM存储引擎,用于批量插入数据时临时缓存写入数据。 当我们使用以下类型的数据写入语句时,该内存区域将用于缓存批处理结构的数据,以帮助批量写入数据文件:
插入……选择……
插入…值(…),(…),(…)…
将数据 infile... 加载到... (非空表) - innodb_buffer_pool_size(全局)
当我们使用 InnoDB 存储引擎时,innodb_buffer_pool_size 参数可能是影响我们性能的最关键的参数。 用于设置用于缓存 InnoDB 索引和数据块的内存区域的大小,类似于 MyISAM 存储引擎的 key_buffer_size 参数。 当然,它可能更像Oracle的db_cache_size。 简单来说,当我们操作一张 InnoDB 表时,所有返回的数据或者在数据移除过程中使用的任何索引块都会经过这个内存区域。
和MyISAM引擎的key_buffer_size一样,innodb_buffer_pool_size设置InnoDB存储引擎最需要的内存区域大小,直接关系到InnoDB存储引擎的性能。 因此,如果我们有足够的内存,我们可以将此参数设置为足够的大小。 由于许多 InnoDB 索引和数据被放入这个缓存区域,最多。
我们可以通过 (Innodb_buffer_pool_read_requests – Innodb_buffer_pool_reads)/Innodb_buffer_pool_read_requests * 100% 来计算缓存命中率,并根据命中率调整 innodb_buffer_pool_size 参数大小进行优化。
- innodb_additional_mem_pool_size(全局)
我们通常不会过多地调整这个参数。 许多人使用默认值。 可能很多人对这个参数的作用不太熟悉。 innodb_additional_mem_pool_size 设置了 InnoDB 存储引擎用来存储数据字典信息和一些内部数据结构的内存空间大小,所以当我们在一个 MySQL Instance 中有很多数据库对象时,我们需要适当调整这个参数的大小以确保所有数据都可以存储在内存中,以提高访问效率。
很容易知道这个参数的大小是否足够,因为当它太小时,MySQL会在数据库的错误日志中记录Warning信息。 这时候,你就知道是时候调整这个参数的大小了。
- innodb_log_buffer_size(全局)
这是 InnoDB 存储引擎的事务日志使用的缓冲区。 与Binlog Buffer类似,InnoDB在写入事务日志时,为了提高性能,也会先将信息写入Innob Log Buffer,只有在innodb_flush_log_trx_commit参数设置的相应条件(或日志缓冲区满)后才会写入日志写入文件(或同步到磁盘)。 可以使用的最大内存空间可以通过 innodb_log_buffer_size 参数设置。
注意:innodb_flush_log_trx_commit 参数对 InnoDB Log 的写入性能有非常关键的影响。 该参数可以设置为0、1、2,解释如下:0:日志缓冲区中的数据会以每秒一次的频率写入日志文件,同时文件系统会同步到磁盘,但每个事务的提交不会触发任何日志缓冲区记录文件。 刷新或文件系统到磁盘的刷新操作;
1:每次提交事务都会将日志缓冲区中的数据写入日志文件,同时也会触发文件系统同步到磁盘;
2:事务提交会触发日志从缓冲区到日志文件的flush不会触发磁盘文件系统到磁盘的同步。 此外,每秒还会有一次文件系统到磁盘的同步操作。此外,MySQL 文档还提到,这些设置中的每秒同步一次机制可能无法完全确保每秒同步以非常准确的速率发生。 它还取决于进程调度问题。 事实上,InnoDB 是否真的能满足这个参数设置的值的含义。 正常恢复仍然受到不同操作系统下的文件系统和磁盘本身的限制。 有时它可能会告诉 mysqld 已经同步,但实际上并未完成磁盘同步。 磁盘同步完成。
- innodb_max_dirty_pages_pct (global)
该参数与上述参数不同。 它不是用来设置用于缓存某些数据的内存大小的参数,而是控制 InnoDB Buffer Pool 中不需要写入数据文件的 Dirty Pages 的比例(已修复但有未从内存写入数据文件)。 这个比例越大,从内存到磁盘的写操作会相对减少,所以可以在一定程度上减少写操作的磁盘IO。
但是如果这个比例过大,数据库crash后的重启时间可能会很长,因为需要从日志文件中恢复大量的事务数据并写入数据文件。 同时,过大的 ratio 值也可能导致达到 ratio 设置上限后的“过度”flush 操作,导致性能波动较大。
- query_cache_type:如果使用innodb存储引擎,建议为0,如果使用MyISAM存储引擎,建议为2,同时在SQL语句中显式控制是否是你的gquery缓存
- query_cache_size:根据命中率调整(Qcache_hits/(Qcache_hits+Qcache_inserts)*100))。 一般不建议太大。 256MB 可能差不多。 大配置静态数据可适当调整
- binlog_cache_size:2MB~4MB适合一般环境选择,事务量大、写频繁的数据库环境可以调大一些,但不建议超过32MB
- key_buffer_size:如果不使用MyISAM存储引擎,16MB足够缓存一些系统表信息等。如果使用MyISAM存储引擎,在内存允许的情况下,尽量把所有索引都放在内存中。 简而言之,“越大越好”
- bulk_insert_buffer_size:如果经常需要使用bulk insert的特殊语句(上面解释)插入数据,可以适当增加这个参数到16MB~32MB。 不建议继续增加。 有人 8MB
- innodb_buffer_pool_size:如果不使用 InnoDB 存储引擎,则不需要调整此参数。 如果需要使用,在内存允许的情况下,尽量将所有InnoDB数据文件存储在内存中,而且“越大越好”
- innodb_additional_mem_pool_size:一般数据库建议调整到8MB~16MB。 如果表太多,可以调整到32MB。 可以根据错误日志中的信息判断是否需要增加
- innodb_log_buffer_size:默认为 1MB。 对于频繁的系统,可以适当增加至4MB~8MB。 当然,如前所述,这个参数其实是和其他flush参数相关的。 一般来说,不建议超过32MB
- innodb_max_dirty_pages_pct:根据以往经验,如果重启恢复的数据超过1GB,启动速度会比较慢,几乎无法接受,所以建议不要超过1GB/innodb_buffer_pool_size(GB)*100。 当然,如果你能容忍较长的启动时间,又想尽量减少从内存到磁盘的flush,可以将此值调整为90,但不建议超过90
注意:以上数值范围只是我根据以往遇到的数据库场景得出的一些优化经验值,可能并不适用于所有场景,所以在实际优化过程中,需要通过以下方式不断调整和分析您自己,欢迎您随时通过Mail联系我,交流优化或 架构 技术,共同探讨学习。