• 8.10.1 The InnoDB Buffer Pool


    8.10 Buffering and Caching
    [+/-]

    8.10.1 The InnoDB Buffer Pool
    8.10.2 The MyISAM Key Cache
    8.10.3 The MySQL Query Cache
    8.10.4 Caching of Prepared Statements and Stored Programs

    MySQL 使用几种策略,cache 信息到内存来增加性能:

    8.10.1 The InnoDB Buffer Pool

    InnoDB 维护一个存储区域被叫做buffer pool,用于catching 数据和索引在内存里。

    了解InnoDB buffer pool 是如何工作的,并利用它来保持频繁访问的数据在内存里, 是MySQL 优化的一个重要的方面你。

    指南

    理想情况下, 你设置buffer pool 的大小尽可能的大,为服务器上的其他进程的运行留有足够的空间,

    不不要额外的分页。 更大的缓冲池,InnoDB 表现像一个内存数据库,从磁盘读取数据一次,

    然后从内存访问数据在随后的读取。buffer pool 甚至cache insert 和update 操作的改变的数据,

    因此,磁盘写入可以组合在一起,以更好的性能。

    根据系统中典型的负载, 你可以调整buffer pool的部分比例。

    你可以调优buffer pool 选择哪些blocks 被cache 一旦buffer pool 被填满,

    以保持频繁访问的数据在内存里,尽管突然出现的活动,如备份或者报表。

    在64位操作系统具有大内存, 你可以把buffer pool 分成多个parts,

    最小化内存结构之间的竞争在并发报错之间。

    内部细节:

    InnoDB 管理 池子作为一个列表, 使用一个LRU算法,当room 需要增加一个新的block 到池子里,

    InnoDB 驱逐做少使用的块和增加新的块到list 的中间。

    在列表头部, 是最近访问的块

    在尾部,最少访问的块

    这个算法保持大量使用的块在一个新的sublist, 老的sublist 包含最少使用的块,这些块是被驱逐的。

    LRU算法的操作如下默认:

    3/8的buffer pool 被分给old list

    列表的中间是新的sublist 遇到老的sublist 的边界

    当InnoDB 读取一个块到buffer pool,它初始化是插入到中间( old sublist 的头),

    一个block 可以被读取 因为它是一个用户指定的操作, 如SQL查询,

    或作为一个预读操作被InnoDB 执行。

    访问旧的sublist中的一个块,让它变的年轻,移到buffer pool的前面(new list 的头部)

    如果该块需要被读取, 第一次访问立即发生,块变的年轻。

    如果一个块由于预读,第一次访问不立即发生(可能根本不会发生在block 被驱逐前)

    当数据库操作时,在buffer pool中的blocks不被访问的 移到到list的尾部。

    Blocks 在old sublist 也会变老由于block 被插入到中间,最终,

    一个block 保持不被使用足够长时间达到old sublist 的尾部,被驱逐。

    默认情况下,读取的块被立即移动到new sublist,意味着它们会待在buffer pool里很长的时间。

    一个表扫描( 比如执行mysqldump 操作, 或者执行SELECT 语句没有WHERE条件)

    可以带来大量的数据到buffer pool,驱逐同等数量的older 数据,

    尽管新的数据从来不被使用, 类似的.

    Configuration Options 配置选项:

    几个InnoDB 系统变量控制buffer pool的大小,让你调优LRU算法:

    innodb_buffer_pool_size

    指定缓冲池大小,如果你的buffer pool是小的,但是你有足够的内存,让buffer pool变的大些来改善性能,

    降低disk IO的总量。

    innodb_buffer_pool_instances

    把buffer pool 分离到一个用户指定数量的单独的区域,每个局域都有它自己的LRU LIST和相关的数据结构

    降低冲突在并发的内存读写操作, 这个选项生效只有当你设置 innodb_buffer_pool_size to大于等于1G大小。

    你指定的总的内存大小被划分在所有的buffer pool, 最有效的方式,

    指定一个innodb_buffer_pool_instances 和innodb_buffer_pool_size 的组合,每个buffer pool 实例至少一个GB。

    mysql> show variables like ‘%innodb_buffer_pool_instances%’;
    +——————————+——-+
    | Variable_name | Value |
    +——————————+——-+
    | innodb_buffer_pool_instances | 8 |
    +——————————+——-+
    1 row in set (0.00 sec)

    mysql> show variables like ‘%innodb_buffer_pool_size%’;
    +————————-+————+
    | Variable_name | Value |
    +————————-+————+
    | innodb_buffer_pool_size | 8589934592 |
    +————————-+————+
    1 row in set (0.00 sec)

    innodb_old_blocks_pct

    指定的相似的buffer pool的比例,InnoDB 使用用于old block sublist,

    范围是5到95, 默认是3/8

    innodb_old_blocks_time

    指定 一个block 被插入到old sublist 的时间(单位ms) 必须stay ,在第一次访问 在它被移到new sublist.

    默认是0,一个block 被插入到old sublist 移到到一个新的sublist 当innodb 驱逐了1/4的插入块的页从buffer pool.

    无论多么快的插入访问发生,如果值是大于0,blocks 仍旧在old sublist直到访问至少发生,在很多ms后。

    设置 innodb_old_blocks_time 大于0防止一次性表扫描溢出new sublist,被scan 访问的块里的记录很多次在一个快速的

    但是快根本没被使用。如果innodb_old_blocks_time 设置的值大于处理块的时间,

    块仍旧在old sublist,块老化到list 的尾部被驱逐。这样,块用于一次扫描不会严重的损坏new sublist 上的使用的块。

    innodb_old_blocks_time 可以在运行时设置,你可以临时改变它,在表扫描和dumps的时候:

    SET GLOBAL innodb_old_blocks_time = 1000;
    … perform queries that scan tables …
    SET GLOBAL innodb_old_blocks_time = 0;

    在该过程中,还会涉及另一个参数innodb_old_blocks_time。在访问sublist of old blocks区域里的数据块时,并不是马上就移动到sublist of new blocks区域,而是会先让数据停留在sublist of old blocks区域innodb_old_blocks_time(微秒),然后再移动到sublist of new blocks区域,这样就保证了sublist of new blocks区域里的数据不会马上被踢出。

  • 相关阅读:
    Discuz经典函数注释之authcode
    在delphi中,DLL加载时做初始化的Demo
    KERNEL32相关函数
    解析 png 图片的十六进制字符流
    delphi 获取硬盘序列号、cpu号、bios号、网卡号
    封装 INI 文件读写函数
    A窗口消失B窗口弹出
    delphi公用函数
    获取打开文件的PID
    C# cmd调用外部命令
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13351404.html
Copyright © 2020-2023  润新知