原文:
7.4.5. The MyISAM Key Cache
To minimize disk I/O, the MyISAM storage engine exploits a strategy that is used by many database management systems. It employs a cache mechanism to keep the most frequently accessed table blocks in memory:
-
For index blocks, a special structure called the key cache (or key buffer) is maintained. The structure contains a number of block buffers where the most-used index blocks are placed.
-
For data blocks, MySQL uses no special cache. Instead it relies on the native operating system file system cache.
This section first describes the basic operation of the MyISAM key cache. Then it discusses features that improve key cache performance and that enable you to better control cache operation:
To control the size of the key cache, use the key_buffer_size system variable. If this variable is set equal to zero, no key cache is used. The key cache also is not used if the key_buffer_size value is too small to allocate the minimal number of block buffers (8).
MySQL Enterprise. For expert advice on identifying the optimum size for key_buffer_size, subscribe to the MySQL Enterprise Monitor. See http://www.mysql.com/products/enterprise/advisors.html.
When the key cache is not operational, index files are accessed using only the native file system buffering provided by the operating system. (In other words, table index blocks are accessed using the same strategy as that employed for table data blocks.)
An index block is a contiguous unit of access to the MyISAM index files. Usually the size of an index block is equal to the size of nodes of the index B-tree. (Indexes are represented on disk using a B-tree data structure. Nodes at the bottom of the tree are leaf nodes. Nodes above the leaf nodes are nonleaf nodes.)
All block buffers in a key cache structure are the same size. This size can be equal to, greater than, or less than the size of a table index block. Usually one these two values is a multiple of the other.
When data from any table index block must be accessed, the server first checks whether it is available in some block buffer of the key cache. If it is, the server accesses data in the key cache rather than on disk. That is, it reads from the cache or writes into it rather than reading from or writing to disk. Otherwise, the server chooses a cache block buffer containing a different table index block (or blocks) and replaces the data there by a copy of required table index block. As soon as the new index block is in the cache, the index data can be accessed.
If it happens that a block selected for replacement has been modified, the block is considered “dirty.” In this case, prior to being replaced, its contents are flushed to the table index from which it came.
Usually the server follows an LRU (Least Recently Used) strategy: When choosing a block for replacement, it selects the least recently used index block. To make this choice easier, the key cache module maintains all used blocks in a special list (LRU chain) ordered by time of use. When a block is accessed, it is the most recently used and is placed at the end of the list. When blocks need to be replaced, blocks at the beginning of the list are the least recently used and become the first candidates for eviction.
译文:
为了减小disk的I/O,MyISAM的存储引擎和一般的数据库系统一样,使用了缓存机制保存经常访问的block(index block)。
- 对于索引块(index block),Key Cache中保存了常用的索引块。
- 对于数据块(data block),MySQL没有使用Cache,只是使用了操作系统中文件系统本身的Cache。
基本的功能机制和性能优化选项。
- 多session并发访问Cache
- 可以set up多重Key Cache,并指定一个table index给指定的Cache。
参数key_buffer_size设置为0或者过小时不使用Key Cache,也就是和数据块一样只能使用操作系统中文件系统自带的Cache。
一个索引块一般是MyISAM的索引文件的连续访问的组合。一般索引块的大小是MyISAM的索引结构中节点的大小(MyISAM的索引以BTREE结构存放)。
所有Key Cache中的block buffer是一样大的,可以大于、等于、小于索引块的大小。
当需要访问索引数据时,服务器检查是否有现成的block buffer在Key Cache中。若有,则从Key Cache中读取而不是disk上读取。也就是说,对索引的读和写均在Key Cache上(写的部分到时候要flush到disk上)。若没有,服务器将Cache中包含的不同表的索引块的block buffer替换成请求的索引块的拷贝,然后再提供读写。
当一个block被替换之前已经被修改过了,这个block就被标记为”脏”。这种情况下,在再次替换前,先将这个block flush到所属表的index文件上(在disk上)。
服务器一般使用LRU策略:当选择被替换的block时,选择最近最少使用的索引块。为了更好地实现该算法,Key Cache模块将所有的block按时间顺序放在一个list中(LRU链),当一个block被访问时,它被放在最近最常使用的位置(即LRU链的结尾,MRU端)。当一个block需要被替换时,LRU的开头部分(LRU端)就是优先考虑的部分,没有再到MRU部分找。