Maison > Article > base de données > Explication détaillée de l'optimisation du cache pour l'optimisation MySQL (2)
Cet article est la suite du premier article de la série d'optimisation MySQL Cache Il présente tous les aspects de l'optimisation du cache plus en détail. J'espère que vous l'aimerez. 🎜>
MySQL a des caches partout à l'intérieur. Quand je lirai le code source de MySQL, j'analyserai en détail comment le cache est utilisé. Cette partie comprend principalement diverses optimisations de cache explicites :RequêteOptimisation du cache
Indextampon de cache
mysql> show variables like '%query_cache%'; +------------------------------+---------+ | Variable_name | Value | +------------------------------+---------+ | have_query_cache | YES | | query_cache_limit | 1048576 | | query_cache_min_res_unit | 4096 | | query_cache_size | 1048576 | | query_cache_type | OFF | | query_cache_wlock_invalidate | OFF | +------------------------------+---------+
S'il faut prendre en charge la mise en cache des requêtes. have_query_cache
Si la taille de l'ensemble de résultats d'une instruction select dépasse la valeur querycachelimit, l'ensemble de résultats ne sera pas ajouté au cache de requêtes. query_cache_limit
Le cache de requêtes s'applique à l'espace mémoire en blocs, et la taille de bloc appliquée à chaque fois est la valeur définie. 4K est une valeur très raisonnable et n’a pas besoin d’être modifiée. query_cache_min_res_unit
Taille du cache de requête. query_cache_size
Type de cache de requête, les valeurs sont 0 (OFF), 1 (ON), 2 (DEMOND). OFF indique que le cache de requêtes est désactivé. ON signifie que la requête est toujours recherchée en premier dans le cache de requêtes, sauf si l'option sql_no_cache est incluse dans l'instruction select. DEMOND indique que la mise en cache n'est applicable que si l'option sql_cache est incluse dans l'instruction select. query_cache_type
mysql> show status like 'Qcache%'; +-------------------------+---------+ | Variable_name | Value | +-------------------------+---------+ | Qcache_free_blocks | 1 | | Qcache_free_memory | 1031360 | | Qcache_hits | 0 | | Qcache_inserts | 0 | | Qcache_lowmem_prunes | 0 | | Qcache_not_cached | 0 | | Qcache_queries_in_cache | 0 | | Qcache_total_blocks | 1 | +-------------------------+---------+Afficher le
statutInformations du cache actuel :
Qcache_free_blocks
indique le nombre de blocs mémoire (nombre de fragments) dans le cache de requêtes qui sont dans un état reproductible. Si la valeur de Qcache_free_blocks est plus grande, cela signifie qu'il y a plus de fragments dans le cache de requête, indiquant que le jeu de résultats de la requête est plus petit. Dans ce cas, la valeur de query_cache_min_res_unit peut être réduite. L'utilisation du cache de requêtesQcache_free_memory
indique la quantité de mémoire disponible restante dans le cache de requêtes de l'instance de service MySQL actuelle.Qcache_hits
indique le nombre de fois que le cache de requêtes est utilisé, et la valeur augmentera séquentiellement. Si Qcache_hits est relativement volumineux, cela signifie que le cache de requêtes est utilisé très fréquemment et que le cache de requêtes doit être augmenté.Qcache_inserts
indique le nombre total d'ensembles de résultats d'instructions select qui ont été mis en cache dans le cache de requêtes.Qcache_lowmen_prunes
indique le nombre de résultats de requête que MySQLQcache_not_cached
Indique le nombre de sélections qui ne sont pas entrées dans le cache des requêtesQcache_queryies_in_cache
Indique le cache de requêtes. Combien d'ensembles de résultats d'instructions de sélection sont mis en cache dansQcache_total_blocks
Le nombre total de caches de requêtesComment calculer l'accès au cache rate : Cache de requêtes Le taux de réussite = Qcache_hits / Com_select * 100%où Com_select est le nombre d'instructions de sélection exécutées par l'instance MySQL actuelle. Généralement Com_select = Qcache_insert Qcache_not_cached. Qcache_not_cached contient des instructions de sélection qui rendent le cache de requêtes invalide en raison de modifications fréquentes des données, de sorte que le taux de réussite est généralement faible. Si vous mettez de côté le facteur d'échec, le taux de réussite du cache de requêtes = Qcache_hits / (Qcache_hits Qcache_inserts) Si vous utilisez cette formule pour calculer le taux de réussite du cache de requêtes est relativement élevé, cela signifie que la plupart des instructions select atteignent le cache de requêtes. Utilisez la commande suivante pour vérifier combien d'instructions de sélection ont été exécutées par le système actuelmysql> show status like 'Com_select'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | Com_select | 1 | +---------------+-------+
2. 🎜> 结果集缓存是会话缓存,MySQL客户机成功连接服务器之后。MySQL服务器会为每个MySQL客户机保留结果集缓存。缓存MySQL客户机连接线程的连接信息以及缓存返回MySQL客户机的结果集信息,当MySQL客户机向服务器发送select 语句时,MySQL将select语句的执行结果暂存在结果集缓存中。结果集的缓存大小由 net_buffer_length 参数值定义: 如果结果集超过net_buffer_length设置的值,则自动扩充容量,但不超过:max_allowd_packet的阈限值: 3、排序缓存 MySQL 常用的有InnoDB 和MyISAM 两种数据存储引擎。因此在优化的时候,每种引擎都会采用适合自己引擎的优化方法。关于MySQL 与InnoDB 表结构文件和数据日志文件的不同,可以先看本人的博客MySQL 日志系统,以便对这些基础概念有足够的了解,接下来看引擎的优化的方法才能如鱼得水,不觉得枯燥。 1、普通排序缓存 排序缓存是会话缓存, 如果客户机向服务端发送的SQL语句中含有设计排序的order by 或者group by 子句。MySQL就会选择相应的排序算法,在普通排序索引上进行排序,提升排序速度。普通排序索引的大小由sort_buffer_size 参数定义,如果要提升排序的速度,首先应该添加合适的索引,此后则应该增大排序索引缓存sort_buffer_size. 接下来我们来看下与排序缓存相关的参数有哪些: max_length_for_sort_data 默认大小为1024字节,对每一列的进行排序操作是,如果该列的值长度较长,通过增加该参数来提升MySQL性能。 max_sort_length order by 或者 group by 的时候使用该列的前 max_sort_length字节进行排序,排序操作完成后,会将此次排序的信息记录到本次会话的状态里。 Sort_merge_passes 使用临时文件完成排序操作的次数。MySQL在进行排序操作时,首先尝试在普通排序缓存中完成排序。如果缓存空间不够用,MySQL将利用缓存进行多次排序。并把每次的排序结果存放到临时文件中,最后再把临时文件中的数据做一次排序。Sort_merge_passes值就是记录了使用文件进行排序的次数。由于文件排序要牵涉到读文件,打开文件句柄,然后关闭文件等操作。所以读取文件的系统消耗比较大,通过增大普通排序缓存sort_buffer_size来减少使用临时文件排序的次数,从而增加排序的性能。 Sort_range 使用范围排序的次数 Sort_rows 已经排序的记录行数 Sort_scan 通过全表扫描完成排序的次数 2、MyISAM排序缓存 当我们使用alter table 语句或者create index 语句创建MyISAM表的索引,或者导入一部分数据使用load data infile path,这些操作都会导致索引被重建,重建索引时需要对索引字段进行排序操作,为了加快重建索引的效率,MyISAM提供了排序缓存用于实现索引的排序工作,这些方法都是尽量是排序的工作在内存中完成。MyISAM排序缓存的大小由myisam_sort_buffer_size定义。索引重建之后,该缓存立马释放。 但是当排序的缓存超过myisam_sort_buffer_size的阈限时,此时就需要在临时文件中完成索引字段的排序工作,外存临时文件的大小由myisam_max_sort_file_size参数设定,索引重建后,临时文件立即删除。 3、InnoDB 排序缓存 和MyISAM引擎类似,当执行alter table 、create index 创建索引是,InnoDB提供了3个InnoDB排序缓存用于实现索引的排序,每个缓存的大小由innodb_sort_buffer_size定义。 4、join 连接缓存 join缓存是会话缓存,如果两张表相连,但是却无法使用索引(这时使用join连接缓存的前提),MySQL将为每张表分配join 连接缓存。 join_buffer_size 定义了连接缓存的大小,如上图,默认为256; 5、表缓存Cache 与表结构定义缓存Cache MySQL 服务访问数据库中的表时,实际上MySQL是做的文件的读取操作。MySQL的数据都是存在硬盘上的一个个文件,这个和一些内存的型的数据库不同。当我们查询一张表,使用select 语句时,不考虑使用查询缓存,首先要操作系统打开该文件,产生该文件的描述符。操作系统将文件描述符交给MySQL,MySQL才能对数据库进行CURD的操作。打开文件、产生文件描述符都需要消耗系统资源,造成访问延时。MySQL将已经打开的文件,包括文件描述符缓存起来,以后再次访问该文件时,就无需打开该文件,提高了读取文件的效率。 表结构并不经常变化,当对表进行访问的时候,除了将该表植入MySQL的表缓存外,MySQL还将表结构放入了表结构定义缓存中,供下次使用。 table_open_cache 设定了可以缓存表以及视图的数量限制 table_definition_cache 设定了可以存储多少张frm 表结构 对于MySQL MyISAM引擎来说,表结构包含MYI 和MYD 以及表结构frm, 当访问MyISAM 引擎的时候,需要一次性打开两个文件(MYI 、MYD),产生两个文件描述符。 open_files_limit 打开文件的上限 innodb_open_files 如果InnoDB 表使用的是独立表空间文件(ibd),该参数设定同一时间能够打开的文件数量。 以下是和打开表相关的状态值: 6、表扫描缓存buffer 表扫描分为顺序扫描(Sequential Scan)以及随机扫描(Random Scan) 两种方式 顺序扫描 当MyISAM表没有建索引时,查询速度将进行全表扫描,效率很低。为了提升全表扫描的速度,MySQL提供了顺序扫描缓存(read buffer)。此时MySQL按照存储数据的存储顺序因此读出全部的数据块,每次读取的数据块缓存在顺序扫描缓存中,当read buffer写满之后,将数据返还给上层调用者。 随机扫描 当表里有缓存,扫描表的时候,会将表的索引字段放进内存里先拍好序,然后按照已经拍好的顺序去硬盘中查找数据。 7、MyISAM索引缓存buffer 通过缓存MYI索引文件的内容,可以加快读取索引的速度以及索引的速度。索引缓存只对MyISAM表起作用,且被所有线程共享。查询语句或者更新索引通过索引访问表数据的时候,MySQL首先检查索引缓存中是否已经存在需要的索引信息,如果有通过缓存中的索引可以直接访问到索引对应的MYD文件。如果没有,则会读取MYI文件,并将相应的索引数据读取到缓存中。索引缓存对MyISAM表的访问性能起到了至关重要的作用。 key_buffer_size 设置索引缓存的大小,默认是8M。建议提升。 key_cache_block_size 指定每个索引缓存的区块大小,建议设置为4K,即4096 key_cache_pision_limit 为了有效的使用缓存。默认情况下MySQL降缓存划分为两个索引缓存区,温区(warm area) 以及热区(hot area)。key_cache_pision_limit参数以百分比的形式向曾哥索引缓存划分为多个区域。当默认值是100的时候,表示索引缓存只有温区,将启用LRU算法淘汰索引缓存中的索引。 key_cahe_age_threshold 控制温区域热区中的索引何时升级何时降级。如果该值小于100,则有热区。移动算法大致类似与LRU算法。 查看当前MySQL服务实例索引读以及索引写的状态值: 8、日志缓存 日志缓存分为二进制日志缓存以及InnoDB重做日志缓存 1、二进制日志缓存 Mysql 进行创建或者更新的数据的时候,会记录一条二进制日志。然而频繁的进行I/O操作将对MySQL造成较大的性能影响。因此MySQL开辟了一个二进制日志缓存binlog_cache_size。首先将操作写入二进制日志,当操作成功之后,将二进制日志写入硬盘。 2、InnoDB重做日志缓存 事务在commit前,会将产生的重做日志写入InnoDB重做日志缓存,然后InnoDB【择机】执行轮询策略,将缓存中的重做日志文件写入ib_logfile0 以及ib_logfile1重做日志中。 InnoDB重做日志缓存可以确保事务提交前,事务运行期间产生的重做日志保存在InnoDB的日志缓存中,但并不写入重做日志文件中。写入时机由innodb_flush_log_at_trx_commit参数控制。 0:当缓存中重做日志文件以每秒一次的频率写入硬盘缓存,并且同时会更新到硬盘。 1:在每次事务提交的时候,将缓存中重做日志写到重做日志文件,同时写入硬盘,默认是该行为。 2:事务提交的时候,写到缓存,但并不触发文件系统到硬盘的同步操作,但此外每秒一次同步硬盘。 9、预读机制 预读机制主要利用了前文MySQL优化:一 、缓存优化所描述的原理。即局部性特征,空间局部性,和时间局部性,这里不再赘述。 1、InnoDB预读机制 InnoDB采用预读机制,将“未来即将访问的数据”包括索引加载到预读缓存中,进而提升数据的读性能。InnoDB支持顺序预读(linear read ahead)与随机预读(random read ahead)两种方式。 数据块(page)是InnoDB硬盘管理的最小单位,一个区由64个连续的数据块构成,对于顺序预读而言,InnoDB首选将该数据所在数据块置入InnoDB缓存池中,可以预测这些数据块的后续块很快就会被访问,于是这些数据块以及前置的数据块会被置入内存中。根据innodb_read_ahead_threshold参数设定预读前后多少个数据块。 2、索引缓存预加载 数据库管理员可以使用MySQL命令 load index into cache 预加载MyISAM表索引 10、MyISAM表延迟插入 看到这个延迟插入的功能,想起项目里一个有点类似的功能,启发了自己的思路。 使用方法为:insert delyed into table values(*); delyed_insert_limit 默认值为100.当向MySQL表延迟插入100行记录后,检查该表是否有select语句在等待执行,如果有,暂停insert语句执行。 delayed_insert_timeout 在超时范围内,如果delayed 队列里没有数据,延迟插入线程将关掉。 delayed_queue_size 延迟插入的队列长度,超出将阻塞,直到有足够的空间。 max_delayed_threads 延迟插入的线程数。 MyISAM表的批量延迟插入 类似 insert into table values(1),values(2),values(n)。MyISAM将进行批量插入。先将插入的数据放入缓存。当缓存被写满或者提交完毕了,MySQL一次性的将缓存中的写入硬盘。通过批量插入可以大大缩减MySQL客户机与服务机的连接语法分析等消耗,使得效率比分开执行单个insert语句快的多。 默认批量插入的大小为8M。如果业务上有需要,可以设定的大一些,以提高批量插入的性能。 MyISAM表的索引延迟更新 索引可以加快数据检索,但是对于更新来说,不仅需要修改记录,可能还需要修改索引,因此索引会导致数据更新操作变慢,如果将MySQL的delay_key_write参数设置为1(ON),可以弥补这一缺陷。开启后更新操作修改数据的时候先将数据的更新提交到硬盘,索引的更新全部在索引缓存里完成。在关闭表的时候,一起更新到硬盘,这样就可以使索引更新的更快。仅对MyISAM有效。 InnoDB延迟更新 非聚簇索引的更新操作通常会带来随机I/O,降低InoDB的性能。当更新(insert, delete ,update=insert+delete)非聚簇索引的数据时,会先检查非聚簇索引页是否位于InnoDB缓存池中,如果是直接更新,否则先将“信息修改”记录在更新缓存中(change buffer) 这篇博客的内容比较多,总结提炼下来以备以后查看。对整个MySQL的优化先有个整体的框架,徐徐渐进慢慢进步。这些参数可以不用记忆,用到的时候到博客中查找或者百度即可。了解道,知道术,就可以完成优化的过程。知道原理比记忆枯燥的原理要简单的多。对MySQL优化感兴趣的博友可以关注我的博客,以便看到后续的分享。mysql> show variables like 'net_buffer_length';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| net_buffer_length | 16384 |
+-------------------+-------+
mysql> show variables like 'max_allowed_packet';
+--------------------+---------+
| Variable_name | Value |
+--------------------+---------+
| max_allowed_packet | 4194304 |
+--------------------+---------+
mysql> select @@global.sort_buffer_size / 1024;
+----------------------------------+
| @@global.sort_buffer_size / 1024 |
+----------------------------------+
| 256.0000 |
+----------------------------------+
1 row in set (0.00 sec)
mysql> show variables like '%sort%';
+--------------------------------+---------------------+
| Variable_name | Value |
+--------------------------------+---------------------+
| innodb_disable_sort_file_cache | OFF |
| innodb_ft_sort_pll_degree | 2 |
| innodb_sort_buffer_size | 1048576 |
| max_length_for_sort_data | 1024 |
| max_sort_length | 1024 |
| myisam_max_sort_file_size | 9223372036853727232 |
| myisam_sort_buffer_size | 8388608 |
| sort_buffer_size | 262144 |
+--------------------------------+---------------------+
mysql> show status like '%sort%';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Sort_merge_passes | 0 |
| Sort_range | 0 |
| Sort_rows | 0 |
| Sort_scan | 0 |
+-------------------+-------+
mysql> select @@global.myisam_sort_buffer_size/1024;
+---------------------------------------+
| @@global.myisam_sort_buffer_size/1024 |
+---------------------------------------+
| 8192.0000 |
+---------------------------------------+
mysql> select @@global.myisam_max_sort_file_size /1024;
+------------------------------------------+
| @@global.myisam_max_sort_file_size /1024 |
+------------------------------------------+
| 9007199254739967.7734 |
+------------------------------------------+
mysql> select @@global.innodb_sort_buffer_size/1024;
+---------------------------------------+
| @@global.innodb_sort_buffer_size/1024 |
+---------------------------------------+
| 1024.0000 |
+---------------------------------------+
mysql> select @@global.join_buffer_size/1024;
+--------------------------------+
| @@global.join_buffer_size/1024 |
+--------------------------------+
| 256.0000 |
+--------------------------------+
mysql> show variables like 'table%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| table_definition_cache | 1400 |
| table_open_cache | 2000 |
| table_open_cache_instances | 1 |
+----------------------------+-------+
mysql> show variables like '%open%';
+----------------------------+----------+
| Variable_name | Value |
+----------------------------+----------+
| have_openssl | DISABLED |
| innodb_open_files | 2000 |
| open_files_limit | 65535 |
| table_open_cache | 2000 |
| table_open_cache_instances | 1 |
+----------------------------+----------+
mysql> show status like 'Open%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| Open_files | 18 |
| Open_streams | 0 |
| Open_table_definitions | 70 |
| Open_tables | 63 |
| Opened_files | 125 |
| Opened_table_definitions | 0 |
| Opened_tables | 0 |
+--------------------------+-------+
mysql> show variables like 'key%';
+--------------------------+---------+
| Variable_name | Value |
+--------------------------+---------+
| key_buffer_size | 8388608 (8M)|
| key_cache_age_threshold | 300 |
| key_cache_block_size | 1024 |
| key_cache_pision_limit | 100 |
+--------------------------+---------+
mysql> show status like 'Key%';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| Key_blocks_not_flushed | 0 |
| Key_blocks_unused | 6698 |
| Key_blocks_used | 0 |
| Key_read_requests | 0 |
| Key_reads | 0 |
| Key_write_requests | 0 |
| Key_writes | 0 |
+------------------------+-------+
mysql> show variables like '%binlog%cache%';
+----------------------------+----------------------+
| Variable_name | Value |
+----------------------------+----------------------+
| binlog_cache_size | 32768 |
| binlog_stmt_cache_size | 32768 |
| max_binlog_cache_size | 18446744073709547520 |
| max_binlog_stmt_cache_size | 18446744073709547520 |
+----------------------------+----------------------+
mysql> show status like '%binlog%cache%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| Binlog_cache_disk_use | 0 |
| Binlog_cache_use | 0 |
| Binlog_stmt_cache_disk_use | 0 |
| Binlog_stmt_cache_use | 0 |
+----------------------------+-------+
mysql> show variables like 'innodb_log_buffer_size';
+------------------------+---------+
| Variable_name | Value |
+------------------------+---------+
| innodb_log_buffer_size | 8388608 |
+------------------------+---------+
mysql> show variables like 'innodb_flush_log%';
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| innodb_flush_log_at_timeout | 1 |
| innodb_flush_log_at_trx_commit | 1 |
+--------------------------------+-------+
mysql> show variables like 'innodb_read_ahead%';
+-----------------------------+-------+
| Variable_name | Value |
+-----------------------------+-------+
| innodb_read_ahead_threshold | 56 |
+-----------------------------+-------+
mysql> show variables like '%delayed%';
+----------------------------+-------+
| Variable_name | Value |
+----------------------------+-------+
| delayed_insert_limit | 100 |
| delayed_insert_timeout | 300 |
| delayed_queue_size | 1000 |
| max_delayed_threads | 20 |
| max_insert_delayed_threads | 20 |
+----------------------------+-------+
mysql> select @@global.bulk_insert_buffer_size/(1024*1024);
+----------------------------------------------+
| @@global.bulk_insert_buffer_size/(1024*1024) |
+----------------------------------------------+
| 8.0000 |
+----------------------------------------------+
mysql> show variables like 'delay_key_write';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| delay_key_write | ON |
+-----------------+-------+
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!