MySQL 5.6 Reference Manual-14.4 InnoDB Configuration

2022-12-31,,,

14.4 InnoDB Configuration

14.4.1 InnoDB Initialization and Startup Configuration

14.4.2 Configuring InnoDB for Read-Only Operation

14.4.3 InnoDB Buffer Pool Configuration

14.4.4 Configuring the Memory Allocator for InnoDB

14.4.5 Configuring InnoDB Change Buffering

14.4.6 Configuring Thread Concurrency for InnoDB

14.4.7 Configuring the Number of Background InnoDB I/O Threads

14.4.8 Configuring the InnoDB Master Thread I/O Rate

14.4.9 Configuring Spin Lock Polling

14.4.10 Configuring InnoDB Purge Scheduling

14.4.11 Configuring Optimizer Statistics for InnoDB

14.4.12 Configuring the Merge Threshold for Index Pages

This section provides configuration information and procedures for InnoDB initialization, startup, and various components and features of the InnoDB storage engine. For information about optimizing database operations for InnoDB tables, see Section 8.5, "Optimizing for InnoDB Tables".

这一章节讲述了InnoDB的配置信息,以及初始化,启动等各个部件和特性的信息。对于InnoDB的 优化操作信息可以见Section 8.5, "Optimizing for InnoDB Tables"。

14.4.1 InnoDB Initialization and Startup Configuration

The first decisions to make about InnoDB configuration involve how to lay out InnoDB data files, and how much memory to allocate for the InnoDB storage engine. You record these choices either by recording them in a configuration file that MySQL reads at startup, or by specifying them as command-line options in a startup script. The full list of options, descriptions, and allowed parameter values is at Section 14.12, "InnoDB Startup Options and System Variables".

第一部分介绍了InnoDB的配置,涉及到了InnoDB的数据文件是如何分布的,以及InnoDB存储引擎是如何分配内存的。你可以把这些选项写到配置文件里,让MySQL的启动的时候去读它,或者在启动脚本里面加入这些命令行参数。参数的详细信息可见Section 14.12, "InnoDB Startup Options and System Variables"。

Overview of InnoDB Tablespace and Log Files

Two important disk-based resources managed by the InnoDB storage engine are its tablespace data files and its log files. If you specify no InnoDB configuration options, MySQL creates an auto-extending data file, slightly larger than 12MB, named ibdata1 and two log files named ib_logfile0 and ib_logfile1 in the MySQL data directory. Their size is given by the size of the innodb_log_file_size system variable. To get good performance, explicitly provide InnoDB parameters as discussed in the following examples. Naturally, edit the settings to suit your hardware and requirements.

InnoDB存储引擎管理的两个重要的基于磁盘的资源是它自身的表空间数据文件和日志文件。如果你没有指定InnoDB的配置参数,MySQL会在MySQL数据目录里创建一个自动扩展的数据文件,大约比12MB多一点,名字叫ibdata1,以及两个名字分别为ib_logfile0和ib_logfile1的日志文件。它们的大小是由innodb_log_file_size系统参数决定的。要得到更好的性能,可以根据下面例子讨论的显示指定InnoDB参数。自然地,配置的参数要适合你的硬件和要求。

The examples shown here are representative. See Section 14.12, "InnoDB Startup Options and System Variables" for additional information about InnoDB-related configuration parameters.

这里的例子是具有代表性的。关于详细InnoDB相关的配置参数可以查看Section 14.12, "InnoDB Startup Options and System Variables"。

Considerations for Storage Devices

In some cases, database performance improves if the data is not all placed on the same physical disk. Putting log files on a different disk from data is very often beneficial for performance. The example illustrates how to do this. It places the two data files on different disks and places the log files on the third disk. InnoDB fills the tablespace beginning with the first data file. You can also use raw disk partitions (raw devices) as InnoDB data files, which may speed up I/O. See Section 14.5.3, "Using Raw Disk Partitions for the System Tablespace".

在某些情况下,如果把数据文件分散到不同的物理磁盘上可以提高数据库的性能。这其中把日志文件当数据文件分离开来是一种常见的优化手段。这里的例如就说明了应该如何做:把两个数据文件放到不同的磁盘上,并把日志文件放到第三个磁盘上。InnoDB首先会填充表空间的第一个数据文件。你还可以使用raw disk partitions (raw devices)作为InnoDB的数据文件,这能够加快I/O的速度。详见Section 14.5.3, "Using Raw Disk Partitions for the System Tablespace"。

Caution

InnoDB is a transaction-safe (ACID compliant) storage engine for MySQL that has commit, rollback, and crash-recovery capabilities to protect user data. However, it cannot do so if the underlying operating system or hardware does not work as advertised. Many operating systems or disk subsystems may delay or reorder write operations to improve performance. On some operating systems, the very fsync() system call that should wait until all unwritten data for a file has been flushed might actually return before the data has been flushed to stable storage. Because of this, an operating system crash or a power outage may destroy recently committed data, or in the worst case, even corrupt the database because of write operations having been reordered. If data integrity is important to you, perform some "pull-the-plug" tests before using anything in production. On OS X 10.3 and higher, InnoDB uses a special fcntl() file flush method. Under Linux, it is advisable to disable the write-back cache.

InnoDB是事务安全(符合ACID)的存储引擎,能够commit,rollback,以及崩溃恢复的能力的保护用户数据。然而,如果其所在的操作系统或者硬件不工作了那也是不行的。许多操作系统或者磁盘子系统会用延迟或者重新排序写操作来该散性能。在一些操作系统里,会使用fsync()把数据刷新到稳定的存储里,但在返回结果之前它会一直等待。就因为这个,操作系统崩溃或者电源故障InnoDB会丢失最近一次的commit数据,最坏的情况是,因为重新写操作而损害了数据。如果一些环境数据完整是极为重要的,最好在生产环境使用之前做一些"pull-the-plug"的测试。在OS X 10.3或更高的版本上,InnoDB会使用特定的fcntl()文件刷新方法。在Linux环境下,最好是关闭write-back cache。

On ATA/SATA disk drives, a command such hdparm -W0 /dev/hda may work to disable the write-back cache. Beware that some drives or disk controllers may be unable to disable the write-back cache.

在ATA/SATA磁盘上,hdparm -W0 /dev/hda命令能够关闭write-back cache。还有要注意的是一些磁盘控制器是不能够关闭write-back cache的。

With regard to InnoDB recovery capabilities that protect user data, InnoDB uses a file flush technique involving a structure called the doublewrite buffer, which is enabled by default (innodb_doublewrite=ON). The doublewrite buffer adds safety to recovery following a crash or power outage, and improves performance on most varieties of Unix by reducing the need for fsync() operations. It is recommended that the innodb_doublewrite option remains enabled if you are concerned with data integrity or possible failures. For additional information about the doublewrite buffer, see Section 14.10, "InnoDB Disk I/O and File Space Management".

在InnoDB的恢复能力里,会使用一个叫做doublewrite buffer的文件刷新技术(默认是开启的,innodb_doublewrite=ON)。doublewrite buffer会在崩溃或者电源故障后安全恢复数据库,还能在众多Unix平台上减少fsync()操作来改善性能。如果你非常关心数据的完整性或者可能的故障,那么建议开启innodb_doublewrite这个参数。关于doublewrite buffer的更多信息可以查看Section 14.10, "InnoDB Disk I/O and File Space Management"。

Caution

If reliability is a consideration for your data, do not configure InnoDB to use data files or log files on NFS volumes. Potential problems vary according to OS and version of NFS, and include such issues as lack of protection from conflicting writes, and limitations on maximum file sizes.

如果非常关注数据的可靠性,那么不要把InnoDB的数据文件或者日志文件配置到NFS卷上。不同的OS和NFS的版本会有很多潜在的问题:例如冲突写造成的保护不足,还有最大文件大小的限制。

Specifying the Location and Size for InnoDB Tablespace Files

To set up the InnoDB tablespace files, use the innodb_data_file_path option in the [mysqld] section of the my.cnf option file. On Windows, you can use my.ini instead. The value of innodb_data_file_path should be a list of one or more data file specifications. If you name more than one data file, separate them by semicolon (";") characters:

可以在my.cnf的[mysqld]章节里使用innodb_data_file_path参数来设置InnoDB表空间文件。在Windows上,使用的是my.ini。innodb_data_file_path的值可以是一个或者多个文件的列表,通过分号(";")分割:

innodb_data_file_path=datafile_spec1[;datafile_spec2]...

For example, the following setting explicitly creates a minimally sized system tablespace:

下面的例子显式地创建了一个最小尺寸的系统表空间:

[mysqld]

innodb_data_file_path=ibdata1:12M:autoextend

This setting configures a single 12MB data file named ibdata1 that is auto-extending. No location for the file is given, so by default, InnoDB creates it in the MySQL data directory.

这里配置了单个12MB的数据文件,名字是ibdata1,并自动扩展。没有指定文件的位置,所以会十一on个默认的在MySQL的数据目录下。

Sizes are specified using K, M, or G suffix letters to indicate units of KB, MB, or GB.

大小使用K, M, or G来表示KB, MB, or GB。

A tablespace containing a fixed-size 50MB data file named ibdata1 and a 50MB auto-extending file named ibdata2 in the data directory can be configured like this:

下面的例子配置了表空间有两个文件,一个是带笑傲固定50MB,名字是ibdata1,另一个也是50MB,但是是自动扩展的,名字叫ibdata2。它们都在数据目录里。

[mysqld]

innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend

The full syntax for a data file specification includes the file name, its size, and several optional attributes:

指定数据文件的语法规范包括文件名,大小,以及一些其他的属性:

file_name:file_size[:autoextend[:max:max_file_size]]

The autoextend and max attributes can be used only for the last data file in the innodb_data_file_path line.

autoextend和max属性只能用于innodb_data_file_path里的最后的一个数据文件。

If you specify the autoextend option for the last data file, InnoDB extends the data file if it runs out of free space in the tablespace. The increment is 8MB at a time by default. To modify the increment, change the innodb_autoextend_increment system variable.

如果你为最后一个文件设定了autoextend,那么InnoDB超过空余表空间的时候会自动扩展数据文件。默认的一次增量值是8MB。通过innodb_autoextend_increment系统变量可以修改增量值。

If the disk becomes full, you might want to add another data file on another disk. For tablespace reconfiguration instructions, see Section 14.5.1, "Resizing the InnoDB System Tablespace".

如果磁盘要满了,你可以在另一个磁盘上添加一个新的文件。对于表空间的配置指定,可以查看Section 14.5.1, "Resizing the InnoDB System Tablespace"。

InnoDB is not aware of the file system maximum file size, so be cautious on file systems where the maximum file size is a small value such as 2GB. To specify a maximum size for an auto-extending data file, use the max attribute following the autoextend attribute. Use the max attribute only in cases where constraining disk usage is of critical importance, because exceeding the maximum size causes a fatal error, possibly including a crash. The following configuration permits ibdata1 to grow up to a limit of 500MB:

InnoDB不会关注文件系统的最大文件限制,所以要关注文件系统的最大文件限制,例如能不能超过2GB。根据下面的例子可以使用autoextend熟悉的max属性来指定自动扩展文件的最大限制。使用max属性只是用来约束磁盘空间的使用情况,因为超过最大的限制还会引起一个致命的错误,甚至包括系统崩溃。下面的配置允许ibdata1能够增长到 500MB:

[mysqld]

innodb_data_file_path=ibdata1:12M:autoextend:max:500M

InnoDB creates tablespace files in the MySQL data directory by default. To specify a location explicitly, use the innodb_data_home_dir option. For example, to use two files named ibdata1 and ibdata2 but create them in the /ibdata directory, configure InnoDB like this:

InnoDB默认在MySQL数据目录里创建表空间。也可以使用innodb_data_home_dir参数来显式指定位置。例如,这样可以配置在/ibdata目录里创建两个文件:

[mysqld]

innodb_data_home_dir = /ibdata

innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend

Note

InnoDB does not create directories, so make sure that the /ibdata directory exists before you start the server. This is also true of any log file directories that you configure. Use the Unix or DOS mkdir command to create any necessary directories.

InnoDB不会自己创建目录,所以在服务启动之前要确保/ibdata目录是存在的。对于日志文件目录也是同样的。使用Unix或者DOS的mkdir命令来创建必要的目录。

Make sure that the MySQL server has the proper access rights to create files in the data directory. More generally, the server must have access rights in any directory where it needs to create data files or log files.

还有要确保MySQL有适当的访问权限在数据目录里创建文件。一般地说,对于MySQL要创建的数据文件或者日志文件的任何目录都要有适当的权限。

InnoDB forms the directory path for each data file by textually concatenating the value of innodb_data_home_dir to the data file name, adding a path name separator (slash or backslash) between values if necessary. If the innodb_data_home_dir option is not specified in my.cnf at all, the default value is the "dot" directory ./, which means the MySQL data directory. (The MySQL server changes its current working directory to its data directory when it begins executing.)

InnoDB也可以通过innodb_data_home_dir的值连接文件名来作为每个文件的目录路径。如果my.cnf里面没有指定innodb_data_home_dir,默认的值是"./",这就意味着是MySQL的数据目录。(MySQL可以把当面的工作工作改到它的数据目录。)

If you specify innodb_data_home_dir as an empty string, you can specify absolute paths for the data files listed in the innodb_data_file_path value. The following example is equivalent to the preceding one:

如果你指定了innodb_data_home_dir是一个空字符串,那也可以在innodb_data_file_path里面为数据文件使用绝对路径。下面的例子等价于前面的例子:

[mysqld]

innodb_data_home_dir =

innodb_data_file_path=/ibdata/ibdata1:50M;/ibdata/ibdata2:50M:autoextend

Specifying InnoDB Configuration Options

Sample my.cnf file for small systems. Suppose that you have a computer with 512MB RAM and one hard disk. The following example shows possible configuration parameters in my.cnf or my.ini for InnoDB, including the autoextend attribute. The example suits most users, both on Unix and Windows, who do not want to distribute InnoDB data files and log files onto several disks. It creates an auto-extending data file ibdata1 and two InnoDB log files ib_logfile0 and ib_logfile1 in the MySQL data directory.

小系统可以参考下面的my.cnf样例。假设计算机的内存是512MB,只有一个硬盘。下面的额配置样例包括了autoextend属性。这个例子适合于大多数的用户,在Unix和Windows上都适用,但是不适用于那些把InnoDB数据文件和日志文件分布到不同的磁盘。它会在MySQL数据目录里创建一个自动扩展的数据文件ibdata1以及两个InnoDB日志文件ib_logfile0和ib_logfile1。

[mysqld]

# You can write your other MySQL server options here

# ...

# Data files must be able to hold your data and indexes.

# Make sure that you have enough free disk space.

innodb_data_file_path = ibdata1:12M:autoextend

#

# Set buffer pool size to 50-80% of your computer's memory

innodb_buffer_pool_size=256M

innodb_additional_mem_pool_size=20M

#

# Set the log file size to about 25% of the buffer pool size

innodb_log_file_size=64M

innodb_log_buffer_size=8M

#

innodb_flush_log_at_trx_commit=1

Note

Data files must be less than 2GB in some file systems. The combined size of the log files can be up to 512GB. The combined size of data files must be slightly larger than 10MB.

一些文件系统里数据文件必须要小于2GB。日志文件的组合可以达到512GB。数据文件组合后的大小要至少大于10MB。

Setting Up the InnoDB System Tablespace

When you create an InnoDB system tablespace for the first time, it is best that you start the MySQL server from the command prompt. InnoDB then prints the information about the database creation to the screen, so you can see what is happening. For example, on Windows, if mysqld is located in C:\Program Files\MySQL\MySQL Server 5.6\bin, you can start it like this:

当你第一次创建一个InnoDB系统表空间的时候,最好从命令行启动MySQL服务。InnoDB会打印出数据库创建的信息到屏幕上,这样你就能看到发生了什么。例如,在Windows上,如果mysqld在C:\Program Files\MySQL\MySQL Server 5.6\bin里,你可以这样启动它:

C:\> "C:\Program Files\MySQL\MySQL Server 5.6\bin\mysqld" --console

If you do not send server output to the screen, check the server's error log to see what InnoDB prints during the startup process.

如果没有输出到屏幕,那么可以通过error log来查看InnoDB的启动的时候的打印信息。

Editing the MySQL Configuration File

You can place InnoDB options in the [mysqld] group of any option file that your server reads when it starts. The locations for option files are described in Section 4.2.6, "Using Option Files".

你可以把InnoDB参数放置在任何配置文件的[mysqld]组里,让服务在启动的时候去读取它。关于参数文件的位置信息可以查看Section 4.2.6, "Using Option Files"。

If you installed MySQL on Windows using the installation and configuration wizards, the option file will be the my.ini file located in your MySQL installation directory. See Section 2.3.3, "Installing MySQL on Microsoft Windows Using MySQL Installer".

如果你在Windows上安装MySQL使用的是安装配置向导,配置文件my.ini会放在MySQL的安装目录里。详见Section 2.3.3, "Installing MySQL on Microsoft Windows Using MySQL Installer"。

If your PC uses a boot loader where the C: drive is not the boot drive, your only option is to use the my.ini file in your Windows directory (typically C:\WINDOWS). You can use the SET command at the command prompt in a console window to print the value of WINDIR:

如果你的C盘不是启动盘,那么则需要把my.ini文件放到Windows目录里(通常是C:\WINDOWS)。你可以在命令行使用SET命令来打印出WINDIR的值:

C:\> SET WINDIR

windir=C:\WINDOWS

To make sure that mysqld reads options only from a specific file, use the --defaults-file option as the first option on the command line when starting the server:

为了确保mysqld读取的参数是来自于指定的文件,在启动服务的时候可以指定--defaults-file参数:

mysqld --defaults-file=your_path_to_my_cnf

Sample my.cnf file for large systems. Suppose that you have a Linux computer with 2GB RAM and three 60GB hard disks at directory paths /, /dr2 and /dr3. The following example shows possible configuration parameters in my.cnf for InnoDB.

适用于大系统的my.cnf样例。假设Linux系统有2GB的内存,三个60GB的硬盘目录分别是/, /dr2 and /dr3。下面的例子显示了InnoDB可用的配置参数。

[mysqld]

# You can write your other MySQL server options here

# ...

innodb_data_home_dir =

#

# Data files must be able to hold your data and indexes

innodb_data_file_path = /db/ibdata1:2000M;/dr2/db/ibdata2:2000M:autoextend

#

# Set buffer pool size to 50-80% of your computer's memory,

# but make sure on Linux x86 total memory usage is < 2GB

innodb_buffer_pool_size=1G

innodb_additional_mem_pool_size=20M

innodb_log_group_home_dir = /dr3/iblogs

#

# Set the log file size to about 25% of the buffer pool size

innodb_log_file_size=250M

innodb_log_buffer_size=8M

#

innodb_flush_log_at_trx_commit=1

innodb_lock_wait_timeout=50

#

# Uncomment the next line if you want to use it

#innodb_thread_concurrency=5

Determining the Maximum Memory Allocation for InnoDB

Warning

On 32-bit GNU/Linux x86, be careful not to set memory usage too high. glibc may permit the process heap to grow over thread stacks, which crashes your server. It is a risk if the value of the following expression is close to or exceeds 2GB:

在32位的GNU/Linux x86系统上,注意不要把可用内存设置得过高。glibc版可能允许进程堆堵塞thread stack,这会使得实例崩溃。如果下面表达式的值接近或者超过2GB就会有风险:

innodb_buffer_pool_size

+ key_buffer_size

+ max_connections*(sort_buffer_size+read_buffer_size+binlog_cache_size)

+ max_connections*2MB

Each thread uses a stack (often 2MB, but only 256KB in MySQL binaries provided by Oracle Corporation.) and in the worst case also uses sort_buffer_size + read_buffer_size additional memory.

每个线程使用一个stack(通常是2MB,但是Oracle公司提供的MySQL只有256KB),最坏的情况是还使用了额外的sort_buffer_size + read_buffer_size内存。

Tuning other mysqld server parameters. The following values are typical and suit most users:

调整其他的mysqld实例参数。下面的是比较常见的适用于大多数的用户:

[mysqld]

skip-external-locking

max_connections=200

read_buffer_size=1M

sort_buffer_size=1M

#

# Set key_buffer to 5 - 50% of your RAM depending on how much

# you use MyISAM tables, but keep key_buffer_size + InnoDB

# buffer pool size < 80% of your RAM

key_buffer_size=value

On Linux, if the kernel is enabled for large page support, InnoDB can use large pages to allocate memory for its buffer pool and additional memory pool. See Section 8.12.5.2, "Enabling Large Page Support".

在Linux平台上,如果内核已经开启对大页的支持,InnoDB也可以为它的buffer pool和additional memory pool使用大页来分配内存。详见Section 8.12.5.2, "Enabling Large Page Support"。

14.4.2 Configuring InnoDB for Read-Only Operation

You can now query InnoDB tables where the MySQL data directory is on read-only media, by enabling the --innodb-read-only configuration option at server startup.

你现在能够通过开启--innodb-read-only配置参数,把MySQL的数据目录放在只读的媒介上,对InnoDB表进行只读操作。

How to Enable

To prepare an instance for read-only operation, make sure all the necessary information is flushed to the data files before storing it on the read-only medium. Run the server with change buffering disabled (innodb_change_buffering=0) and do a slow shutdown.

要准备实例只读,要确保所有必要的信息在存储到只读媒介之前都刷新到了数据文件上。是运行实例的时候关闭change buffer(innodb_change_buffering=0),并进行一个缓慢关闭(do a slow shutdown)。

To enable read-only mode for an entire MySQL instance, specify the following configuration options at server startup:

在服务启动的时候可以指定下面的配置参数来开启对于整个MySQL实例的只读模式:

--innodb-read-only=1
If the instance is on read-only media such as a DVD or CD, or the /var directory is not writeable by all: --pid-file=path_on_writeable_media and --event-scheduler=disabled
如果实例是在只读媒介上,例如DVD或者CD,又或者/var不可写:--pid-file=path_on_writeable_media and --event-scheduler=disabled

Usage Scenarios

This mode of operation is appropriate in situations such as:

这种模式适用于以下的场景:

Distributing a MySQL application, or a set of MySQL data, on a read-only storage medium such as a DVD or CD.
MySQL应用或者一组MySQL数据在只读的存储媒介上,例如DVD or CD。
Multiple MySQL instances querying the same data directory simultaneously, typically in a data warehousing configuration. You might use this technique to avoid bottlenecks that can occur with a heavily loaded MySQL instance, or you might use different configuration options for the various instances to tune each one for particular kinds of queries.
多个MySQL实例同时查询同个数据目录,通常在数据仓库里会有这样的配置。你可以使用这种方法来避免加重一个MySQL实例的负载,又或者可以使用对不同的实例 使用不同的配置参数。
Querying data that has been put into a read-only state for security or data integrity reasons, such as archived backup data.
因安全性或者数据完整性的原因以只读的状态查询数据,例如归档的备份数据。

Note

This feature is mainly intended for flexibility in distribution and deployment, rather than raw performance based on the read-only aspect. See Section 8.5.3, "Optimizing InnoDB Read-Only Transactions" for ways to tune the performance of read-only queries, which do not require making the entire server read-only.

将来主要的目的是数据分布部署的灵活性,而不是基于只读方面的性能优势。对于调整只读查询的方式可以查看Section 8.5.3, "Optimizing InnoDB Read-Only Transactions",这就不需要把整个实例置于只读状态。

How It Works

When the server is run in read-only mode through the --innodb-read-only option, certain InnoDB features and components are reduced or turned off entirely:

当实例通过--innodb-read-only参数工作在只读模式,一些主要的InnoDB特性和部件将会被关闭:

No change buffering is done, in particular no merges from the change buffer. To make sure the change buffer is empty when you prepare the instance for read-only operation, disable change buffering (innodb_change_buffering=0) and do a slow shutdown first.
没有change buffer会工作,尤其是将不再会有来自change buffer的合并。当你准备要把实例配置成只读的时候要确保change buffer是空的,可以挂壁change buffer(innodb_change_buffering=0) 然后进行一个slow shutdown。
There is no crash recovery phase at startup. The instance must have performed a slow shutdown before being put into the read-only state.
在启动的时候就不会再有崩溃恢复的阶段。在要把实例方知道只读状态之前要实例必须要执行一个slow shutdown。
Because the redo log is not used in read-only operation, you can set innodb_log_file_size to the smallest size possible (1 MB) before making the instance read-only.
因为redo log不会用于只读的操作,你可以在配置实例只读之前设置innodb_log_file_size为最小可能的值(1 MB) 。
All background threads other than I/O read threads are turned off. As a consequence, a read-only instance cannot encounter any deadlocks.
除了I/O读线程外所有的后台线程要关闭。因此,一个只读的实例不会遭遇到任何的死锁状况。
Information about deadlocks, monitor output, and so on is not written to temporary files. As a consequence, SHOW ENGINE INNODB STATUS does not produce any output.
死锁,监控输出等信息将 不会写入到临时文件。因此,SHOW ENGINE INNODB STATUS将不会产生任何的输出。
If the MySQL server is started with --innodb-read-only but the data directory is still on writeable media, the root user can still perform DCL operations such as GRANT and REVOKE.
如果MySQL实例使用--innodb-read-only启动的,但是数据目录任然是在可写的媒介上的,root用户任然可以执行例如GRANT和REVOKE的DCL操作。
Changes to configuration option settings that would normally change the behavior of write operations, have no effect when the server is in read-only mode.
修改配置参数的指定通常会改变写操作的行为,但是实例在只读模式下这将不会有效果。
The MVCC processing to enforce isolation levels is turned off. All queries read the latest version of a record, because update and deletes are not possible.
MVCC处理使用强制隔离级别会被关闭。所有查询都会读最近版本的记录,因为update和delete是不可用的。
The undo log is not used. Disable any settings for the innodb_undo_tablespaces and innodb_undo_directory configuration options.
undo log不会被使用。将会关闭任何关于innodb_undo_tablespaces和innodb_undo_directory的配置参数。

14.4.3 InnoDB Buffer Pool Configuration

14.4.3.1 Configuring InnoDB Buffer Pool Prefetching (Read-Ahead)

14.4.3.2 Configuring the Rate of InnoDB Buffer Pool Flushing

14.4.3.3 Making the Buffer Pool Scan Resistant

14.4.3.4 Using Multiple Buffer Pool Instances

14.4.3.5 Preloading the InnoDB Buffer Pool for Faster Restart

14.4.3.6 Tuning InnoDB Buffer Pool Flushing

This section provides performance related configuration information for the InnoDB buffer pool. For additional information, see Section 8.10.1, "The InnoDB Buffer Pool".

这一章节提供了InnoDB buffer pool相关的性能的配置信息。另外还可以查看Section 8.10.1, "The InnoDB Buffer Pool"。

14.4.3.1 Configuring InnoDB Buffer Pool Prefetching (Read-Ahead)

A read-ahead request is an I/O request to prefetch multiple pages in the buffer pool asynchronously, in anticipation that these pages will be needed soon. The requests bring in all the pages in one extent. InnoDB uses two read-ahead algorithms to improve I/O performance:

预读请求是一种I/O的请求,以异步方式从buffer pool中预读取多个将来锁需要的数据页。这个请求会把所有的数据页放到一个extent里面。InnoDB会使用两种预读的算法来改善I/O性能:

Linear read-ahead is a technique that predicts what pages might be needed soon based on pages in the buffer pool being accessed sequentially. You control when InnoDB performs a read-ahead operation by adjusting the number of sequential page accesses required to trigger an asynchronous read request, using the configuration parameter innodb_read_ahead_threshold. Before this parameter was added, InnoDB would only calculate whether to issue an asynchronous prefetch request for the entire next extent when it read in the last page of the current extent.

线性(Linear)预读方式是基于那些顺序访问的已经存在在buffer pool里面数据页来预测那些将来可能需要的数据页。当InnoDB在执行一个预读操作的时候,你可以通过使用配置参数innodb_read_ahead_threshold来调整顺序访问数据页的数量来控制触发一个异步读的请求。在添加这个参数之前,InnoDB只会计算是否要在读当前extent的最后一个数据页的时候是否要为下个extent执行异步预读请求。

The configuration parameter innodb_read_ahead_threshold controls how sensitive InnoDB is in detecting patterns of sequential page access. If the number of pages read sequentially from an extent is greater than or equal to innodb_read_ahead_threshold, InnoDB initiates an asynchronous read-ahead operation of the entire following extent. It can be set to any value from 0-64. The default value is 56. The higher the value, the more strict the access pattern check. For example, if you set the value to 48, InnoDB triggers a linear read-ahead request only when 48 pages in the current extent have been accessed sequentially. If the value is 8, InnoDB would trigger an asynchronous read-ahead even if as few as 8 pages in the extent were accessed sequentially. You can set the value of this parameter in the MySQL configuration file, or change it dynamically with the SET GLOBAL command, which requires the SUPER privilege.

配置参数innodb_read_ahead_threshold控制了InnoDB顺序数据页访问检测模式的敏感度。如果一个extent里面顺序读取的数据页的数量大于或者等于innodb_read_ahead_threshold定义的数量,InnoDB就会为后面的extent启动异步的预读操作。这个参数的值可以设置为0-64之间的任何值,默认的是56.值越高,访问检测的模式越严格。例如,你设置的值是48,InnoDB只会在当前extent有48个数据页被顺序访问了才会触发一个线性的预读请求。如果值是8,即使extent里面只有8个数据页被顺序访问也会触发一个异步的预读请求。你可以在MySQL的配置文件里设置这个参数,或者使用SET GLOBAL命令动态修改,当然这是需要SUPER权限的。

Random read-ahead is a technique that predicts when pages might be needed soon based on pages already in the buffer pool, regardless of the order in which those pages were read. If 13 consecutive pages from the same extent are found in the buffer pool, InnoDB asynchronously issues a request to prefetch the remaining pages of the extent. To enable this feature, set the configuration variable innodb_random_read_ahead to ON.

随机(Random)预读也是基于buffer pool里面的数据页对不久之后需要的数据页进行预测的,但是它不会管buffer pool里面那些数据页被读取的顺序。如果在buffer pool里面看到同一个extent里面有13个连续的数据页,InnoDB就会会这个extent剩下的数据页异步地执行一个预读请求。要开启这个特性,则需要把配置变量innodb_random_read_ahead设置成ON(默认是OFF)。

The SHOW ENGINE INNODB STATUS command displays statistics to help you evaluate the effectiveness of the read-ahead algorithm. Statistics include counter information for the Innodb_buffer_pool_read_ahead, Innodb_buffer_pool_read_ahead_evicted, and Innodb_buffer_pool_read_ahead_rnd global status variables. This information can be useful when fine-tuning the innodb_random_read_ahead setting.

SHOW ENGINE INNODB STATUS命令显示的统计信息能够帮助你评估预读算法的效能。统计信息包含了Innodb_buffer_pool_read_ahead, Innodb_buffer_pool_read_ahead_evicted, and Innodb_buffer_pool_read_ahead_rnd这几个全局状态变量的计数信息。这些信息对微调innodb_random_read_ahead的设定是非常有用的。

For more information about I/O performance, see Section 8.5.8, "Optimizing InnoDB Disk I/O" and Section 8.12.3, "Optimizing Disk I/O".

更多关于I/O性能的信息可以查看Section 8.5.8, "Optimizing InnoDB Disk I/O" and Section 8.12.3, "Optimizing Disk I/O"。

14.4.3.2 Configuring the Rate of InnoDB Buffer Pool Flushing

InnoDB performs certain tasks in the background, including flushing of dirty pages (those pages that have been changed but are not yet written to the database files) from the buffer pool. InnoDB flushes buffer pool pages if the percentage of dirty pages in the buffer pool exceeds innodb_max_dirty_pages_pct. As of MySQL 5.7.5, InnoDB flushes buffer pool pages if the percentage of dirty pages in the buffer pool is greater than or equal to innodb_max_dirty_pages_pct (Bug#13029450).

InnoDB会在后台执行某些任务,这其中就包括从buffer pool中刷新脏数据页(已经被修改了的但是还未写入到数据库文件的数据页)。如果buffer pool中的脏数据的百分比达到innodb_max_dirty_pages_pct所设定的值InnoDB就会刷新buffer pool中的数据页。从MySQL5.7.5开始,如果buffer pool中脏数据的百分比大于或者等于innodb_max_dirty_pages_pct所设定的值InnoDB就会刷新buffer pool的数据页(Bug#13029450)。

InnoDB uses an algorithm to estimate the required rate of flushing, based on the speed of redo log generation and the current rate of flushing. The intent is to smooth overall performance by ensuring that buffer flush activity keeps up with the need to keep the buffer pool "clean". Automatically adjusting the rate of flushing can help to avoid sudden dips in throughput, when excessive buffer pool flushing limits the I/O capacity available for ordinary read and write activity.

InnoDB会基于redo log产生的速度和当前刷新的比例来估算请求的刷新比例。这样做的目的是通过确保buffer刷新的动作让buffer pool保持"干净(clean)"来平滑整体的性能。自动调整刷新比例能够在过多的buffer pool刷新操作限制普通读写操作的I/O能力时候避免突然的吞吐量的下降。

InnoDB uses its log files in a circular fashion. Before reusing a portion of a log file, InnoDB flushes to disk all dirty buffer pool pages whose redo entries are contained in that portion of the log file, a process known as a sharp checkpoint. If a workload is write-intensive, it generates a lot of redo information, all written to the log file. If all available space in the log files is used up, a sharp checkpoint occurs, causing a temporary reduction in throughput. This situation can happen even though innodb_max_dirty_pages_pct is not reached.

InnoDB以循环的方式使用日志文件。在再利用一个日志文件的一部分之前,InnoDB会刷新这部分redo log上的脏buffer pool数据到磁盘上,这个操作称之为sharp checkpoint。如果负载是写密集型的,会产生大量的redo信息,这些信息都会写入到日志文件里。如果日志文件里面可用空间都用完了,就会发生sharp checkpoint,这就会引起临时性的吞吐量下降。即使还没有达到innodb_max_dirty_pages_pct设定的值这种情况还是会发生的。

InnoDB uses a heuristic-based algorithm to avoid such a scenario, by measuring the number of dirty pages in the buffer pool and the rate at which redo is being generated. Based on these numbers, InnoDB decides how many dirty pages to flush from the buffer pool each second. This self-adapting algorithm is able to deal with sudden changes in the workload.

InnoDB使用了一种基于启发式的算法来避免这一情况:测量buffer pool中脏数据页的数量以及redo产生的比例。基于这些数字,InnoDB决定每秒钟要重buffer pool中刷新多少的脏数据页。这种自适应的算法能够处理负载突然变化的情况。

Internal benchmarking has also shown that this algorithm not only maintains throughput over time, but can also improve overall throughput significantly.

内部标杆也显示出这种算法不仅仅能够维护不同时间的吞吐量,还能显著改善整体的吞吐量。

Because adaptive flushing can significantly affect the I/O pattern of a workload, the innodb_adaptive_flushing configuration parameter lets you turn off this feature. The default value for innodb_adaptive_flushing is TRUE, enabling the adaptive flushing algorithm. You can set the value of this parameter in the MySQL option file (my.cnf or my.ini) or change it dynamically with the SET GLOBAL command, which requires the SUPER privilege.

因为自适应刷新能够明显影响工作负载的I/O模式,innodb_adaptive_flushing配置参数能够让你关闭这一特性。innodb_adaptive_flushing默认的值是TRUE,是开启是适应刷新算法的。你可以在MySQL的配置文件或者SET GLOBAL命名动态地设置这个参数的值,当然这是需要SUPER权限的。

For more information about InnoDB I/O performance, see Section 8.5.8, "Optimizing InnoDB Disk I/O".

更多关于InnoDB I/0性能的信息可以查看Section 8.5.8, "Optimizing InnoDB Disk I/O"。

14.4.3.3 Making the Buffer Pool Scan Resistant

Rather than using a strictly LRU algorithm, InnoDB uses a technique to minimize the amount of data that is brought into the buffer pool and never accessed again. The goal is to make sure that frequently accessed ("hot") pages remain in the buffer pool, even as read-ahead and full table scans bring in new blocks that might or might not be accessed afterward.

相比使用严格的LRU算法,InnoDB会使用一种算法来最小化把那些不会再被访问的数据带出buffer pool。主要的目标是当预读和全表扫描会带进来一些可能不会再访问的新数据页的时候,还要确保那些频繁访问的("热")数据页保留在buffer pool里。

Newly read blocks are inserted into the middle of the LRU list. All newly read pages are inserted at a location that by default is 3/8 from the tail of the LRU list. The pages are moved to the front of the list (the most-recently used end) when they are accessed in the buffer pool for the first time. Thus pages that are never accessed never make it to the front portion of the LRU list, and "age out" sooner than with a strict LRU approach. This arrangement divides the LRU list into two segments, where the pages downstream of the insertion point are considered "old" and are desirable victims for LRU eviction.

最近读取的数据页会插入到LRU列表的中间位置。所有新读取的数据页会被插入到LRU列表尾部的默认的3/8的位置。当这些buffer pool中的数据页第一次被访问的时候会移动到列表的前部(最近使用的尾端)。因此不再使用的数据页就不会到LRU列表的前部,而且相比严格的LRU算法会更早地"淡"出列表。这种布置把LRU列表分割成了两部分,插入点下游的数据页会被看成"旧"的数据而被驱逐出LRU列表。

For an explanation of the inner workings of the InnoDB buffer pool and the specifics of its LRU replacement algorithm, see Section 8.10.1, "The InnoDB Buffer Pool".

对于InnoDB buffer pool内部工作原理和其LRU替换算法的细节,可以查看Section 8.10.1, "The InnoDB Buffer Pool"。

You can control the insertion point in the LRU list, and choose whether InnoDB applies the same optimization to blocks brought into the buffer pool by table or index scans. The configuration parameter innodb_old_blocks_pct controls the percentage of "old" blocks in the LRU list. The default value of innodb_old_blocks_pct is 37, corresponding to the original fixed ratio of 3/8. The value range is 5 (new pages in the buffer pool age out very quickly) to 95 (only 5% of the buffer pool is reserved for hot pages, making the algorithm close to the familiar LRU strategy).

你可以控制LRU列表的插入点,并选择让InnoDB是通过表还是索引扫描来把相同的优化数据页带入到buffer pool里。控制参数innodb_old_blocks_pct控制了LRU列表的"旧"数据页的百分比,默认值是37,相当于原始的3/8。这个值可以设定到5(buffer pool里的新数据页非常快就会被清除出去)到95(buffer pool里面只有 5%保留为热数据页,使得这种算法接近于通常的LRU方式)之间。

The optimization that keeps the buffer pool from being churned by read-ahead can avoid similar problems due to table or index scans. In these scans, a data page is typically accessed a few times in quick succession and is never touched again. The configuration parameter innodb_old_blocks_time specifies the time window (in milliseconds) after the first access to a page during which it can be accessed without being moved to the front (most-recently used end) of the LRU list. The default value of innodb_old_blocks_time is 1000. Increasing this value makes more and more blocks likely to age out faster from the buffer pool.

通过预读预防buffer pool被搅拌的优化方式可以避免因表或者索引扫描带来类似的问题。在这些扫描里,一个数据页通常会被接连几次访问,而在那之后就不再会被访问了。配置参数innodb_old_blocks_time指定了一个数据页在第一次访问之后多久(毫秒级)而不会移动到LRU列表的前部(最近使用的尾端),默认值是1000。增加这个值会使得越来越多的数据页迅速从buffer pool里淡出去。

Both innodb_old_blocks_pct and innodb_old_blocks_time are dynamic, global and can be specified in the MySQL option file (my.cnf or my.ini) or changed at runtime with the SET GLOBAL command. Changing the setting requires the SUPER privilege.

innodb_old_blocks_pct and innodb_old_blocks_time都是动态的,可以在MySQL的配置文件里指定或者用SET GLOBAL命令来设置,当让也是要有SUPER权限的。

To help you gauge the effect of setting these parameters, the SHOW ENGINE INNODB STATUS command reports additional statistics. The BUFFER POOL AND MEMORY section looks like:

为了帮助你测量这些参数的影响,可以通过SHOW ENGINE INNODB STATUS命令来列出额外的统计信息。BUFFER POOL AND MEMORY章节的内容如下:

Total memory allocated 1107296256; in additional pool allocated 0

Dictionary memory allocated 80360

Buffer pool size 65535

Free buffers 0

Database pages 63920

Old database pages 23600

Modified db pages 34969

Pending reads 32

Pending writes: LRU 0, flush list 0, single page 0

Pages made young 414946, not young 2930673

1274.75 youngs/s, 16521.90 non-youngs/s

Pages read 486005, created 3178, written 160585

2132.37 reads/s, 3.40 creates/s, 323.74 writes/s

Buffer pool hit rate 950 / 1000, young-making rate 30 / 1000 not 392 / 1000

Pages read ahead 1510.10/s, evicted without access 0.00/s

LRU len: 63920, unzip_LRU len: 0

I/O sum[43690]:cur[221], unzip sum[0]:cur[0]

Old database pages is the number of pages in the "old" segment of the LRU list.
Old database pages指的是LRU列表里"旧"的段的数据页的数量。
Pages made young and not young is the total number of "old" pages that have been made young or not respectively.
Pages made young and not young分别指的是变得(or not)新的"旧"数据页的数量。
youngs/s and non-young/s is the rate at which page accesses to the "old" pages have resulted in making such pages young or otherwise respectively since the last invocation of the command.
youngs/s and non-young/s表示自上次调用以来访问旧数据页而导致这些数据页变新(or not)的比例。
young-making rate and not provides the same rate but in terms of overall buffer pool accesses instead of accesses just to the "old" pages.
young-making rate and not提供了相同的比例,但是只的是整个的buffer pool而不只是访问的旧的数据页。

Note

Per second averages provided in InnoDB Monitor output are based on the elapsed time between the current time and the last time InnoDB Monitor output was printed.

InnoDB Monitor输出的每秒平均值是基于当前的时间和上次InnoDB Monitor打印输出的所消逝的时间。

Because the effects of these parameters can vary widely based on your hardware configuration, your data, and the details of your workload, always benchmark to verify the effectiveness before changing these settings in any performance-critical or production environment.

因为这些配置基于你的硬件配置,数据,工作负载的细节,影响是非常广泛的,所以要在任何性能关键的生产环境更改这些设置之前,要进行基准测试来验证有效性。

In mixed workloads where most of the activity is OLTP type with periodic batch reporting queries which result in large scans, setting the value of innodb_old_blocks_time during the batch runs can help keep the working set of the normal workload in the buffer pool.

对于混合型的工作负载,绝大多数的活动是OLTP型的,以及周期性的有大量扫描的批量表报查询,可以在运行批处理的时候设置innodb_old_blocks_time的值可以让结果集在普通的工作负载下也保持在buffer pool里面。

When scanning large tables that cannot fit entirely in the buffer pool, setting innodb_old_blocks_pct to a small value keeps the data that is only read once from consuming a significant portion of the buffer pool. For example, setting innodb_old_blocks_pct=5 restricts this data that is only read once to 5% of the buffer pool.

当要扫描大表而无法全部读放入到buffer pool的时候,可以把innodb_old_blocks_pct设置成一个教小的值来阻止那些只会读一次的数据进入到buffer pool消耗很大的那部分。例如,设置innodb_old_blocks_pct=5就可以约束那些只会读一次的数据只会占到buffer pool的5%。

When scanning small tables that do fit into memory, there is less overhead for moving pages around within the buffer pool, so you can leave innodb_old_blocks_pct at its default value, or even higher, such as innodb_old_blocks_pct=50.

当要扫描的小表能够放入到内存的时候,把数据页移动到buffer pool里几乎没有损耗,所以你可以把 innodb_old_blocks_pct设置成默认的值,或者更高,例如innodb_old_blocks_pct=50。

The effect of the innodb_old_blocks_time parameter is harder to predict than the innodb_old_blocks_pct parameter, is relatively small, and varies more with the workload. To arrive at an optimal value, conduct your own benchmarks if the performance improvement from adjusting innodb_old_blocks_pct is not sufficient.

innodb_old_blocks_time参数的影响相比innodb_old_blocks_pct更难预测,相对也更小,对于不同的工作负载变化更大。如果调整innodb_old_blocks_pct性能改善不明显,对innodb_old_blocks_time的修改则要更慎重,最好进行一定的基准测试。

For more information about the InnoDB buffer pool, see Section 8.10.1, "The InnoDB Buffer Pool".

更多关于InnoDB buffer pool的信息可以查看Section 8.10.1, "The InnoDB Buffer Pool"。

14.4.3.4 Using Multiple Buffer Pool Instances

For systems with buffer pools in the multi-gigabyte range, dividing the buffer pool into separate instances can improve concurrency, by reducing contention as different threads read and write to cached pages. This feature is typically intended for systems with a buffer pool size in the multi-gigabyte range. Multiple buffer pool instances are configured using the innodb_buffer_pool_instances configuration option, and you might also adjust the innodb_buffer_pool_size value.

对于一个buffer pool有好几个G的系统,把buffer pool分割成几个实例能够提升并发性,减少不同线程读写cache中数据页的争用。这种特性通常是针对于哪种buffer pool有好几个G的系统。使用innodb_buffer_pool_instances配置参数配置多个buffer pool instance,你也可以调整innodb_buffer_pool_size的值。

When the InnoDB buffer pool is large, many data requests can be satisfied by retrieving from memory. You might encounter bottlenecks from multiple threads trying to access the buffer pool at once. You can enable multiple buffer pools to minimize this contention. Each page that is stored in or read from the buffer pool is assigned to one of the buffer pools randomly, using a hashing function. Each buffer pool manages its own free lists, flush lists, LRUs, and all other data structures connected to a buffer pool, and is protected by its own buffer pool mutex.

当InnoDB buffer pool非常大的时候,要满足很多个对内存里的数据请求。多个线程试图在同一时刻访问buffer pool时可能会遇到瓶颈。你可以开启多个buffer pool来最小化这种争用。每个读取或者存储到buffer pool的数据页会用hash函数随机分配到一个buffer pool里。每个buffer pool读管理它自己的空闲列表,刷新列表,LRU列表,以及连接到buffer pool的其他数据结构,而且它也由它自己的buffer pool mutex来保护。

To enable multiple buffer pool instances, set the innodb_buffer_pool_instances configuration option to a value greater than 1 (the default) up to 64 (the maximum). This option takes effect only when you set the innodb_buffer_pool_size to a size of 1 gigabyte or more. The total size you specify is divided among all the buffer pools. For best efficiency, specify a combination of innodb_buffer_pool_instances and innodb_buffer_pool_size so that each buffer pool instance is at least 1 gigabyte.

要开启多个buffer pool instance,可以把innodb_buffer_pool_instances配置参数设置到1(默认)到64(最大)。这个参数只有在你把innodb_buffer_pool_size设置得大于等于1G的时候才会有影响。你所指定的数值是分割整个buffer pool的数量。要达到最佳的效果,innodb_buffer_pool_instances and innodb_buffer_pool_size值的设定要使得每个buffer pool instance最少有1G。

For more information about the InnoDB buffer pool, see Section 8.10.1, "The InnoDB Buffer Pool".

更多关于InnoDB buffer pool的信息可以查看Section 8.10.1, "The InnoDB Buffer Pool"。

14.4.3.5 Preloading the InnoDB Buffer Pool for Faster Restart

To avoid a lengthy warmup period after restarting the server, particularly for instances with large InnoDB buffer pools, you can save the InnoDB buffer pool state at server shutdown and restore the buffer pool to the same state at server startup.

为了避免在实例重启后冗长的数据预热的过程,特别是对于那些有巨大InnoDB buffer pool的实例,你可以在实例shutdown之前保存InnoDB buffer pool的状态,实例再次启动之后再恢复这个状态。

After you restart a busy server, there is typically a warmup period with steadily increasing throughput, as disk pages that were in the InnoDB buffer pool are brought back into memory (as the same data is queried, updated, and so on). The ability to restore the buffer pool to the pre-shutdown state shortens the warmup period as it allows you to immediately reload disk pages that were in the buffer pool before the restart, rather than waiting for DML operations to access the corresponding rows. The I/O requests can be performed in large batches, making the overall I/O faster. The page loading happens in the background, and does not delay the database startup.

在你重启一个繁忙的实例之后,通常周的数据预热会增加吞吐量,InnoDB buffer pool在磁盘上的数据页需要带回到内存里(查询修改的数据)。保存实例关闭之前buffer pool的状态可以缩短数据预热的时间,这能让你在实例启动之前立刻把磁盘上的数据页重新加载到buffer pool里,而不需要等待DML操作去访问相关的行记录。这里的I/O请求都是批量处理的,这会使得整体的I/O速度更快。数据页的加载是在后台运行的,所以不会延迟数据库的启动时间。

In addition to saving the buffer pool state at shutdown and restoring it at startup, you can also save and restore the buffer pool state at any time, while the server is running. For example, you might save the state of the buffer pool after reaching a stable throughput under a steady workload. You might restore the previous buffer pool state after running reports or maintenance jobs that bring data pages into the buffer pool that are only needed during the time period for those operations, or after some other period with a non-typical workload.

另外你也可以在任何时候保存恢复buffer pool的状态,只要实例是运行着的。例如,你可以在稳固工作负载下达到一个稳定的吞吐量之后保存buffer pool的 状态,在那些周期性的运行报表或者数据维护(这些操作会使得原先的数据页清出buffer pool)之后再恢复之前保存的状态,又或者在其他的周期性的非正常负载之后恢复。

Although the buffer pool itself could be many gigabytes in size, the data that InnoDB saves on disk is tiny by comparison. Only tablespace IDs and page IDs necessary to locate the appropriate pages are saved to disk. This information is derived from the INNODB_BUFFER_PAGE_LRU INFORMATION_SCHEMA table. By default, tablespace ID and page ID data is saved in a file named ib_buffer_pool, which is saved to the InnoDB data directory. The file name can be modified using the innodb_buffer_pool_filename configuration parameter.

虽然buffer pool自身可能有好几个G,但是InnoDB保存在磁盘上数据是非常小的。只有那些保存表空间IDs和数据页IDs的数据页会保存到磁盘上。这些信息通过INNODB_BUFFER_PAGE_LRU INFORMATION_SCHEMA表是可以得到的。默认情况下,表空间ID和数据页ID的信息会保存在一个叫做ib_buffer_pool的文件里,这个文件保存在InnoDB数据目录里。这个文件名可以通过innodb_buffer_pool_filename配置参数更改。

Because the data is cached in and aged out of the buffer pool as it is with regular database operations, there is no problem if the disk pages are recently updated, or if a DML operation involves data that has not yet been loaded. The loading mechanism skips requested pages that no longer exist.

因为数据会通过相关的数据库操作缓存入或者淡出buffer pool,所以数据页刚刚被修改过,或者DML操作相关的数据还未被加载这些情况都不是问题。数据加载机制会跳过那些不存在的数据请求。

The underlying mechanism involves a background thread that is dispatched to perform the dump and load operations.

潜在机制涉及的后台线程会执行相关的导出和加载操作。

Disk pages from compressed tables are loaded into the buffer pool in their compressed form. Uncompression happens as usual when the page contents are accessed during the course of DML operations. Because decompression is a CPU-intensive process, it is more efficient for concurrency to perform the operation in one of the connection threads rather than in the single thread that performs the buffer pool restore operation.

压缩过的表里的数据页会以它们压缩后的形式加载到buffer pool里。通过DML操作访问的数据页的内容是不会压缩的。因为解压是一个CPU密集的操作,相比在一个线程里执行buffer pool的恢复操作,在连接线程里并发执行则会更有效率。

Saving the Buffer Pool State

To save the state of the InnoDB buffer pool at server shutdown, issue the statement:

实例shutdown的时候保存InnoDB buffer pool的状态:

SET GLOBAL innodb_buffer_pool_dump_at_shutdown=ON;

To save the state of the InnoDB buffer pool while MySQL server is running, issue the statement:

MySQL服务正在运行的时候保存InnoDB buffer pool的状态:

SET GLOBAL innodb_buffer_pool_dump_now=ON;

Restoring the Buffer Pool State

To restore the InnoDB buffer pool state at server startup, specify the --innodb_buffer_pool_load_at_startup option when starting the server:

在实例启动的时候恢复InnoDB buffer pool的状态:

mysqld --innodb_buffer_pool_load_at_startup=ON;

To restore the InnoDB buffer pool state while MySQL is running, issue the statement:

MySQL服务正在运行的时候恢复InnoDB buffer pool的状态:

SET GLOBAL innodb_buffer_pool_load_now=ON;

Displaying Buffer Pool Dump Progress

To display progress when saving the InnoDB buffer pool state to disk, use one of the following options:

用下面的命令显示保存InnoDB buffer pool的进展:

SHOW STATUS LIKE 'Innodb_buffer_pool_dump_status';

or:

SELECT variable_value FROM information_schema.global_status WHERE

variable_name = 'INNODB_BUFFER_POOL_DUMP_STATUS';

If the operation has not yet started, "not started" is returned. If the operation is complete, the completion time is printed (e.g. Finished at 110505 12:18:02). If the operation is in progress, status information is provided (e.g. Dumping buffer pool 5/7, page 237/2873).

如果操作还未开始,则会返回"not started"。如果操作已经完成了,会打印出完成的时间(e.g. Finished at 110505 12:18:02)。如果操作正在处理,则会提供相关的信息状态(e.g. Dumping buffer pool 5/7, page 237/2873)。

Displaying Buffer Pool Load Progress

To display progress when loading the InnoDB buffer pool, use one of the following options:

使用下面的命令加载InnoDB buffer pool的进展:

SHOW STATUS LIKE 'Innodb_buffer_pool_load_status';

or:

SELECT variable_value FROM information_schema.global_status WHERE

variable_name = 'INNODB_BUFFER_POOL_LOAD_STATUS';

If the operation has not yet started, "not started" is returned. If the operation is complete, the completion time is printed (e.g. Finished at 110505 12:23:24). If the operation is in progress, status information is provided (e.g. Loaded 123/22301 pages).

如果操作还未开始,返回"not started"。如果操作已经完成了,打印完成的时间(e.g. Finished at 110505 12:23:24)。如果操作正在进行,显示相关的状态信息(e.g. Loaded 123/22301 pages)。

Aborting a Buffer Pool Load

To abort a buffer pool load operation, issue the statement:

执行下面的语句终止buffer pool的加载:

SET GLOBAL innodb_buffer_pool_load_abort=ON;

14.4.3.5.1 Monitoring Buffer Pool Load Progress Using Performance Schema

As of MySQL 5.7.6, you can monitor buffer pool load progress using Performance Schema.

从MySQL5.7.6开始,可以使用Performance Schema监控buffer pool的加载进展。

The following example demonstrates how to enable the stage/innodb/buffer pool load stage event instrument and related consumer tables to monitor buffer pool load progress.

下面的例子演示了如何开启stage/innodb/buffer pool加载阶段的时间工具,以及相关的表来监控buffer pool的加载进展。

For information about buffer pool dump and load procedures used in this example, see Section 14.4.3.5, "Preloading the InnoDB Buffer Pool for Faster Restart". For information about Performance Schema stage event instruments and related consumers, see Section 22.9.5, "Performance Schema Stage Event Tables".

使用这个例子导出,加载buffer pool的信息可以查看Section 14.4.3.5, "Preloading the InnoDB Buffer Pool for Faster Restart"。关于Performance Schema的阶段时间工具和相关表可以查看Section 22.9.5, "Performance Schema Stage Event Tables"。

1.Enable the stage/innodb/buffer pool load instrument:

1.开启stage/innodb/buffer pool load工具:

mysql> UPDATE setup_instruments SET ENABLED = 'YES' WHERE NAME LIKE 'stage/innodb/buffer%';

Query OK, 1 row affected (0.00 sec)

Rows matched: 1 Changed: 1 Warnings: 0

2.Enable the stage event consumer tables, which include events_stages_current, events_stages_history, and events_stages_history_long.

2.开启阶段事件表,这里面包括了events_stages_current, events_stages_history, and events_stages_history_long。

mysql> UPDATE setup_consumers SET ENABLED = 'YES' WHERE NAME LIKE '%stages%';

Query OK, 3 rows affected (0.00 sec)

Rows matched: 3 Changed: 3 Warnings: 0

3.Dump the current buffer pool state by enabling innodb_buffer_pool_dump_now.

3.通过开启innodb_buffer_pool_dump_now导出当前buffer pool的状态.

mysql> SET GLOBAL innodb_buffer_pool_dump_now=ON;

Query OK, 0 rows affected (0.00 sec)

4.Check the buffer pool dump status to ensure that the operation has completed.

4.检查buffer pool导出的状态来确认操作是否已完成。

mysql> SHOW STATUS LIKE 'Innodb_buffer_pool_dump_status'\G

*************************** 1. row ***************************

Variable_name: Innodb_buffer_pool_dump_status

Value: Buffer pool(s) dump completed at 150202 16:38:58

5.Load the buffer pool by enabling innodb_buffer_pool_load_now:

5.通过开启innodb_buffer_pool_load_now加载buffer pool:

mysql> SET GLOBAL innodb_buffer_pool_load_now=ON;

Query OK, 0 rows affected (0.01 sec)

6.Check the current status of the buffer pool load operation by querying the Performance Schema events_stages_current table. The WORK_COMPLETED column shows the number of buffer pool pages loaded. The WORK_ESTIMATED column provides an estimate of the remaining work, in pages.

6.通过查询Performance Schema的events_stages_current表来检查buffer pool加载操作的当前状态。WORK_COMPLETED列显示了buffer pool加载数据页的数量。WORK_ESTIMATED显示了预估了剩余工作量(单位是数据页)

mysql> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM events_stages_current;

+-------------------------------+----------------+----------------+

| EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED |

+-------------------------------+----------------+----------------+

| stage/innodb/buffer pool load | 5353 | 7167 |

+-------------------------------+----------------+----------------+

The events_stages_current table returns an empty set if the buffer pool load operation has completed. In this case, you can check the events_stages_history table to view data for the completed event. For example:

如果buffer pool的加载工作已经完成了,那么events_stages_current表返回的是空集。在这种情况下,你可以检查events_stages_history表来查看已经完成事件的数据。例如:

mysql> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED FROM events_stages_history;

+-------------------------------+----------------+----------------+

| EVENT_NAME | WORK_COMPLETED | WORK_ESTIMATED |

+-------------------------------+----------------+----------------+

| stage/innodb/buffer pool load | 7167 | 7167 |

+-------------------------------+----------------+----------------+

Note

You can also monitor buffer pool load progress using Performance Schema when loading the buffer pool at startup using innodb_buffer_pool_load_at_startup. In this case, the stage/innodb/buffer pool load instrument and related consumers must also be enabled at startup. For more information, see Section 22.2.2, "Performance Schema Startup Configuration".

你还可以使用Performance Schema监控使用innodb_buffer_pool_load_at_startup在实例启动的时候加载buffer pool的进展。在这种情况下,stage/innodb/buffer pool load工具和相关的表也必须要在启动的时候开启。更多相关的信息可以查看Section 22.2.2, "Performance Schema Startup Configuration"。

14.4.3.6 Tuning InnoDB Buffer Pool Flushing

The configuration options innodb_flush_neighbors and innodb_lru_scan_depth let you fine-tune certain aspects of the flushing process for the InnoDB buffer pool. These options primarily help write-intensive workloads. With heavy DML activity, flushing can fall behind if it is not aggressive enough, resulting in excessive memory use in the buffer pool; or, disk writes due to flushing can saturate your I/O capacity if that mechanism is too aggressive. The ideal settings depend on your workload, data access patterns, and storage configuration (for example, whether data is stored on HDD or SSD devices).

innodb_flush_neighbors and innodb_lru_scan_depth配置参数能够让你微调InnoDB buffer pool刷新进程的某一方面。这些参数主要用在写密集型的情况。在繁忙的DML活动的情况下,如果不够积极的话会使得刷新操作落后,而导致buffer pool使用过多的内存;又或者机制过于激进,刷新过程中的磁盘写操作又会使得I/O能力趋于饱和。理想的设定需要取决于你的负载情况,数据访问的模式,以及存储的配置(例如,数据是存储在HDD上还是SSD上)。

For systems with constant heavy workloads, or workloads that fluctuate widely, several configuration options let you fine-tune the flushing behavior for InnoDB tables: innodb_adaptive_flushing_lwm, innodb_max_dirty_pages_pct_lwm, innodb_io_capacity_max, and innodb_flushing_avg_loops. These options feed into the formula used by the innodb_adaptive_flushing option.

对于工作负载一直很高的系统,或者负载的浮动很大,有好几个配置参数可以让你微调InnoDB表的刷新行为:innodb_adaptive_flushing_lwm, innodb_max_dirty_pages_pct_lwm, innodb_io_capacity_max, and innodb_flushing_avg_loops。这些参数可以融入到the innodb_adaptive_flushing所使用的公式里。

The innodb_adaptive_flushing, innodb_io_capacity and innodb_max_dirty_pages_pct options are limited or extended by the following options: innodb_adaptive_flushing_lwm, innodb_io_capacity_max and innodb_max_dirty_pages_pct_lwm:

innodb_adaptive_flushing, innodb_io_capacity and innodb_max_dirty_pages_pct参数可以通过下面的参数进行限制或者扩展:innodb_adaptive_flushing_lwm, innodb_io_capacity_max and innodb_max_dirty_pages_pct_lwm:

The InnoDB adaptive flushing mechanism is not appropriate in all cases. It gives the most benefit when the redo log is in danger of filling up. The innodb_adaptive_flushing_lwm option specifies a "low water mark" percentage of redo log capacity; when that threshold is crossed, InnoDB turns on adaptive flushing even if not specified by the innodb_adaptive_flushing option.
InnoDB自适应的刷新机制并不适合所有的情况,它能最大化对redo log的填充阻塞时的利益。innodb_adaptive_flushing_lwm参数指定了一个redo log能力的"low water mark"百分比;当阀值超过了,InnoDB会打开自适应的刷新即使是innodb_adaptive_flushing没有指定。
If flushing activity falls far behind, InnoDB can flush more aggressively than specified by innodb_io_capacity. innodb_io_capacity_max represents an upper limit on the I/O capacity used in such emergency situations, so that the spike in I/O does not consume all the capacity of the server.
如果刷新活动远远落后了,InnoDB的刷新动作会比innodb_io_capacity所指定的更积极。innodb_io_capacity_max代表了紧急情况I/O能力的上限,所以这不会耗尽服务器所有的I/O能力。
InnoDB tries to flush data from the buffer pool so that the percentage of dirty pages does not exceed the value of innodb_max_dirty_pages_pct. The default value for innodb_max_dirty_pages_pct is 75.
InnoDB会试图从buffer pool里刷新数据,所以脏数据页的百分比不会达到innodb_max_dirty_pages_pct所设定的值。innodb_max_dirty_pages_pct默认的是75。

Note

The innodb_max_dirty_pages_pct setting establishes a target for flushing activity. It does not affect the rate of flushing. For information about managing the rate of flushing, see Section 14.4.3.2, "Configuring the Rate of InnoDB Buffer Pool Flushing".

innodb_max_dirty_pages_pct设定建立了一个刷新活动的目标。它不会影响刷新的速度。管理刷新速度的信息可以查看Section 14.4.3.2, "Configuring the Rate of InnoDB Buffer Pool Flushing"。

The innodb_max_dirty_pages_pct_lwm option specifies a "low water mark" value that represents the percentage of dirty pages where pre-flushing is enabled to control the dirty page ratio and ideally prevent the percentage of dirty pages from reaching innodb_max_dirty_pages_pct. A value of innodb_max_dirty_pages_pct_lwm=0 disables the "pre-flushing" behavior.

innodb_max_dirty_pages_pct_lwm参数指定了一个"low water mark"值来表示脏数据页的百分比:开启预刷新来控制脏数据页的比例,尽可能阻止脏数据页的百分比达到innodb_max_dirty_pages_pct所设定的值。innodb_max_dirty_pages_pct_lwm=0(默认值)表示关闭"预刷新"的行为。

Most of the options referenced above are most applicable to servers that run write-heavy workloads for long periods of time and have little reduced load time to catch up with changes waiting to be written to disk.

上文提到的参数最适合于大量写操作的环境:运行时间很长,几乎无法减少加载时间来赶上等待的修改数据写入到磁盘里。

innodb_flushing_avg_loops defines the number of iterations for which InnoDB keeps the previously calculated snapshot of the flushing state, which controls how quickly adaptive flushing responds to foreground load changes. Setting a high value for innodb_flushing_avg_loops means that InnoDB keeps the previously calculated snapshot longer, so adaptive flushing responds more slowly. A high value also reduces positive feedback between foreground and background work, but when setting a high value it is important to ensure that InnoDB redo log utilization does not reach 75% (the hardcoded limit at which async flushing starts) and that the innodb_max_dirty_pages_pct setting keeps the number of dirty pages to a level that is appropriate for the workload.

innodb_flushing_avg_loops定义了InnoDB之前评估刷新状态快照的迭代的数量,这就控制了自适应刷新多快会响应前台加载的变化。对innodb_flushing_avg_loops设置一个更高的值意味着InnoDB保持之前评估的快照越久,,自适应刷新响应得越慢。比较高的值还会减少前后台工作之间的积极反馈,但同时也对确保一下情况是非常重要的:InnoDB redo log的利用率不会达到75%(这是一个写死的限制当开始异步刷新时候);innodb_max_dirty_pages_pct设定的脏数据页的数量适合与工作负载。

Systems with consistent workloads, a large innodb_log_file_size, and small spikes that do not reach 75% redo log space utilization should use a high innodb_flushing_avg_loops value to keep flushing as smooth as possible. For systems with extreme load spikes or log files that do not provide a lot of space, consider a smaller innodb_flushing_avg_loops value. The smaller value will allow flushing to closely track the load and help avoid reaching 75% redo log space utilization.

对于工作量比较平稳的系统,innodb_log_file_size的值也比较大,小的高峰也不会达到redo log 75%的空间利用限制则可以把innodb_flushing_avg_loops设一个比较高的值,这会使得刷新操作尽可能地光滑。对于系统的负载波动比较大的情况或者日志文件比较小的情况,则可以考虑使用一个较小的innodb_flushing_avg_loops值,这能够使得刷新操作紧跟这工作负载的变化而避免达到75%的redo log空间利用率的限制。

14.4.4 Configuring the Memory Allocator for InnoDB

When InnoDB was developed, the memory allocators supplied with operating systems and run-time libraries were often lacking in performance and scalability. At that time, there were no memory allocator libraries tuned for multi-core CPUs. Therefore, InnoDB implemented its own memory allocator in the mem subsystem. This allocator is guarded by a single mutex, which may become a bottleneck. InnoDB also implements a wrapper interface around the system allocator (malloc and free) that is likewise guarded by a single mutex.

在InnoDB的开发阶段,内存分配器是由操作系统和运行库提供了,这经常会限制性能和可扩展性。在那个时候,没有用于多核CPU的内存分配库。因此,在mem子系统里InnoDB使用了它自身的内存分配器。这个分配器通过单个mutex来守护的,这也就造成了瓶颈。InnoDB还会使用系统分配器(malloc and free)的接口,这同样也是由单个mutex守护的。

Today, as multi-core systems have become more widely available, and as operating systems have matured, significant improvements have been made in the memory allocators provided with operating systems. New memory allocators perform better and are more scalable than they were in the past. The leading high-performance memory allocators include Hoard, libumem, mtmalloc, ptmalloc, tbbmalloc, and TCMalloc. Most workloads, especially those where memory is frequently allocated and released (such as multi-table joins), benefit from using a more highly tuned memory allocator as opposed to the internal, InnoDB-specific memory allocator.

现在,多核系统已经变得更为普遍,操作系统的支持也已成熟,其所提供的内存分配器的改善也更为明显。新的内存分配器比之前的执行得更好,更可扩展。领先的高性能内存分配其包括Hoard, libumem, mtmalloc, ptmalloc, tbbmalloc, and TCMalloc。对于大多数的情况,尤其是频繁的内存分配释放(例如多表join),使用InnoDB指定的内存分配器相对于内部提供的可以获得更多的好处。

You can control whether InnoDB uses its own memory allocator or an allocator of the operating system, by setting the value of the system configuration parameter innodb_use_sys_malloc in the MySQL option file (my.cnf or my.ini). If set to ON or 1 (the default), InnoDB uses the malloc and free functions of the underlying system rather than manage memory pools itself. This parameter is not dynamic, and takes effect only when the system is started. To continue to use the InnoDB memory allocator, set innodb_use_sys_malloc to 0.

你可以通过在MySQL的配置文件里设置innodb_use_sys_malloc配置参数来控制InnoDB使用其自身的内存分配器或者是操作系统的分配器。如果设置为ON or 1 (the default),InnoDB会使用底层系统的malloc and free函数不是自己管理内存池。这个参数不是动态的,只有系统启动的时候才会生效。要使用InnoDB的内存分配器,则要把innodb_use_sys_malloc设置为0.

When the InnoDB memory allocator is disabled, InnoDB ignores the value of the parameter innodb_additional_mem_pool_size. The InnoDB memory allocator uses an additional memory pool for satisfying allocation requests without having to fall back to the system memory allocator. When the InnoDB memory allocator is disabled, all such allocation requests are fulfilled by the system memory allocator.

当InnoDB内存分配器关闭的时候,InnoDB会忽略innodb_additional_mem_pool_size的值。InnoDB内存分配器为了满足分配需求会使用额外的内存池,而不需要后退到系统内存分配器。当InnoDB内存分配器关闭了,所有的分配请求都由系统内存分配器来实现。

On Unix-like systems that use dynamic linking, replacing the memory allocator may be as easy as making the environment variable LD_PRELOAD or LD_LIBRARY_PATH point to the dynamic library that implements the allocator. On other systems, some relinking may be necessary. Please refer to the documentation of the memory allocator library of your choice.

在Unix类的系统上会使用动态连接(dynamic linking),替换内存分配器和把环境变量LD_PRELOAD or LD_LIBRARY_PATH指向动态库一样简单,并以此来实现分配器。在其他系统上,则就需要重连接(relinking),并参考你选择的内存分配库的文档。

Since InnoDB cannot track all memory use when the system memory allocator is used (innodb_use_sys_malloc is ON), the section "BUFFER POOL AND MEMORY" in the output of the SHOW ENGINE INNODB STATUS command only includes the buffer pool statistics in the "Total memory allocated". Any memory allocated using the mem subsystem or using ut_malloc is excluded.

因为在使用系统内存分配器的时候无法追踪所有使用的内存,所以SHOW ENGINE INNODB STATUS命令输出的"BUFFER POOL AND MEMORY"部分只包括了"Total memory allocated"里面的buffer pool统计信息。任何使用mem子系统的内存分配器或者使用了ut_malloc的都是被排除在外的。

Note

innodb_use_sys_malloc and innodb_additional_mem_pool_size were deprecated in MySQL 5.6.3 and are removed in MySQL 5.7.4.

innodb_use_sys_malloc and innodb_additional_mem_pool_size已经在MySQL5.6.3被废弃,在MySQL5.7.4已经被移除。

For more information about the performance implications of InnoDB memory usage, see Section 8.10, "Buffering and Caching".

更多关于InnoDB内存使用情况的性能影响的信息可以查看Section 8.10, "Buffering and Caching"。

14.4.5 Configuring InnoDB Change Buffering

14.4.5.1 Configuring the Change Buffer Maximum Size

When INSERT, UPDATE, and DELETE operations are performed on a table, the values of indexed columns (particularly the values of secondary keys) are often in an unsorted order, requiring substantial I/O to bring secondary indexes up to date. InnoDB has a change buffer that caches changes to secondary index entries when the relevant page is not in the buffer pool, thus avoiding expensive I/O operations by not immediately reading in the page from disk. The buffered changes are merged when the page is loaded to the buffer pool, and the updated page is later flushed to disk. The InnoDB main thread merges buffered changes when the server is nearly idle, and during a slow shutdown.

当在一个表上执行INSERT,UPDATE和DELETE操作时,索引列上的值(特别是secondary key的值)通常没有经过排序的,这就需要在最近的secondary index上有大量的I/O。当相关的数据页不在buffer pool的时候,InnoDB用change buffer来缓存secondary index条目的更新,因此可以通过延迟从磁盘读数据页的方式避免了昂贵的I/O操作。缓存的更新在加载到buffer pool的时候会进行合并,并在之后的时间再刷新到磁盘里。当实例在空闲或者慢关闭的时候,InnoDB的主线程会对缓存的更新进行合并。

Because it can result in fewer disk reads and writes, the change buffer feature is most valuable for workloads that are I/O-bound, for example applications with a high volume of DML operations such as bulk inserts.

因为这能够减少磁盘的读写,所以change buffer特性对于高I/O的情况是极为有用的,特别是那些批量insert的大量DML操作。

However, the change buffer occupies a part of the buffer pool, reducing the memory available to cache data pages. If the working set almost fits in the buffer pool, or if your tables have relatively few secondary indexes, it may be useful to disable change buffering. If the working set fits entirely within the buffer, change buffering does not impose extra overhead, because it only applies to pages that are not in the buffer pool.

然而,change buffer会占用buffer pool的一部分空间,而减少了buffer pool缓存数据页的可用内存空间。如果工作集几乎都在buffer pool里,或者表上几乎没有secondary index,那么关闭change buffer则会更有用。如果工作集完全都在buffer pool里了,那么change buffer则不会有额外的损耗,因为它只适用于那些不在buffer pool里的数据页。

You can control the extent to which InnoDB performs change buffering using the innodb_change_buffering configuration parameter. You can enable or disable buffering for inserts, delete operations (when index records are initially marked for deletion) and purge operations (when index records are physically deleted). An update operation is a combination of an insert and a delete. The default innodb_change_buffering value is all.

你可以通过使用innodb_change_buffering配置参数来控制change buffer的程度。你可以关闭或开启对insert,delete(索引记录做了删除标记)操作的缓存,以及purge(物理删除索引记录)操作。update操作可以看成一组insert和delete操作。innodb_change_buffering默认的值是all。

Permitted innodb_change_buffering values include:

innodb_change_buffering允许的值包括:

all

The default value: buffer inserts, delete-marking operations, and purges.

默认值:缓存insert和delete-marking,purge操作。

none

Do not buffer any operations.

不缓存任何操作。

inserts

Buffer insert operations.

缓存insert操作。

deletes

Buffer delete-marking operations.

缓存delete-marking操作。

changes

Buffer both inserts and delete-marking operations.

只缓存insert和delete-marking操作。

purges

Buffer the physical deletion operations that happen in the background.

只缓存发生在后台的物理阐述操作。

You can set the innodb_change_buffering parameter in the MySQL option file (my.cnf or my.ini) or change it dynamically with the SET GLOBAL command, which requires the SUPER privilege. Changing the setting affects the buffering of new operations; the merging of existing buffered entries is not affected.

你可以在MySQL的配置文件或者使用SET GLOBAL动态设置innodb_change_buffering参数,当然这是需要SUPER权限的。修改后的设置会影响新操作的缓存;已存在缓存条目的合并则不会受影响。

For related information, see Section 14.2.5.5, "Change Buffer". For information about configuring change buffer size, see Section 14.4.5.1, "Configuring the Change Buffer Maximum Size".

相关的信息可以查看Section 14.2.5.5, "Change Buffer"。配置change buffer大小的信息可以查看Section 14.4.5.1, "Configuring the Change Buffer Maximum Size"。

14.4.5.1 Configuring the Change Buffer Maximum Size

As of MySQL 5.6.2, the innodb_change_buffer_max_size configuration option allows you to configure the maximum size of the change buffer as a percentage of the total size of the buffer pool. By default, innodb_change_buffer_max_size is set to 25. The maximum setting is 50.

从MySQL5.6.2开始,innodb_change_buffer_max_size配置参数允许你配置change buffer占整个buffer pool的最大百分比。默认情况下,innodb_change_buffer_max_size的值是25。最大可以设置到50。

You might consider increasing innodb_change_buffer_max_size on a MySQL server with heavy insert, update, and delete activity, where change buffer merging does not keep pace with new change buffer entries, causing the change buffer to reach its maximum size limit.

当实例上有很多的insert,update和delete活动的时候,你可以考虑增加innodb_change_buffer_max_size。change buffer的合并操作不会为新的change buffer条目保留空间,这就导致其会达到其最大值的限制。

You might consider decreasing innodb_change_buffer_max_size on a MySQL server with static data used for reporting, or if the change buffer consumes too much of the memory space that is shared with the buffer pool, causing pages to age out of the buffer pool sooner than desired.

对于实例上都是用于报表的静态数据,或者change buffer已经消耗了过多的buffer pool的内存空间(这会引起更多的数据页淡出buffer pool)的情况,你可以考虑减少innodb_change_buffer_max_size的值。

Test different settings with a representative workload to determine an optimal configuration. The innodb_change_buffer_max_size setting is dynamic, which allows you modify the setting without restarting the server.

对于典型的工作环境要测试不同的设置来决定最佳的配置。innodb_change_buffer_max_size的设置是可以动态修改的,这就可以让你在不重启的情况下修改设定。

14.4.6 Configuring Thread Concurrency for InnoDB

InnoDB uses operating system threads to process requests from user transactions. (Transactions may issue many requests to InnoDB before they commit or roll back.) On modern operating systems and servers with multi-core processors, where context switching is efficient, most workloads run well without any limit on the number of concurrent threads. Scalability improvements in MySQL 5.5 and up reduce the need to limit the number of concurrently executing threads inside InnoDB.

InnoDB使用操作系统线程拉处理来自于用户事务的请求。(事务在commit或者rollback之前会向InnoDB发送很多个请求。)现代的操作系统和服务器都支持多核CPU的,context switch也很高效,大多数环境都可以在不对并发线程的数据量做限制的情况下很好地工作。MySQL5.5改善了可扩展性,减少了InnoDB内部在并发执行线程的数量的限制。

In situations where it is helpful to minimize context switching between threads, InnoDB can use a number of techniques to limit the number of concurrently executing operating system threads (and thus the number of requests that are processed at any one time). When InnoDB receives a new request from a user session, if the number of threads concurrently executing is at a pre-defined limit, the new request sleeps for a short time before it tries again. A request that cannot be rescheduled after the sleep is put in a first-in/first-out queue and eventually is processed. Threads waiting for locks are not counted in the number of concurrently executing threads.

InnoDB使用了大量技术来限制操作系统线程并发执行的数量(因此在任何时候都能处理大量的请求),这对减少线程之间的context switch是非常有帮助的。当InnoDB接受到一个来自于用户session的请求,如果线程并发执行的数量已经达到预定义的限制,那么新的请求会在其再次尝试之前随眠一小段时间。请求在睡眠之后会被放入到一个先进先出的队列里,并最终被处理。因为锁等待的线程不会被计入到并发执行线程的数量里。

You can limit the number of concurrent threads by setting the configuration parameter innodb_thread_concurrency. Once the number of executing threads reaches this limit, additional threads sleep for a number of microseconds, set by the configuration parameter innodb_thread_sleep_delay, before being placed into the queue.

你可以通过innodb_thread_concurrency限制并发线程的数量。一旦执行线程的数量达到了这个限制,新的线程就会睡眠及微秒,这个时间可以通过innodb_thread_sleep_delay设定,在这之后就会被放入到队列里。

Previously, it required experimentation to find the optimal value for innodb_thread_sleep_delay, and the optimal value could change depending on the workload. In MySQL 5.6.3 and higher, you can set the configuration option innodb_adaptive_max_sleep_delay to the highest value you would allow for innodb_thread_sleep_delay, and InnoDB automatically adjusts innodb_thread_sleep_delay up or down depending on the current thread-scheduling activity. This dynamic adjustment helps the thread scheduling mechanism to work smoothly during times when the system is lightly loaded and when it is operating near full capacity.

之前,需要做大量的实验来找到innodb_thread_sleep_delay最佳的值,但这个最佳值又会随便工作情况而改变。在MySQL5.6.3及更高的版本里,你可以把innodb_adaptive_max_sleep_delay设置到最高值,让InnoDB根据当前的线程安排自动调整innodb_thread_sleep_delay。动态调整可以在让系统在高负载的情况下,或者操作接近饱和的时候让线程安排机制工作得更平滑。

The default value for innodb_thread_concurrency and the implied default limit on the number of concurrent threads has been changed in various releases of MySQL and InnoDB. The default value of innodb_thread_concurrency is 0, so that by default there is no limit on the number of concurrently executing threads.

innodb_thread_concurrency的默认值对并发线程数量的限制根据MySQL和InnoDB的版本会有不同。当前的默认值是0,表示对并发执行线程的数量没有限制。

InnoDB causes threads to sleep only when the number of concurrent threads is limited. When there is no limit on the number of threads, all contend equally to be scheduled. That is, if innodb_thread_concurrency is 0, the value of innodb_thread_sleep_delay is ignored.

只有在并发线程的数量达到限制的时候InnoDB才会引发线程睡眠。当线程数量没有限制的时候,所有的竞争都会被平等地安排。也就是说,如果innodb_thread_concurrency的值是0,innodb_thread_sleep_delay的值将会被忽略。

When there is a limit on the number of threads (when innodb_thread_concurrency is > 0), InnoDB reduces context switching overhead by permitting multiple requests made during the execution of a single SQL statement to enter InnoDB without observing the limit set by innodb_thread_concurrency. Since an SQL statement (such as a join) may comprise multiple row operations within InnoDB, InnoDB assigns a specified number of "tickets" that allow a thread to be scheduled repeatedly with minimal overhead.

当线程数量是有限制的时候(innodb_thread_concurrency is > 0),InnoDB也会把单个SQL语句的执行分成多个请求进入到InnoDB里来减少context switch的损坏,这期间是不会理会innodb_thread_concurrency的限制的。当一个SQL语句(例如一个join语句)在InnoDB里包含多行操作时,InnoDB会分配一定数量的"tickets",允许一个线程反复被安排而最小化损耗。

When a new SQL statement starts, a thread has no tickets, and it must observe innodb_thread_concurrency. Once the thread is entitled to enter InnoDB, it is assigned a number of tickets that it can use for subsequently entering InnoDB to perform row operations. If the tickets run out, the thread is evicted, and innodb_thread_concurrency is observed again which may place the thread back into the first-in/first-out queue of waiting threads. When the thread is once again entitled to enter InnoDB, tickets are assigned again. The number of tickets assigned is specified by the global option innodb_concurrency_tickets, which is 5000 by default. A thread that is waiting for a lock is given one ticket once the lock becomes available.

当开始一个新的SQL语句的时候,线程是没有ticket的,它必须要遵循innodb_thread_concurrency。一旦这个线程有资格进入到InnoDB里,那它会被分配到一定数量的ticket,它可以反复进入InnoDB执行行操作。如果ticket用完了,这个线程就会被驱赶,innodb_thread_concurrency的限制也会重新其作用,线程也可能会被放回到先进先出的等待队列里。当这个线程一旦再次进入InnoDB里,又会再次被分配到ticket。分配的ticket的数量是由全局参数innodb_concurrency_tickets决定的,默认值是5000。因锁等待的线程一旦可获得锁的时候会得到一个ticket。

The correct values of these variables depend on your environment and workload. Try a range of different values to determine what value works for your applications. Before limiting the number of concurrently executing threads, review configuration options that may improve the performance of InnoDB on multi-core and multi-processor computers, such as innodb_adaptive_hash_index.

这些变量的值正确与否要取决于你当环境和工作量。尝试一个范围内不同的值来确定那组适合于你 的应用程序。在限制并发执行线程的数量之前,回顾这些配置参数或许能够改善多核多处理器上InnoDB的性能,例如innodb_adaptive_hash_index。

For general performance information about MySQL thread handling, see Section 8.12.6.1, "How MySQL Uses Threads for Client Connections".

MySQL线程处理的一般性能信息可以查看Section 8.12.6.1, "How MySQL Uses Threads for Client Connections"。

14.4.7 Configuring the Number of Background InnoDB I/O Threads

InnoDB uses background threads to service various types of I/O requests. You can configure the number of background threads that service read and write I/O on data pages, using the configuration parameters innodb_read_io_threads and innodb_write_io_threads. These parameters signify the number of background threads used for read and write requests respectively. They are effective on all supported platforms. You can set the value of these parameters in the MySQL option file (my.cnf or my.ini); you cannot change them dynamically. The default value for these parameters is 4 and the permissible values range from 1-64.

InnoDB使用后台线程来处理各种类型的I/O请求。你可以使用innodb_read_io_threads and innodb_write_io_threads来配置处理读和写的I/O后台线程的数量。这些参数表示分别用于读和写的后台线程的数量。它们在所有支持的平台上都有效果。你可以在MySQL的配置文件里设置这些参数;但是不能动态修改它们。这些参数的默认值是4,允许的范围是1-64。

The purpose of this change is to make InnoDB more scalable on high end systems. Each background thread can handle up to 256 pending I/O requests. A major source of background I/O is the read-ahead requests. InnoDB tries to balance the load of incoming requests in such way that most of the background threads share work equally. InnoDB also attempts to allocate read requests from the same extent to the same thread to increase the chances of coalescing the requests together. If you have a high end I/O subsystem and you see more than 64 × innodb_read_io_threads pending read requests in SHOW ENGINE INNODB STATUS, you might gain by increasing the value of innodb_read_io_threads.

修改这些参数可以使得InnoDB在高端系统上更具有扩展性。每个后台线程能够处理多达256个I/O请求。后台I/O的主要来源是预读请求。InnoDB会以这样的方式尝试平衡传入请求的负载:大多数后台线程共享同样的工作。InnoDB还会试图把来自相同extent的读请求分配到相同的线程上来增加对请求进行合并的机会。如果你有一个高端的I/O子系统二期在SHOW ENGINE INNODB STATUS里看到有超过64 × innodb_read_io_threads个等待读请求,那么你可以增加innodb_read_io_threads的值。

For more information about InnoDB I/O performance, see Section 8.5.8, "Optimizing InnoDB Disk I/O".

更多关闭InnoDB I/O性能的信息可以查看Section 8.5.8, "Optimizing InnoDB Disk I/O"。

14.4.8 Configuring the InnoDB Master Thread I/O Rate

The master thread in InnoDB is a thread that performs various tasks in the background. Most of these tasks are I/O related, such as flushing dirty pages from the buffer pool or writing changes from the insert buffer to the appropriate secondary indexes. The master thread attempts to perform these tasks in a way that does not adversely affect the normal working of the server. It tries to estimate the free I/O bandwidth available and tune its activities to take advantage of this free capacity. Historically, InnoDB has used a hard coded value of 100 IOPs (input/output operations per second) as the total I/O capacity of the server.

InnoDB的主线程会在后台执行各种不同的任务。这些任务大部分都是I/O相关的,例如从buffer pool里刷新脏数据页或者从insert buffer里把更新内容写入到相关secondary index里。主线程会在尽量不影响实例正常工作的情况下执行这些任务。它会尝试评估I/O空余的可用带宽并调整活动以利用这部分空余的能力。历史上,InnoDB曾经打到过100 IOPs(每秒输入/输出操作的次数)的总I/O能力了。

The parameter innodb_io_capacity indicates the overall I/O capacity available to InnoDB. This parameter should be set to approximately the number of I/O operations that the system can perform per second. The value depends on your system configuration. When innodb_io_capacity is set, the master threads estimates the I/O bandwidth available for background tasks based on the set value. Setting the value to 100 reverts to the old behavior.

参数innodb_io_capacity表明了InnoDB可用的整体的I/O能力。这个参数应该被设置成系统每秒能够执行I/O操作的数量。这个值是要取决于你的系统配置的。当设置了innodb_io_capacity,主线程会基于这个设定的值来为后台任务评估可用的I/O带宽。把这个值设定到100可以恢复到旧的行为。

You can set the value of innodb_io_capacity to any number 100 or greater. The default value is 200, reflecting that the performance of typical modern I/O devices is higher than in the early days of MySQL. Typically, values around the previous default of 100 are appropriate for consumer-level storage devices, such as hard drives up to 7200 RPMs. Faster hard drives, RAID configurations, and SSDs benefit from higher values.

你可以把innodb_io_capacity设置到100以上的任何数。现在的默认的值是 200,这是因为现代磁盘的I/O性能要比以前要高。之前的默认值100是为了适应于普通用户级别的磁盘,例如7200 RPMs的硬盘。对于更快的磁盘,RAID配置,以及SSDs则应该设置一个更高的值。

The innodb_io_capacity setting is a total limit for all buffer pool instances. When dirty pages are flushed, the innodb_io_capacity limit is divided equally among buffer pool instances. For more information, see the innodb_io_capacity system variable description.

innodb_io_capacity设置也是一个对所有buffer pool instance的总限制。当要刷新脏数据页的时候,innodb_io_capacity的限制对buffer pool instance是平等分割的。更多信息可以查看innodb_io_capacity系统变量的描述。

You can set the value of this parameter in the MySQL option file (my.cnf or my.ini) or change it dynamically with the SET GLOBAL command, which requires the SUPER privilege.

你可以在MySQL的配置文件进行设置,或者使用SET GLOBAL进行动态修改,当然这需要SUPER权限。

The innodb_flush_sync configuration option, introduced in MySQL 5.7.8, causes the innodb_io_capacity setting to be ignored during bursts of I/O activity that occur at checkpoints. innodb_flush_sync is enabled by default.

在MySQL5.7.8里面引进innodb_flush_sync配置参数,这会导致当在检查点的时候发生爆发性I/O活动时会忽略innodb_io_capacity的指定。而且innodb_flush_sync默认就是开启的。

Formerly, the InnoDB master thread also performed any needed purge operations. In MySQL 5.6.5 and higher, those I/O operations are moved to other background threads, whose number is controlled by the innodb_purge_threads configuration option.

以前,InnoDB主线程还会执行任何需要purge操作。在MySQL5.6.5及更高的版本里,这些I/O操作已经被移到其他的后台线程上,这些后台线程的数量由innodb_purge_threads配置参数控制。

For more information about InnoDB I/O performance, see Section 8.5.8, "Optimizing InnoDB Disk I/O".

更多关于InnoDB I/O性能的信息可以查看Section 8.5.8, "Optimizing InnoDB Disk I/O"。

14.4.9 Configuring Spin Lock Polling

Many InnoDB mutexes and rw-locks are reserved for a short time. On a multi-core system, it can be more efficient for a thread to continuously check if it can acquire a mutex or rw-lock for a while before sleeping. If the mutex or rw-lock becomes available during this polling period, the thread can continue immediately, in the same time slice. However, too-frequent polling by multiple threads of a shared object can cause "cache ping pong", different processors invalidating portions of each others' cache. InnoDB minimizes this issue by waiting a random time between subsequent polls. The delay is implemented as a busy loop.

很多的InnoDB mutex和rw-lock会被保留一小段时间。在一个多核的平台上,如果一个线程在睡眠之前获取了一个mutex或者rw-lock,进行连续不断的检查会更有效率。如果mutex或者rw-lock在轮询周期内变得可用,在同一时间片上线程能够立刻继续。然而,共享资源上多个线程泰国频繁的轮询也会导致"cache ping pong",不同的处理器会使得批次的部分缓存无效。InnoDB通过在随后的轮询之间等待一段随机的时间来最小化这种问题。这个延迟会以一个繁忙的循环来实现。

You can control the maximum delay between testing a mutex or rw-lock using the parameter innodb_spin_wait_delay. The duration of the delay loop depends on the C compiler and the target processor. (In the 100MHz Pentium era, the unit of delay was one microsecond.) On a system where all processor cores share a fast cache memory, you might reduce the maximum delay or disable the busy loop altogether by setting innodb_spin_wait_delay=0. On a system with multiple processor chips, the effect of cache invalidation can be more significant and you might increase the maximum delay.

你可以通过innodb_spin_wait_delay参数在测试mutex或者rw-lock之间控制最大的延迟时间。延迟循环的持续时间取决于C编译器和目标处理器。(在100MHz Pentium的年代,延迟的单位是一微秒。)在一个所有处理内核都共享一个快速缓存的系统上,你可以减少最大延迟时间或者通过设定innodb_spin_wait_delay=0来关闭整个繁忙的循环。在有多个处理芯片的系统上,缓存失效是非常严重的,你应该增大最大延迟时间。

The default value of innodb_spin_wait_delay is 6. The spin wait delay is a dynamic global parameter that you can specify in the MySQL option file (my.cnf or my.ini) or change at runtime with the command SET GLOBAL innodb_spin_wait_delay=delay, where delay is the desired maximum delay. Changing the setting requires the SUPER privilege.

innodb_spin_wait_delay的默认值是6。旋转等待延迟是一个动态全局参数,你可以在MySQL的配置文件里指定,或者使用SET GLOBAL innodb_spin_wait_delay=delay在运行的时候修改,这里的delay就是描述的最大延迟时间。修改这个设置需要SUPER的权限。

For performance considerations for InnoDB locking operations, see Section 8.11, "Optimizing Locking Operations".

InnoDB锁操作性能上注意事项可以查看Section 8.11, "Optimizing Locking Operations"。

14.4.10 Configuring InnoDB Purge Scheduling

The purge operations (a type of garbage collection) that InnoDB performs automatically is now done in one or more separate threads, rather than as part of the master thread. This change improves scalability, because the main database operations run independently from maintenance work happening in the background.

现在InnoDB会自动在一个或者多个线程上执行purge操作(一种垃圾回收机制),而不是作为主线程的一部分。这种改变改善了可扩展性,因为主要主要的数据库操作会在后台独立于维护工作来运行。

To control this feature, increase the value of the configuration option innodb_purge_threads. If DML action is concentrated on a single table or a few tables, keep the setting low so that the threads do not contend with each other for access to the busy tables. If DML operations are spread across many tables, increase the setting. Its maximum is 32.

要控制这个特性,可以增加innodb_purge_threads配置参数的值。如果DML活动都集中在一个表或者一小部分表上,把设置保持在较低的值可以让线程不会为访问繁忙的表而相互竞争。如果DML操作分散到很多个表上,那么可以增加这个设定值。最大值可以设到32。

There is another related configuration option, innodb_purge_batch_size with a default value of 300 and maximum value of 5000. This option is mainly intended for experimentation and tuning of purge operations, and should not be interesting to typical users.

这里还有另一个相关的配置参数,innodb_purge_batch_size默认值是300,最大值是5000。这个参数主要用于测试和调整purge操作,并不适用于普通用户。

For more information about InnoDB I/O performance, see Section 8.5.8, "Optimizing InnoDB Disk I/O".

更多关闭InnoDB I/O性能的信息可以查看Section 8.5.8, "Optimizing InnoDB Disk I/O"。

14.4.11 Configuring Optimizer Statistics for InnoDB

14.4.11.1 Configuring Persistent Optimizer Statistics Parameters

14.4.11.2 Configuring Non-Persistent Optimizer Statistics Parameters

14.4.11.3 Estimating ANALYZE TABLE Complexity for InnoDB Tables

This section describes how to configure persistent and non-persistent optimizer statistics for InnoDB tables. Persistent optimizer statistics were introduced in MySQL 5.6.2 and were made the default in MySQL 5.6.6 (innodb_stats_persistent=ON).

这一章节描述了如何为InnoDB表配置持久化或者非持久化的优化器统计信息。持久化的优化器统计信息在MySQL5.6.2引入,并在MySQL5.6.6开始作为默认配置(innodb_stats_persistent=ON)。

Persistent optimizer statistics are persisted across server restarts, allowing for greater plan stability and more consistent query performance. Persistent optimizer statistics also provide control and flexibility with these additional benefits:

持久化的优化器统计信息会在实例重启的时候进行持久化,这样就能够产生更稳定的执行计划,更一致的查询性能。持久化的优化器统计信息还能够带来以下这些额外的好处:

You can use the innodb_stats_auto_recalc configuration option to control whether statistics are updated automatically after substantial changes to a table.
你可以使用innodb_stats_auto_recalc配置参数来控制是否要为大量修改过的表进行自动的统计信息更新。
You can use the STATS_PERSISTENT, STATS_AUTO_RECALC, and STATS_SAMPLE_PAGES clauses with CREATE TABLE and ALTER TABLE statements to configure optimizer statistics for individual tables.
你能够使用在CREATE TABLE and ALTER TABLE语句里使用STATS_PERSISTENT, STATS_AUTO_RECALC, and STATS_SAMPLE_PAGES子句来为个别的表配置优化器统计信息。
You can query optimizer statistics data in the mysql.innodb_table_stats and mysql.innodb_index_stats tables.
你可以在mysql.innodb_table_stats and mysql.innodb_index_stats tables表里面查询优化器统计信息数据。
You can view the last_update column of the mysql.innodb_table_stats and mysql.innodb_index_stats tables to see when statistics were last updated.
你可以在mysql.innodb_table_stats and mysql.innodb_index_stats表里的last_update列来查看统计信息最近一次更新在什么时候。
You can manually modify the mysql.innodb_table_stats and mysql.innodb_index_stats tables to force a specific query optimization plan or to test alternative plans without modifying the database.
你可以手动修改mysql.innodb_table_stats and mysql.innodb_index_stats表的数据来强制指定一个查询优化计划或者在不修改数据库的情况下测试其他的执行计划。

Non-persistent optimizer statistics are cleared on each server restart and after some other operations, and recomputed on the next table access. As a result, different estimates could be produced when recomputing statistics, leading to different choices in execution plans and variations in query performance.

非持久化的优化器统计信息会在每次实例重启后或者一些其他操作而被清空,在下次访问的表的时候需要再次重新统计。那结果可能是当重新计算统计信息的时候会产生不同的评估信息,从而导致选择不同的执行计划以及不同的查询性能。

This section also provides information about estimating ANALYZE TABLE complexity, which may be useful when attempting to achieve a balance between accurate statistics and ANALYZE TABLE execution time.

这一章节还提供了评估ANALYZE TABLE复杂性的信息,这在尝试在获得精确的统计信息和ANALYZE TABLE执行时间之间取平衡是非常有用的。

14.4.11.1 Configuring Persistent Optimizer Statistics Parameters

The persistent optimizer statistics feature improves plan stability by storing statistics to disk and making them persistent across server restarts so that the optimizer is more likely to make consistent choices each time for a given query.

优化器统计信息持久化的特性通过在实例重启的时候把统计信息存储到磁盘上,这样优化器为每次查询选择的执行计划也更一致,这样也就改善了稳定性。

Optimizer statistics are persisted to disk when innodb_stats_persistent=ON or when individual tables are created or altered with STATS_PERSISTENT=1. innodb_stats_persistent is enabled by default as of MySQL 5.6.6.

当innodb_stats_persistent=ON或者个别表在created or altered的时候使用STATS_PERSISTENT=1可以把优化器统计信息持久化到磁盘上。从MySQL5.6.6开始innodb_stats_persistent默认就是开启的。

Formerly, optimizer statistics were cleared on each server restart and after some other operations, and recomputed on the next table access. Consequently, different estimates could be produced when recalculating statistics, leading to different choices in query execution plans and thus variations in query performance.

从前,优化器统计信息会在每次实例重启之后或者一些其他操作而被清空,下次访问之前再进行重新统计。因此,当重新计算统计信息的时候可能会产生不同的评估,这就导致了会选择了不同的执行计划以及不同的查询性能。

Persistent statistics are stored in the mysql.innodb_table_stats and mysql.innodb_index_stats tables, as described in Section 14.4.11.1.4, "InnoDB Persistent Statistics Tables".

持久化的统计信息被存储在mysql.innodb_table_stats and mysql.innodb_index_stats表里,如Section 14.4.11.1.4, "InnoDB Persistent Statistics Tables"所描述的。

To revert to using non-persistent optimizer statistics, you can modify tables using an ALTER TABLE tbl_name STATS_PERSISTENT=0 statement. For related information, see Section 14.4.11.2, "Configuring Non-Persistent Optimizer Statistics Parameters"

要回到使用非持久化的优化器统计信息,你可以使用ALTER TABLE tbl_name STATS_PERSISTENT=0语句来修改表。相关的信息可以查看Section 14.4.11.2, "Configuring Non-Persistent Optimizer Statistics Parameters"。

14.4.11.1.1 Configuring Automatic Statistics Calculation for Persistent Optimizer Statistics

The innodb_stats_auto_recalc configuration option, which is enabled by default, determines whether statistics are calculated automatically whenever a table undergoes substantial changes (to more than 10% of the rows). You can also configure automatic statistics recalculation for individual tables using a STATS_AUTO_RECALC clause in a CREATE TABLE or ALTER TABLE statement. innodb_stats_auto_recalc is enabled by default.

innodb_stats_auto_recalc配置参数,默认是开启的,它决定了表的数据在大量修改后(超过10%)是否自动计算统计信息。你也可以在CREATE TABLE or ALTER TABLE里面使用STATS_AUTO_RECALC语句来为个别的表进行配置。

Because of the asynchronous nature of automatic statistics recalculation (which occurs in the background), statistics may not be recalculated instantly after running a DML operation that affects more than 10% of a table, even when innodb_stats_auto_recalc is enabled. In some cases, statistics recalculation may be delayed by a few seconds. If up-to-date statistics are required immediately after changing significant portions of a table, run ANALYZE TABLE to initiate a synchronous (foreground) recalculation of statistics.

因为自动重新计算统计信息的异步性(发生在后台),即使innodb_stats_auto_recalc是开启的,在运行一个影响超过表10%的数据的DML操作之后,统计信息也有可能不会立即进行重新计算。在一些情况下,重新计算统计信息可能会延迟几秒钟的时间。如果想要在一个表的数据重大改变之后立即获取到最新的统计信息,可以运行ANALYZE TABLE开始同步(前台操作)计算统计信息。

If innodb_stats_auto_recalc is disabled, ensure the accuracy of optimizer statistics by issuing the ANALYZE TABLE statement for each applicable table after making substantial changes to indexed columns. You might run this statement in your setup scripts after representative data has been loaded into the table, and run it periodically after DML operations significantly change the contents of indexed columns, or on a schedule at times of low activity. When a new index is added to an existing table, index statistics are calculated and added to the innodb_index_stats table regardless of the value of innodb_stats_auto_recalc.

如果innodb_stats_auto_recalc是关闭的,那就要在每个在索引列上要大量修改的表上执行ANALYZE TABLE语句来确保优化器统计信息的精确性。你可以在加载数据的配置脚本里运行这个语句,并在索引列大量修改之后定期运行它,又或者指定一个时间表在数据库活动少的时候运行。当有新的索引添加到现有的表上,不论innodb_stats_auto_recalc的值是什么数据库都会计算索引的统计信息,并把结果加入到innodb_index_stats表里。

Caution

To ensure statistics are gathered when a new index is created, either enable the innodb_stats_auto_recalc option, or run ANALYZE TABLE after creating each new index when the persistent statistics mode is enabled.

在创建新索引的时候要确保统计信息已经收集了,可以开启innodb_stats_auto_recalc,又或者在持久化统计信息开启的前提下,子创建每个新索引的时候运行ANALYZE TABLE。

14.4.11.1.2 Configuring Optimizer Statistics Parameters for Individual Tables

innodb_stats_persistent, innodb_stats_auto_recalc, and innodb_stats_persistent_sample_pages are global configuration options. To override these system-wide settings and configure optimizer statistics parameters for individual tables, you can define STATS_PERSISTENT, STATS_AUTO_RECALC, and STATS_SAMPLE_PAGES clauses in CREATE TABLE or ALTER TABLE statements.

innodb_stats_persistent, innodb_stats_auto_recalc, and innodb_stats_persistent_sample_pages是全局的配置参数。要覆盖系统层面的设定为个别表配置优化统计参数,你可以在CREATE TABLE or ALTER TABLE的时候定义STATS_PERSISTENT, STATS_AUTO_RECALC, and STATS_SAMPLE_PAGES。

STATS_PERSISTENT specifies whether to enable persistent statistics for an InnoDB table. The value DEFAULT causes the persistent statistics setting for the table to be determined by the innodb_stats_persistent configuration option. The value 1 enables persistent statistics for the table, while the value 0 turns off this feature. After enabling persistent statistics through a CREATE TABLE or ALTER TABLE statement, issue an ANALYZE TABLE statement to calculate the statistics, after loading representative data into the table.
STATS_PERSISTENT指定了是否开启InnoDB表的统计信息持久化。默认的值是由innodb_stats_persistent配置参数决定的。值为1的时候开启统计信息持久化,0是关闭。在通过CREATE TABLE or ALTER TABLE的时候开启了统计信息的持久化之后,也可以在执行ANALYZE TABLE语句计算统计信息。
STATS_AUTO_RECALC specifies whether to automatically recalculate persistent statistics for an InnoDB table. The value DEFAULT causes the persistent statistics setting for the table to be determined by the innodb_stats_auto_recalc configuration option. The value 1 causes statistics to be recalculated when 10% of the data in the table has changed. The value 0 prevents automatic recalculation for this table; with this setting, issue an ANALYZE TABLE statement to recalculate the statistics after making substantial changes to the table.
STATS_AUTO_RECALC指定了是否自动为InnoDB表计算持久化的统计信息。默认值是由nnodb_stats_auto_recalc配置参数决定的。1表示表里10%的数据被修改后会自动计算统计信息。0为阻止自动计算,但是仍然可以运行ANALYZE TABLE来手动计算。
STATS_SAMPLE_PAGES specifies the number of index pages to sample when estimating cardinality and other statistics for an indexed column, such as those calculated by ANALYZE TABLE.
STATS_SAMPLE_PAGES指定了评估的基数以及索引列其他统计信息时的索引页的样本数量。

All three clauses are specified in the following CREATE TABLE example:

在CREATE TABLE语句中指定这些子句的例子:

CREATE TABLE `t1` (

`id` int(8) NOT NULL auto_increment,

`data` varchar(255),

`date` datetime,

PRIMARY KEY (`id`),

INDEX `DATE_IX` (`date`)

) ENGINE=InnoDB,

STATS_PERSISTENT=1,

STATS_AUTO_RECALC=1,

STATS_SAMPLE_PAGES=25;

14.4.11.1.3 Configuring the Number of Sampled Pages for InnoDB Optimizer Statistics

The MySQL query optimizer uses estimated statistics about key distributions to choose the indexes for an execution plan, based on the relative selectivity of the index. Operations such as ANALYZE TABLE cause InnoDB to sample random pages from each index on a table to estimate the cardinality of the index. (This technique is known as random dives.)

MySQL查询优化器会基于索引的相对选择性,通过key值分布的统计信息来为执行计划选择索引。诸如ANALYZE TABLE的语句会导致InnoDB从表里的每个索引上取样随机的数据页来估算索引的基数。(这种技术称之为random dives)

To give you control over the quality of the statistics estimate (and thus better information for the query optimizer), you can change the number of sampled pages using the parameter innodb_stats_persistent_sample_pages, which can be set at runtime.

为了让你控制评估的统计信息的品质(为查询优化器获得更好信息),你可以使用innodb_stats_persistent_sample_pages(可以在运行时配置)参数来修改取样数据页的数量。

innodb_stats_persistent_sample_pages has a default value of 20. As a general guideline, consider modifying this parameter when encountering the following issues:

innodb_stats_persistent_sample_pages的默认值是20。作为一个通用的方法,遭遇到下面的问题时可以考虑修改这个参数:

1.Statistics are not accurate enough and the optimizer chooses suboptimal plans, as shown by EXPLAIN output. The accuracy of statistics can be checked by comparing the actual cardinality of an index (as returned by running SELECT DISTINCT on the index columns) with the estimates provided in the mysql.innodb_index_stats persistent statistics table.

1.统计信息不够精确,如EXPLAIN显示的优化器选择的不是最优的执行计划。统计信息的准确性可以通过对比索引的实际基数(SELECT DISTINCT索引列)和mysql.innodb_index_stats所提供的评估信息来检查。

If it is determined that statistics are not accurate enough, the value of innodb_stats_persistent_sample_pages should be increased until the statistics estimates are sufficiently accurate. Increasing innodb_stats_persistent_sample_pages too much, however, could cause ANALYZE TABLE to run slowly.

如果确定统计信息不够精确,可以增加innodb_stats_persistent_sample_pages的值直到评估的统计信息足够的精确。然而,innodb_stats_persistent_sample_pages增加得太多又会使得ANALYZE TABLE运行得非常慢。

2.ANALYZE TABLE is too slow. In this case innodb_stats_persistent_sample_pages should be decreased until ANALYZE TABLE execution time is acceptable. Decreasing the value too much, however, could lead to the first problem of inaccurate statistics and suboptimal query execution plans.

2.ANALYZE TABLE运行得很慢。在这种情况下innodb_stats_persistent_sample_pages应该减少直到ANALYZE TABLE的执行时间可接受。然而值减少得太多的话又会导致前面说的第一个问题。

If a balance cannot be achieved between accurate statistics and ANALYZE TABLE execution time, consider decreasing the number of indexed columns in the table or limiting the number of partitions to reduce ANALYZE TABLE complexity. The number of columns in the table's primary key is also important to consider, as primary key columns are appended to each non-unique index.

如果在精确的统计信息和ANALYZE TABLE执行时间上得不到好的平衡,可以考虑减少表上索引的数量或者限制表分区的数量来降低ANALYZE TABLE的复杂性。表里面主键列的数量也是一个重要的考虑因素,因为主键列会附加到每个非唯一索引上。

For related information, see Section 14.4.11.3, "Estimating ANALYZE TABLE Complexity for InnoDB Tables".

更多相关信息可以查看Section 14.4.11.3, "Estimating ANALYZE TABLE Complexity for InnoDB Tables"。

14.4.11.1.4 InnoDB Persistent Statistics Tables

The persistent statistics feature relies on the internally managed tables in the mysql database, named innodb_table_stats and innodb_index_stats. These tables are set up automatically in all install, upgrade, and build-from-source procedures.

持久化统计信息的特性依赖于mysql数据的内部管理表,innodb_table_stats and innodb_index_stats。这些表是自动安装更新的。

Table 14.2 Columns of innodb_table_stats

Column name

Description

database_name

Database name

table_name

Table name, partition name, or subpartition name

last_update

A timestamp indicating the last time that InnoDB updated this row

n_rows

The number of rows in the table

clustered_index_size

The size of the primary index, in pages

sum_of_other_index_sizes

The total size of other (non-primary) indexes, in pages

Table 14.3 Columns of innodb_index_stats

Column name

Description

database_name

Database name

table_name

Table name, partition name, or subpartition name

index_name

Index name

last_update

A timestamp indicating the last time that InnoDB updated this row

stat_name

The name of the statistic, whose value is reported in the stat_value column

stat_value

The value of the statistic that is named in stat_name column

sample_size

The number of pages sampled for the estimate provided in the stat_value column

stat_description

Description of the statistic that is named in the stat_name column

Both the innodb_table_stats and innodb_index_stats tables include a last_update column showing when InnoDB last updated index statistics, as shown in the following example:

innodb_table_stats and innodb_index_stats表都包含一个last_update列显示了InnoDB最近一次更新索引统计信息的时间,如下面的例子显示的:

mysql> select * from innodb_table_stats \G

*************************** 1. row ***************************

database_name: sakila

table_name: actor

last_update: 2014-05-28 16:16:44

n_rows: 200

clustered_index_size: 1

sum_of_other_index_sizes: 1

...

mysql> select * from innodb_index_stats \G

*************************** 1. row ***************************

database_name: sakila

table_name: actor

index_name: PRIMARY

last_update: 2014-05-28 16:16:44

stat_name: n_diff_pfx01

stat_value: 200

sample_size: 1

...

The innodb_table_stats and innodb_index_stats tables are ordinary tables and can be updated manually. The ability to update statistics manually makes it possible to force a specific query optimization plan or test alternative plans without modifying the database. If you manually update statistics, issue the FLUSH TABLE tbl_name command to make MySQL reload the updated statistics.

innodb_table_stats and innodb_index_stats都是普通的表,可以手动update。手动修改统计信息可以强制指定查询计划或者在不修改数据库的情况下测试另一个执行计划。如果你手动更新了执行计划,记得执行FLUSH TABLE tbl_name命令来使得MySQL重新加载更新后统计信息。

14.4.11.1.5 InnoDB Persistent Statistics Tables Example

The innodb_table_stats table contains one row per table. The data collected is demonstrated in the following example.

innodb_table_stats表里每张表都占一条记录。其中的数据会以下面的样例进行收集。

Table t1 contains a primary index (columns a, b) secondary index (columns c, d), and unique index (columns e, f):

t1表包含一个主键 (columns a, b),辅助索引(columns c, d),和唯一索引(columns e, f):

CREATE TABLE t1 (

a INT, b INT, c INT, d INT, e INT, f INT,

PRIMARY KEY (a, b), KEY i1 (c, d), UNIQUE KEY i2uniq (e, f)

) ENGINE=INNODB;

After inserting five rows of sample data, the table appears as follows:

插入5条记录后如下:

mysql> SELECT * FROM t1;

+---+---+------+------+------+------+

| a | b | c | d | e | f |

+---+---+------+------+------+------+

| 1 | 1 | 10 | 11 | 100 | 101 |

| 1 | 2 | 10 | 11 | 200 | 102 |

| 1 | 3 | 10 | 11 | 100 | 103 |

| 1 | 4 | 10 | 12 | 200 | 104 |

| 1 | 5 | 10 | 12 | 100 | 105 |

+---+---+------+------+------+------+

To immediately update statistics, run ANALYZE TABLE (if innodb_stats_auto_recalc is enabled, statistics are updated automatically within a few seconds assuming that the 10% threshold for changed table rows is reached):

运行ANALYZE TABLE立即更新统计信息(如果innodb_stats_auto_recalc是开启的,如果更新的数据超过10%InnoDB会在几秒钟内自动更新统计信息):

mysql> ANALYZE TABLE t1;

+---------+---------+----------+----------+

| Table | Op | Msg_type | Msg_text |

+---------+---------+----------+----------+

| test.t1 | analyze | status | OK |

+---------+---------+----------+----------+

Table statistics for table t1 show the last time InnoDB updated the table statistics (2014-03-14 14:36:34), the number of rows in the table (5), the clustered index size (1 page), and the combined size of the other indexes (2 pages).

显示了t1表最近一次更新统计信息的时间(2014-03-14 14:36:34),表里数据的行数(5),clustered index的大小(1 page),其他索引共计后的大小(2 pages)。

mysql> SELECT * FROM mysql.innodb_table_stats WHERE table_name like 't1'\G

*************************** 1. row ***************************

database_name: test

table_name: t1

last_update: 2014-03-14 14:36:34

n_rows: 5

clustered_index_size: 1

sum_of_other_index_sizes: 2

The innodb_index_stats table contains multiple rows for each index. Each row in the innodb_index_stats table provides data related to a particular index statistic which is named in the stat_name column and described in the stat_description column. For example:

innodb_index_stats表里每个索引会占用多行。innodb_index_stats表里的每行记录提供了索引相关的详细统计信息,名字在stat_name列里,描述在stat_description列里。例如:

mysql> SELECT index_name, stat_name, stat_value, stat_description

-> FROM mysql.innodb_index_stats WHERE table_name like 't1';

+------------+--------------+------------+-----------------------------------+

| index_name | stat_name | stat_value | stat_description |

+------------+--------------+------------+-----------------------------------+

| PRIMARY | n_diff_pfx01 | 1 | a |

| PRIMARY | n_diff_pfx02 | 5 | a,b |

| PRIMARY | n_leaf_pages | 1 | Number of leaf pages in the index |

| PRIMARY | size | 1 | Number of pages in the index |

| i1 | n_diff_pfx01 | 1 | c |

| i1 | n_diff_pfx02 | 2 | c,d |

| i1 | n_diff_pfx03 | 2 | c,d,a |

| i1 | n_diff_pfx04 | 5 | c,d,a,b |

| i1 | n_leaf_pages | 1 | Number of leaf pages in the index |

| i1 | size | 1 | Number of pages in the index |

| i2uniq | n_diff_pfx01 | 2 | e |

| i2uniq | n_diff_pfx02 | 5 | e,f |

| i2uniq | n_leaf_pages | 1 | Number of leaf pages in the index |

| i2uniq | size | 1 | Number of pages in the index |

+------------+--------------+------------+-----------------------------------+

The stat_name column shows the following types of statistics:

stat_name列显示了下面几种类型的统计信息:

size: Where stat_name=size, the stat_value column displays the total number of pages in the index.
size: 当stat_name=size,stat_value列显示了索引总共页的数量。
n_leaf_pages: Where stat_name=n_leaf_pages, the stat_value column displays the number of leaf pages in the index.
n_leaf_pages: 当stat_name=n_leaf_pages,stat_value列显示了索引叶子节点页的数量。
n_diff_pfxNN: Where stat_name=n_diff_pfx01, the stat_value column displays the number of distinct values in the first column of the index. Where stat_name=n_diff_pfx02, the stat_value column displays the number of distinct values in the first two columns of the index, and so on. Additionally, where stat_name=n_diff_pfxNN, the stat_description column shows a comma separated list of the index columns that are counted.
n_diff_pfxNN:当stat_name=n_diff_pfx01,stat_value列显示了索引第一个列里distinct值的数量。当stat_name=n_diff_pfx02,stat_value列显示索引前两列distinct值的数量,并以此类推。另外,当stat_name=n_diff_pfxNN,stat_description显示了以逗号分割的索引列的统计。

To further illustrate the n_diff_pfxNN statistic, which provides cardinality data, consider the t1 table example. As shown below, the t1 table is created with a primary index (columns a, b), a secondary index (columns c, d), and a unique index (columns e, f):

要进一步说明n_diff_pfxNN提供基数数据的统计信息,可以查看样例表t1。如下面所显示的,t1表创建了一个主键(columns a, b),一个secondary index(columns c, d),以及一个唯一索引(columns e, f):

CREATE TABLE t1 (

a INT, b INT, c INT, d INT, e INT, f INT,

PRIMARY KEY (a, b), KEY i1 (c, d), UNIQUE KEY i2uniq (e, f)

) ENGINE=INNODB;

After inserting five rows of sample data, the table appears as follows:

在插入5行样例数据后显示如下:

mysql> SELECT * FROM t1;

+---+---+------+------+------+------+

| a | b | c | d | e | f |

+---+---+------+------+------+------+

| 1 | 1 | 10 | 11 | 100 | 101 |

| 1 | 2 | 10 | 11 | 200 | 102 |

| 1 | 3 | 10 | 11 | 100 | 103 |

| 1 | 4 | 10 | 12 | 200 | 104 |

| 1 | 5 | 10 | 12 | 100 | 105 |

+---+---+------+------+------+------+

When you query the index_name, stat_name, stat_value, and stat_description where stat_name LIKE 'n_diff%', the following result set is returned:

当你查询index_name, stat_name, stat_value, and stat_description,条件是stat_name LIKE 'n_diff%',返回了下面的结果集:

mysql> SELECT index_name, stat_name, stat_value, stat_description

-> FROM mysql.innodb_index_stats

-> WHERE table_name like 't1' AND stat_name LIKE 'n_diff%';

+------------+--------------+------------+------------------+

| index_name | stat_name | stat_value | stat_description |

+------------+--------------+------------+------------------+

| PRIMARY | n_diff_pfx01 | 1 | a |

| PRIMARY | n_diff_pfx02 | 5 | a,b |

| i1 | n_diff_pfx01 | 1 | c |

| i1 | n_diff_pfx02 | 2 | c,d |

| i1 | n_diff_pfx03 | 2 | c,d,a |

| i1 | n_diff_pfx04 | 5 | c,d,a,b |

| i2uniq | n_diff_pfx01 | 2 | e |

| i2uniq | n_diff_pfx02 | 5 | e,f |

+------------+--------------+------------+------------------+

For the PRIMARY index, there are two n_diff% rows. The number of rows is equal to the number of columns in the index.

对于主键索引,有两行n_diff%记录。行的数量等于索引列的数量。

Note

For non-unique indexes, InnoDB appends the columns of the primary key.

对于非唯一索引,InnoDB会追加上主键的列。

Where index_name=PRIMARY and stat_name=n_diff_pfx01, the stat_value is 1, which indicates that there is a single distinct value in the first column of the index (column a). The number of distinct values in column a is confirmed by viewing the data in column a in table t1, in which there is a single distinct value (1). The counted column (a) is shown in the stat_description column of the result set.
当index_name=PRIMARY and stat_name=n_diff_pfx01, the stat_value is 1,这表明了第一个索引列(column a)上只有一个distinct 值。column a上distinct 值的数量可以通过浏览t1表里的数据来确认,只有一个distinct值(1)。column (a)的统计显示在结果集的stat_description列上。
Where index_name=PRIMARY and stat_name=n_diff_pfx02, the stat_value is 5, which indicates that there are five distinct values in the two columns of the index (a,b). The number of distinct values in columns a and b is confirmed by viewing the data in columns a and b in table t1, in which there are five distinct values: (1,1), (1,2), (1,3), (1,4) and (1,5). The counted columns (a,b) are shown in the stat_description column of the result set.
当index_name=PRIMARY and stat_name=n_diff_pfx02, the stat_value is 5,这表明了在索引列(a,b)上有5个distinct 值。columns a and b的distinct 值的数量可以通过浏览t1表的columns a and b列来确认:这有5个distinct 值:(1,1), (1,2), (1,3), (1,4) and (1,5)。columns (a,b)的统计显示在结果集的stat_description列上。

For the secondary index (i1), there are four n_diff% rows. Only two columns are defined for the secondary index (c,d) but there are four n_diff% rows for the secondary index because InnoDB suffixes all non-unique indexes with the primary key. As a result, there are four n_diff% rows instead of two to account for the both the secondary index columns (c,d) and the primary key columns (a,b).

对于secondary index (i1),有4行记录。虽然secondary index只定义了两列(c,d),但是InnoDB会把主键作为非唯一索引的后缀所以这里secondary index有4行n_diff%记录。结果集上,有4行n_diff%记录包含两个secondary index列 (c,d)和两个主键列(a,b)。

Where index_name=i1 and stat_name=n_diff_pfx01, the stat_value is 1, which indicates that there is a single distinct value in the first column of the index (column c). The number of distinct values in column c is confirmed by viewing the data in column c in table t1, in which there is a single distinct value: (10). The counted column (c) is shown in the stat_description column of the result set.
当index_name=i1 and stat_name=n_diff_pfx01, the stat_value is 1,表明索引第一个列(column c)上只有一个distinct 值。column c的distinct 值可以通过浏览表t1的column c的数据来确认:只有一个distinct 值(10)。column (c)的计数显示在结果集的stat_description列上。
Where index_name=i1 and stat_name=n_diff_pfx02, the stat_value is 2, which indicates that there are two distinct values in the first two columns of the index (c,d). The number of distinct values in columns c an d is confirmed by viewing the data in columns c and d in table t1, in which there are two distinct values: (10,11) and (10,12). The counted columns (c,d) are shown in the stat_description column of the result set.
当index_name=i1 and stat_name=n_diff_pfx02, the stat_value is 2,这表明了索引的前两列(c,d)上有两个distinct 值。columns c an d的distinct 值的数量可以通过浏览t1表的columns c and d列来确认:有两个distinct 值:(10,11) and (10,12)。columns (c,d)的计数信息可以在结果集的stat_description列显示出来。
Where index_name=i1 and stat_name=n_diff_pfx03, the stat_value is 2, which indicates that there are two distinct values in the first three columns of the index (c,d,a). The number of distinct values in columns c, d, and a is confirmed by viewing the data in column c, d, and a in table t1, in which there are two distinct values: (10,11,1) and (10,12,1). The counted columns (c,d,a) are shown in the stat_description column of the result set.
当index_name=i1 and stat_name=n_diff_pfx03, the stat_value is 2,表明了索引的前三列有两个distinct 值。columns c, d, and a上distinct 值的数量可以通过浏览t1表的column c, d, and a来确认:有两个distinct值:(10,11,1) and (10,12,1)。columns (c,d,a) 的计数信息可以在结果集的stat_description列上查看。
Where index_name=i1 and stat_name=n_diff_pfx04, the stat_value is 5, which indicates that there are five distinct values in the four columns of the index (c,d,a,b). The number of distinct values in columns c, d, a and b is confirmed by viewing the data in columns c, d, a, and b in table t1, in which there are five distinct values: (10,11,1,1), (10,11,1,2), (10,11,1,3), (10,12,1,4) and (10,12,1,5). The counted columns (c,d,a,b) are shown in the stat_description column of the result set.
当index_name=i1 and stat_name=n_diff_pfx04, the stat_value is 5,表明了索引的四个列(c,d,a,b)上有5个distinct值。columns c, d, a and b的distinct值的数量可以通过浏览t1表的columns c, d, a, and b来确认:有5个distinct值(10,11,1,1), (10,11,1,2), (10,11,1,3), (10,12,1,4) and (10,12,1,5)。columns (c,d,a,b)的计数信息显示在结果集的stat_description列上。

For the unique index (i2uniq), there are two n_diff% rows.

对于唯一索引(i2uniq),有两行n_diff%记录。

Where index_name=i2uniq and stat_name=n_diff_pfx01, the stat_value is 2, which indicates that there are two distinct values in the first column of the index (column e). The number of distinct values in column e is confirmed by viewing the data in column e in table t1, in which there are two distinct values: (100) and (200). The counted column (e) is shown in the stat_description column of the result set.
当index_name=i2uniq and stat_name=n_diff_pfx01, the stat_value is 2,表明索引的第一列(column e)上有两个distinct值。column e上distinct值的数量可以通过浏览t1表的column e来确认:有两个distinct值:(100) and (200)。column (e)的计数信息显示在结果集的stat_description列上。
Where index_name=i2uniq and stat_name=n_diff_pfx02, the stat_value is 5, which indicates that there are five distinct values in the two columns of the index (e,f). The number of distinct values in columns e and f is confirmed by viewing the data in columns e and f in table t1, in which there are five distinct values: (100,101), (200,102), (100,103), (200,104) and (100,105). The counted columns (e,f) are shown in the stat_description column of the result set.
当index_name=i2uniq and stat_name=n_diff_pfx02, the stat_value is 5,表明有5个distinct值在索引列(e,f)上。columns e and f上distinct值的数量可以通过浏览t1表的columns e and f来确认:有5个distinct值(100,101), (200,102), (100,103), (200,104) and (100,105)。columns (e,f)的计数信息显示在结果集的 stat_description列上。

14.4.11.1.6 Retrieving Index Size Using the innodb_index_stats Table

The size of indexes for tables, partitions, or subpartitions can be retrieved using the innodb_index_stats table. In the following example, index sizes are retrieved for table t1. For a definition of table t1 and corresponding index statistics, see Section 14.4.11.1.5, "InnoDB Persistent Statistics Tables Example".

表,分区或者子分区的索引大小可以在innodb_index_stats table表里检索。在下面的列子里,检索了t1表的索引的大小。t1表的定义及相关的索引统计信息可以查看Section 14.4.11.1.5, "InnoDB Persistent Statistics Tables Example"。

mysql> SELECT SUM(stat_value) pages, index_name,

-> SUM(stat_value)*@@innodb_page_size size

-> FROM mysql.innodb_index_stats WHERE table_name='t1'

-> AND stat_name = 'size' GROUP BY index_name;

+-------+------------+-------+

| pages | index_name | size |

+-------+------------+-------+

| 1 | PRIMARY | 16384 |

| 1 | i1 | 16384 |

| 1 | i2uniq | 16384 |

+-------+------------+-------+

For partitions or subpartitions, the same query with a modified WHERE clause can be used to retrieve index sizes. For example, the following query retrieves index sizes for partitions of table t1:

对于分区或者子分区,相同的查询只要修改where条件。例如,下面的查询检索了t1表分区索引的大小:

mysql> SELECT SUM(stat_value) pages, index_name,

-> SUM(stat_value)*@@innodb_page_size size

-> FROM mysql.innodb_index_stats WHERE table_name like 't1#P%'

-> AND stat_name = 'size' GROUP BY index_name;

14.4.11.2 Configuring Non-Persistent Optimizer Statistics Parameters

This section describes how to configure non-persistent optimizer statistics. Optimizer statistics are not persisted to disk when innodb_stats_persistent=OFF or when individual tables are created or altered with STATS_PERSISTENT=0. Instead, statistics are stored in memory, and are lost when the server is shut down. Statistics are also updated periodically by certain operations and under certain conditions.

这一章节描述了如何配置非持久化的优化器统计信息。当innodb_stats_persistent=OFF或者个别表创建修改的时候使用STATS_PERSISTENT=0的时候,优化器统计信息不会持久化的磁盘上。相反,统计信息会存储在内存里,当实例关闭的时候就会丢失。由于某些操作或者某些条件之下统计信息也会定期更新。

As of MySQL 5.6.6, optimizer statistics are persisted to disk by default, enabled by the innodb_stats_persistent configuration option. For information about persistent optimizer statistics, see Section 14.4.11.1, "Configuring Persistent Optimizer Statistics Parameters".

从MySQL5.6.6开始,优化器统计信息默认会持久化到磁盘上,innodb_stats_persistent配置参数默认是开启的。更多关闭持久化的优化器统计信息的内容可以查看Section 14.4.11.1, "Configuring Persistent Optimizer Statistics Parameters"。

Optimizer Statistics Updates

Optimizer statistics are updated when:

一下情况下统计信息会被更新:

Running ANALYZE TABLE.
运行ANALYZE TABLE。
Running SHOW TABLE STATUS, SHOW INDEX, or querying the INFORMATION_SCHEMA.TABLES or INFORMATION_SCHEMA.STATISTICS tables with the innodb_stats_on_metadata option enabled.
运行SHOW TABLE STATUS, SHOW INDEX,或者在innodb_stats_on_metadata开启的情况下查询INFORMATION_SCHEMA.TABLES or INFORMATION_SCHEMA.STATISTICS表。

The default setting for innodb_stats_on_metadata was changed to OFF when persistent optimizer statistics were enabled by default in MySQL 5.6.6. Enabling innodb_stats_on_metadata may reduce access speed for schemas that have a large number of tables or indexes, and reduce stability of execution plans for queries that involve InnoDB tables. innodb_stats_on_metadata is configured globally using a SET statement.

在MySQL5.6.6里默认开启的持久化统计信息会把innodb_stats_on_metadata的默认值该成OFF。开启innodb_stats_on_metadata会降低那些有大量表或索引的schema的速度,还会降低涉及InnoDB表的执行计划的稳定性。innodb_stats_on_metadata通过SET语句进行全局配置。

SET GLOBAL innodb_stats_on_metadata=ON

Starting a mysql client with the --auto-rehash option enabled, which is the default. The auto-rehash option causes all InnoDB tables to be opened, and the open table operations cause statistics to be recalculated.
启动mysql客户端的时候开启了--auto-rehash(默认是开启的)。auto-rehash参数会引起所有InnoDB表被打开,同时打开表的操作会引起统计信心被重新计算。

To improve the start up time of the mysql client and to updating statistics, you can turn off auto-rehash using the --disable-auto-rehash option. The auto-rehash feature enables automatic name completion of database, table, and column names for interactive users.

为了减少mysql客户端的启动时间,你可以使用--disable-auto-rehash参数来关闭auto-rehash。auto-rehash特性能够为交互式用户自动完成数据库,表,列名的补全。

A table is first opened.
表第一次被打开。
InnoDB detects that 1 / 16 of table has been modified since the last time statistics were updated.
InnoDB发现自最近一次统计信息更新以来有1/16的表被修改过了。

Configuring the Number of Sampled Pages

The MySQL query optimizer uses estimated statistics about key distributions to choose the indexes for an execution plan, based on the relative selectivity of the index. When InnoDB updates optimizer statistics, it samples random pages from each index on a table to estimate the cardinality of the index. (This technique is known as random dives.)

MySQL查询优化器评估的关于key的分布的统计信息,基于相对的索引选择度来为执行计划选择索引。当InnoDB更新统计信息的时候,它会从表里的每个索引上随机取样数个数据页来评估索引的基数。(这种技术称之为random dives。)

To give you control over the quality of the statistics estimate (and thus better information for the query optimizer), you can change the number of sampled pages using the parameter innodb_stats_transient_sample_pages. The default number of sampled pages is 8, which could be insufficient to produce an accurate estimate, leading to poor index choices by the query optimizer. This technique is especially important for large tables and tables used in joins. Unnecessary full table scans for such tables can be a substantial performance issue. See Section 8.2.1.21, "How to Avoid Full Table Scans" for tips on tuning such queries. innodb_stats_transient_sample_pages is a global parameter that can be set at runtime.

为了让你能够控制统计信息的评估质量(为查询优化器提供更好的信息),你可以通过innodb_stats_transient_sample_pages参数修改取样数据页的数量。默认的取样数量是8。这个值可能不足以能够提供精确的评估,而导致查询优化器选择相对比较差的索引。这对于大表以及进行join的表是非常重要的,因为针对这些表不必要的全表扫描将会带来严重的性能问题。这种查询的调整技巧可以查看Section 8.2.1.21, "How to Avoid Full Table Scans"。innodb_stats_transient_sample_pages是一个全局的变量,可以在运行时修改。

The value of innodb_stats_transient_sample_pages affects the index sampling for all InnoDB tables and indexes when innodb_stats_persistent=0. Be aware of the following potentially significant impacts when you change the index sample size:

当innodb_stats_persistent=0的时候innodb_stats_transient_sample_pages会影响所有InnoDB表和索引的取样。当你决定要修改取样值的之后要注意下面潜在的重大影响:

Small values like 1 or 2 can result in inaccurate estimates of cardinality.
比较小的值例如1或者2可能会导致基数评估的错误。
Increasing the innodb_stats_transient_sample_pages value might require more disk reads. Values much larger than 8 (say, 100), can cause a significant slowdown in the time it takes to open a table or execute SHOW TABLE STATUS.
增加innodb_stats_transient_sample_pages的值可能会有更多的磁盘读操作。当值远超过8(例如100),可能会导致在打开一个表或者执行SHOW TABLE STATUS的时候出现显著的性能下降。
The optimizer might choose very different query plans based on different estimates of index selectivity.
优化器基于不同的索引选择度的评估而选择了不同的查询计划。

Whatever value of innodb_stats_transient_sample_pages works best for a system, set the option and leave it at that value. Choose a value that results in reasonably accurate estimates for all tables in your database without requiring excessive I/O. Because the statistics are automatically recalculated at various times other than on execution of ANALYZE TABLE, it does not make sense to increase the index sample size, run ANALYZE TABLE, then decrease sample size again.

找到innodb_stats_transient_sample_pages最优的值并进行设置,使得对数据库里所有的表都能进行合理准确评估而又不要求过多的I/O操作。因为统计信息会在不同的时间自动进行重建计算而不只是在执行ANALYZE TABLE的时候,它不会感觉到索引取样数据增加了。在运行 ANALYZE TABLE的时候,可以再减少取样数量的值。

Smaller tables generally require fewer index samples than larger tables. If your database has many large tables, consider using a higher value for innodb_stats_transient_sample_pages than if you have mostly smaller tables.

较小的表通常比大表要求更少的索引取样数量。如果你数据库里有很多大表,那就要考虑把innodb_stats_transient_sample_pages设置得更大一点。

14.4.11.3 Estimating ANALYZE TABLE Complexity for InnoDB Tables

ANALYZE TABLE complexity for InnoDB tables is dependent on:

InnoDB表的ANALYZE TABLE 复杂度依赖于:

The number of pages sampled, as defined by innodb_stats_persistent_sample_pages.
取样数据页的数量,由innodb_stats_persistent_sample_pages定义。
The number of indexed columns in a table
一个表里索引列的数量
The number of partitions. If a table has no partitions, the number of partitions is considered to be 1.
分区的数量。如果表没有分区,分区的数量可以看成是1.

Using these parameters, an approximate formula for estimating ANALYZE TABLE complexity would be:

使用下面的参数,一个大概的公式可以评估ANALYZE TABLE的复杂度:

The value of innodb_stats_persistent_sample_pages * number of indexed columns in a table * the number of partitions

Typically, the greater the resulting value, the greater the execution time for ANALYZE TABLE.

通常,得到的值越大,ANALYZE TABLE执行的时间就越长。

Note

innodb_stats_persistent_sample_pages defines the number of pages sampled at a global level. To set the number of pages sampled for an individual table, use the STATS_SAMPLE_PAGES option with CREATE TABLE or ALTER TABLE. For more information, see Section 14.4.11.1, "Configuring Persistent Optimizer Statistics Parameters".

innodb_stats_persistent_sample_pages在全局的层面定义了取样数据页的数量。在CREATE TABLE or ALTER TABLE的时候使用STATS_SAMPLE_PAGES可以为个别表定义取样数据页的数量。更多的信息可见Section 14.4.11.1, "Configuring Persistent Optimizer Statistics Parameters"。

If innodb_stats_persistent=OFF, the number of pages sampled is defined by innodb_stats_transient_sample_pages. See Section 14.4.11.2, "Configuring Non-Persistent Optimizer Statistics Parameters" for additional information.

如果innodb_stats_persistent=OFF,取样数据页的数量由innodb_stats_transient_sample_pages定义。额外的信息可见Section 14.4.11.2, "Configuring Non-Persistent Optimizer Statistics Parameters"。

For a more in-depth approach to estimating ANALYZE TABLE complexity, consider the following example.

更深入评估ANALYZE TABLE的复杂度,可以考虑下面的列子。

In Big O notation, ANALYZE TABLE complexity is described as:

O(n_sample

* (n_cols_in_uniq_i

+ n_cols_in_non_uniq_i

+ n_cols_in_pk * (1 + n_non_uniq_i))

* n_part)

where:

n_sample is the number of pages sampled (defined by innodb_stats_persistent_sample_pages)
n_sample是取样数据页的数量(由innodb_stats_persistent_sample_pages定义)
n_cols_in_uniq_i is total number of all columns in all unique indexes (not counting the primary key columns)
n_cols_in_uniq_i是所有唯一索引里的所有列的数量(不包括主键列)
n_cols_in_non_uniq_i is the total number of all columns in all non-unique indexes
n_cols_in_non_uniq_i是所有非唯一索引列的数量
n_cols_in_pk is the number of columns in the primary key (if a primary key is not defined, InnoDB creates a single column primary key internally)
n_cols_in_pk是主键里列的数量(如果没有定义主键,InnoDB会在内部创建一个只包含一列的主键)
n_non_uniq_i is the number of non-unique indexes in the table
n_non_uniq_i是表里非唯一索引的数量
n_part is the number of partitions. If no partitions are defined, the table is considered to be a single partition.
n_part是分区的数量。如果没有定义过分区,那一个表可以看成是一个单独的分区。

Now, consider the following table (table t), which has a primary key (2 columns), a unique index (2 columns), and two non-unique indexes (two columns each):

现在考虑下面的表(table t),有一个主键(2 columns),一个唯一索引(2 columns),两个非唯一索引(two columns each):

CREATE TABLE t (

a INT,

b INT,

c INT,

d INT,

e INT,

f INT,

g INT,

h INT,

PRIMARY KEY (a, b),

UNIQUE KEY i1uniq (c, d),

KEY i2nonuniq (e, f),

KEY i3nonuniq (g, h)

);

For the column and index data required by the algorithm described above, query the mysql.innodb_index_stats persistent index statistics table for table t. The n_diff_pfx% statistics show the columns that are counted for each index. For example, columns a and b are counted for the primary key index. For the non-unique indexes, the primary key columns (a,b) are counted in addition to the user defined columns.

上文算法所需要的列和索引数据,可以在mysql.innodb_index_stats里查询到t表的持久化索引统计信息。n_diff_pfx%统计信息显示了每个索引列的数量。例如,主键上的列有a and b。对于非唯一索引,主键列(a,b)会被附加到索引定义列的后面。

Note

For additional information about the InnoDB persistent statistics tables, see Section 14.4.11.1, "Configuring Persistent Optimizer Statistics Parameters"

关于InnoDB持久化的统计信息的额外信息可以查看Section 14.4.11.1, "Configuring Persistent Optimizer Statistics Parameters"。

SELECT index_name, stat_name, stat_description

FROM mysql.innodb_index_stats

WHERE

database_name='test' AND

table_name='t' AND

stat_name like 'n_diff_pfx%';

+------------+--------------+------------------+

| index_name | stat_name | stat_description |

+------------+--------------+------------------+

| PRIMARY | n_diff_pfx01 | a |

| PRIMARY | n_diff_pfx02 | a,b |

| i1uniq | n_diff_pfx01 | c |

| i1uniq | n_diff_pfx02 | c,d |

| i2nonuniq | n_diff_pfx01 | e |

| i2nonuniq | n_diff_pfx02 | e,f |

| i2nonuniq | n_diff_pfx03 | e,f,a |

| i2nonuniq | n_diff_pfx04 | e,f,a,b |

| i3nonuniq | n_diff_pfx01 | g |

| i3nonuniq | n_diff_pfx02 | g,h |

| i3nonuniq | n_diff_pfx03 | g,h,a |

| i3nonuniq | n_diff_pfx04 | g,h,a,b |

+------------+--------------+------------------+

Based on the index statistics data shown above and the table definition, the following values can be determined:

基于上文的表定义以及索引的统计信息数据,可以得到下面的值:

n_cols_in_uniq_i, the total number of all columns in all unique indexes not counting the primary key columns, is 2 (c and d)
n_cols_in_uniq_i,所有唯一索引列的数量(不包括主键列),是2 (c and d)
n_cols_in_non_uniq_i, the total number of all columns in all non-unique indexes, is 4 (e, f, g and h)
n_cols_in_non_uniq_i,所有非唯一索引列的数量,4 (e, f, g and h)
n_cols_in_pk, the number of columns in the primary key, is 2 (a and b)
n_cols_in_pk,主键列的数量,2 (a and b)
n_non_uniq_i, the number of non-unique indexes in the table, is 2 (i2nonuniq and i3nonuniq))
n_non_uniq_i,非唯一索引的数量,2 (i2nonuniq and i3nonuniq)
n_part, the number of partitions, is 1.
n_part, 分区的数量,1

You can now calculate innodb_stats_persistent_sample_pages * (2 + 4 + 2 * (1 + 2)) * 1 to determine the number of leaf pages that are scanned. With innodb_stats_persistent_sample_pages set to the default value of 20, and with a default page size of 16 KiB (innodb_page_size=16384), you can then estimate that 20 * 12 * 16384 bytes are read for table t, or about 4 MiB.

现在你可以计算innodb_stats_persistent_sample_pages * (2 + 4 + 2 * (1 + 2)) * 1来确认要扫描的叶子节点数据页的数量。innodb_stats_persistent_sample_pages默认的值是20,默认数据页的大小是16 KiB (innodb_page_size=16384),你可以计算出b表需要都20 * 12 * 16384 bytes,大约4 MiB。

Note

All 4 MiB may not be read from disk, as some leaf pages may already be cached in the buffer pool.

所有的4 MiB不都是从磁盘读的,有些叶子节点的数据页可能已经被缓存在了buffer pool里了。

14.4.12 Configuring the Merge Threshold for Index Pages

Staring in MySQL 5.7.6, you can configure the MERGE_THRESHOLD value for index pages. If the "page-full" percentage for an index page falls below the MERGE_THRESHOLD value when a row is deleted or when a row is shortened by an UPDATE operation, InnoDB attempts to merge the index page with a neighboring index page. The default MERGE_THRESHOLD value is 50, which is the previously hardcoded value. The minimum MERGE_THRESHOLD value is 1 and the maximum value is 50.

从MySQL5.7.6开始,你可以配置索引页的MERGE_THRESHOLD值。如果当一行记录被删除了或者由于UPDATE操作行的大小变短了而造成索引页的"page-full"百分比低于了MERGE_THRESHOLD值,InnoDB会尝试使用相邻的索引页对当前的进行合并。MERGE_THRESHOLD默认的值是50(在这之前这个值是被写死的)。MERGE_THRESHOLD的值最小是1,最大是50。

When the "page-full" percentage for an index page falls below 50%, which is the default MERGE_THRESHOLD setting, InnoDB attempts to merge the index page with a neighboring page. If both pages are close to 50% full, a page split can occur soon after the pages are merged. If this merge-split behavior occurs frequently, it can have an adverse affect on performance. To avoid frequent merge-splits, you can lower the MERGE_THRESHOLD value so that InnoDB attempts page merges at a lower "page-full" percentage. Merging pages at a lower page-full percentage leaves more room in index pages and helps reduce merge-split behavior.

当一个索引页的"page-full"百分比低于了50%(MERGE_THRESHOLD的默认设定),InnoDB会尝试使用相邻的数据页进行合并。如果两个数据页都是接近50%的,那么合并之后不久这个数据页还会发生分离。乳沟这个合并-分离的操作果味频繁,这对性能就会有不利的影响。要避免频繁的合并-分离,你可以降低MERGE_THRESHOLD的值让InnoDB试图合并"page-full"百分比更小的数据页,这样就能够减少合并-分离的行为。

The MERGE_THRESHOLD for index pages can be defined for a table or for individual indexes. A MERGE_THRESHOLD value defined for an individual index takes priority over a MERGE_THRESHOLD value defined for the table. If undefined, the MERGE_THRESHOLD value defaults to 50.

索引页的MERGE_THRESHOLD可以为一个表定义,也可以为个别索引定义。为个别索引定义的MERGE_THRESHOLD值会覆盖表上定义的MERGE_THRESHOLD的值。如果没有进行定义,那么MERGE_THRESHOLD默认的值杀死 50。

Setting MERGE_THRESHOLD for a Table

You can set the MERGE_THRESHOLD value for a table using the table_option COMMENT clause of the CREATE TABLE statement. For example:

你可以在CREATE TABLE的时候使用COMMENT表定义子句来为一个表定义MERGE_THRESHOLD值。例如:

CREATE TABLE t1 (

id INT,

KEY id_index (id)

) COMMENT='MERGE_THRESHOLD=45';

You can also set the MERGE_THRESHOLD value for an existing table using the table_option COMMENT clause with ALTER TABLE:

你还可以在ALTER TABLE语句中使用COMMENT表定义子句为已存在的表设置MERGE_THRESHOLD的值:

CREATE TABLE t1 (

id INT,

KEY id_index (id)

);

ALTER TABLE t1 COMMENT='MERGE_THRESHOLD=40';

Setting MERGE_THRESHOLD for Individual Indexes

To set the MERGE_THRESHOLD value for an individual index, you can use the index_option COMMENT clause with CREATE TABLE, ALTER TABLE, or CREATE INDEX, as shown in the following examples:

要为个别索引设置MERGE_THRESHOLD,你可以在CREATE TABLE, ALTER TABLE, or CREATE INDEX的时候使用COMMENT索引参数子句,如下面的例子:

Setting MERGE_THRESHOLD for an individual index using CREATE TABLE:
在CREATE TABLE的时候为个别索引设置MERGE_THRESHOLD:

CREATE TABLE t1 (

id INT,

KEY id_index (id) COMMENT 'MERGE_THRESHOLD=40'

);

Setting MERGE_THRESHOLD for an individual index using ALTER TABLE:
在ALTER TABLE的时候为个别索引设置MERGE_THRESHOLD:

CREATE TABLE t1 (

id INT,

KEY id_index (id)

);

ALTER TABLE t1 DROP KEY id_index;

ALTER TABLE t1 ADD KEY id_index (id) COMMENT 'MERGE_THRESHOLD=40';

Setting MERGE_THRESHOLD for an individual index using CREATE INDEX:
在CREATE INDEX的时候为个别索引设置MERGE_THRESHOLD:

CREATE TABLE t1 (id INT);

CREATE INDEX id_index ON t1 (id) COMMENT 'MERGE_THRESHOLD=40';

Note

You cannot modify the MERGE_THRESHOLD value at the index level for GEN_CLUST_INDEX, which is the clustered index created by InnoDB when an InnoDB table is created without a primary key or unique key index. You can only modify the MERGE_THRESHOLD value for GEN_CLUST_INDEX by setting MERGE_THRESHOLD for the table.

你不能够在索引层面为GEN_CLUST_INDEX修改MERGE_THRESHOLD值。这是因为没有创建主键或者唯一索引而由InnoDB创建的clustered index。你只能通过为表设置MERGE_THRESHOLD而修改GEN_CLUST_INDEX的MERGE_THRESHOLD值。

Querying the MERGE_THRESHOLD Value for an Index

The current MERGE_THRESHOLD value for an index can be obtained by querying the INNODB_SYS_INDEXES table. For example:

一个索引的当前MERGE_THRESHOLD值可以通过查询INNODB_SYS_INDEXES表来获得。例如:

mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES WHERE NAME='id_index' \G

*************************** 1. row ***************************

INDEX_ID: 91

NAME: id_index

TABLE_ID: 68

TYPE: 0

N_FIELDS: 1

PAGE_NO: 4

SPACE: 57

MERGE_THRESHOLD: 40

You can use SHOW CREATE TABLE to view the MERGE_THRESHOLD value for a table, if explicitly defined using the table_option COMMENT clause:

如果使用表参数COMMENT进行了显式的定义,你可以使用SHOW CREATE TABLE来显示一个表的MERGE_THRESHOLD:

mysql> SHOW CREATE TABLE t2 \G

*************************** 1. row ***************************

Table: t2

Create Table: CREATE TABLE `t2` (

`id` int(11) DEFAULT NULL,

KEY `id_index` (`id`) COMMENT 'MERGE_THRESHOLD=40'

) ENGINE=InnoDB DEFAULT CHARSET=latin1

Note

A MERGE_THRESHOLD value defined at the index level takes priority over a MERGE_THRESHOLD value defined for the table. If undefined, MERGE_THRESHOLD defaults to 50% (MERGE_THRESHOLD=50, which is the previously hardcoded value.

索引层面定义的MERGE_THRESHOLD值的优先权要高于表级别的定义。如果没有定义,那么默认的值是50%(MERGE_THRESHOLD=50,这在以前是被写死的)。

Likewise, you can use SHOW INDEX to view the MERGE_THRESHOLD value for an index, if explicitly defined using the index_option COMMENT clause:

同样地,如果使用索引参数COMMENT子句显式定义了,你可以使用SHOW INDEX显示一个索引的MERGE_THRESHOLD值:

mysql> SHOW INDEX FROM t2 \G

*************************** 1. row ***************************

Table: t2

Non_unique: 1

Key_name: id_index

Seq_in_index: 1

Column_name: id

Collation: A

Cardinality: 0

Sub_part: NULL

Packed: NULL

Null: YES

Index_type: BTREE

Comment:

Index_comment: MERGE_THRESHOLD=40

Measuring the Effect of MERGE_THRESHOLD Settings

The INNODB_METRICS table provides two counters that can be used to measure the effect of a MERGE_THRESHOLD setting on index page merges.

INNODB_METRICS表提供了两个计数器用来测量MERGE_THRESHOLD设置在索引页合并上的影响。

mysql> SELECT NAME, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS

WHERE NAME like '%index_page_merge%';

+-----------------------------+----------------------------------------+

| NAME | COMMENT |

+-----------------------------+----------------------------------------+

| index_page_merge_attempts | Number of index page merge attempts |

| index_page_merge_successful | Number of successful index page merges |

+-----------------------------+----------------------------------------+

When lowering the MERGE_THRESHOLD value, the objectives are:

使用较小的MERGE_THRESHOLD值有下面这几个目的:

A smaller number of page merge attempts and successful page merges

A similar number of page merge attempts and successful page merges

A MERGE_THRESHOLD setting that is too small could result in large data files due to an excessive amount of empty page space.

MERGE_THRESHOLD设置的太小会导致大的数据文件产生过多的空数据页的空间。

For information about using INNODB_METRICS counters, see Section 14.13.6, "InnoDB INFORMATION_SCHEMA Metrics Table".

关于使用INNODB_METRICS计数器的信息可以查看Section 14.13.6, "InnoDB INFORMATION_SCHEMA Metrics Table"。

MySQL 5.6 Reference Manual-14.4 InnoDB Configuration的相关教程结束。

《MySQL 5.6 Reference Manual-14.4 InnoDB Configuration.doc》

下载本文的Word格式文档,以方便收藏与打印。