- 首先拷贝 my.cnf / my.ini 文件副本.
- 依据使用的存储引擎及可用内存,设置 key_buffer_size 和innodb_buffer_pool_size.
- 慢查询(Slow queries)的修正通常是通过加入索引(indexes),改变表结构(schema),改变 SELECT 语句 来实现,而不是通过数据库调优.
- 不要随便设置查询缓存(Query cache),除非你真正掌握它的优缺点以及适用场景.
- 不要改变其它的參数,除非你遇到了相应的问题(如最大连接数问题, max connections).
- 确保改动的是 [mysqld] 这一节下的内容,而不是其它部分.
- 索引块(Index blocks,每一个1 KB,BTree结构、存放于 .MYI 文件) 缓存到 “key buffer” 中.
- 数据块缓存(Data block caching, 存放于 .MYD 文件里)交给操作系统负责, 所以确保留下了适量的空暇内存(给操作系统).
InnoDB将全部缓存都放在 “buffer pool” 中, 缓存池的大小通过 innodb_buffer_pool_size 控制. 包括被打开表(open tables)中的 16KB一块的数据/索引块,此外还有一些附加开销. MySQL 5.5(以及带插件的 5.1版本号)同意您指定 块大小(block size)为 8 KB或4 KB. MySQL 5.5能够有多个缓冲池,由于每一个缓存池有一个相互排斥锁, 所以设置多个池能够缓解一些相互排斥锁瓶颈. 还有一种计算缓存大小的方法 将主缓存(main cache)设置为最小值; 假设同一台机器上有很多其它应用在跑, 而且/或者RAM内存小于2GB, 那么能够这样指定. SHOW TABLE STATUS; 显示各个数据库中全部表的状态.
- 计算全部MyISAM表的 Index_length 值的总和. 让 key_buffer_size 小于等于这个和值.
- 计算全部 InnoDB表 Data_length + Index_length 值的总和. 设置 innodb_buffer_pool_size 为不超过总和值的110%.
SELECT ENGINE, ROUND(SUM(data_length) /1024/1024, 1) AS "Data MB", ROUND(SUM(index_length)/1024/1024, 1) AS "Index MB", ROUND(SUM(data_length + index_length)/1024/1024, 1) AS "Total MB", COUNT(*) "Num Tables" FROM INFORMATION_SCHEMA.TABLES WHERE table_schema not in ("information_schema", "performance_schema") GROUP BY ENGINE;相互排斥锁瓶颈 MySQL 是单核CPU时代设计的,且能够非常easy移植到不同的硬件体系架构中. 不幸的是,这导致了对连结锁(interlock)操作的凌乱. 在几个重要的流程中存在少量(非常少)的“相互排斥(mutexes)”. 包括:
- MyISAM的 key_buffer
- 查询缓存(Query Cache)
- InnoDB的buffer_pool
- 禁用超线程(HyperThreading)
- 停用超过8个核心以上的部分
- 超线程这里主要是指曾经的超线程技术,因此此部分可能不一定正确.
$ ulimit -a...max memory size (kbytes, -m) 524288因此,确定了 mysqld有多少可用内存, 就能够设置为 20% ~ 70%,但须要适当的减少一些. 假设系统报错,比如 [ERROR] /usr/libexec/mysqld: Out of memory (Needed xxx bytes) , 可能是MySQL申请了超过操作系统同意的内存范围. 须要减小缓存设置. 64位OS与32位MySQL 64位操作系统不受4 GB内存的限制,但32位MySQL依旧受这个限制. 假设你有 4 GB以上的内存,那么能够设置:
- key_buffer_size = 20%(全部RAM的),但不要超过3 GB.
- buffer_pool = 3G
- 仅仅使用MyISAM引擎: (5.0.52 ~ 5.1.23之前的)key_buffer_size有 4GB的硬性限制. 详情请參考 在更高版本号中,设置 key_buffer_size 为 20%的RAM. 在(my.cnf / my.ini)中加上 innodb_buffer_pool_size = 0.
- 仅仅使用InnoDB引擎: 设置 innodb_buffer_pool_size = 70%的RAM. 假设内存非常大,并使用 5.5(及以上)版本号,能够考虑使用 多个缓存池. 推荐设置 1 - 16 个 innodb_buffer_pool_instances, 每一个都不小于1 GB. (非常抱歉,没有最优设置为多少个的具体參考指标;但应该不能设置太多).
- 新手警告! QC与key_buffer和buffer_pool全然无关.
- 当命中时, QC速度快如闪电. 要创建一个运行快1000倍的基准測试并不难.
- 在QC中仅仅有一个相互排斥锁(译者注: 锁越少,就是锁钥匙越少,高并发时就会激烈竞争/等待).
- 除非将QC设置为OFF与0,否则每次查询都会去对照一遍.
- 真相,相互排斥锁会发生碰撞,即使 query_cache_type = DEMAND (2).
- 真相,相互排斥锁会发生碰撞,即便设置了 SQL_NO_CACHE.
- 查询语句仅仅要变了一点点(即使多了个空格)都可能导致在QC中生成多个不同的缓存项.
- 在一个表中发生不论什么 write 事件, QC中相应到这个表的全部条目都会被清除.
- 即便在仅仅读从server(readonly Slave)上也是这样.
- 清除使用的是线性算法来运行,所以QC较大(比方200MB)则会导致速度明显地变慢.
- query_cache_size = 不超过50M
- query_cache_type = DEMAND
- 在全部 SELECT 语句中指明 SQL_CACHE 或 SQL_NO_CACHE, 依据哪些查询可能会从QC缓存中命中.
RHEL,非常英明地,同意用户自己控制 OS 怎样进行预先内存交换分配. 总的来说这是非常好的策略,但对MySQL来说则是一个灾难.
(感觉翻译的有点不流畅,本段原文为: RHEL, in its infinite wisdom, decided to let you control how aggressively the OS will preemptively swap RAM. This is good in general, but lousy for MySQL)
MySQL期望相当稳定的内存分配 —— 缓存(大部分)是预先分配的; 线程(大都)是限制数量的. 不论什么内存交换都可能极大地损害MySQL的性能. 设置非常高的swappiness值,会丢失一些内存,由于操作系统试图为以后的分配保留大量的自由空间(MySQL通常是不须要的). 设置swappiness = 0,不交换,在内存不足时操作系统可能会崩溃,. 我宁愿MySQL一卡一卡的,也不希望他崩了. 对于MySQL-only(专用)server, 中间数(比方5 ?)可能是一个非常好的值. NUMA OK,是时候了解一些CPU管理内存的架构了. 我们先看 (Non-Uniform Memory Access, 非统一内存寻址). 每一个CPU(或多路server中的每一个socket(CPU插座)) 都挂载有一部分内存. 这使得訪问本地(local) RAM 非常快, 而訪问挂载在其它 CPU下的RAM要慢上数十个周期. 接着看操作系统. 在(RHEL ?)非常多情形下,有两个行为:
- OS分配的内存固定到 “first(第一个)” CPU名下.
- 接着分配的其它内存也默认分配到第一个CPU名下,直到它满了.
- OS与MySQL分配完了第一个 CPU的全部RAM.
- MySQL分配了第二个 CPU的部分内存.
- 操作系统OS还须要分配一些其它内存.
在MySQL中, innodb_buffer_pool 就是一个完美的使用者. 通过正确地配置这些,InnoDB能跑得更快一点:
- 启用 Huge pages
- 通知操作系统分配适当的数量(和 buffer_pool 个数一致)
- 通知MySQL使用huge pages
mysql> SHOW GLOBAL VARIABLES LIKE "key_buffer_size";+-----------------+----------+| Variable_name | Value |+-----------------+----------+| key_buffer_size | 76996608 |+-----------------+----------+注意,这部分设置MySQL会向下取整,对齐到一定的数字. 你可能须要改动两个地方(运行SET 并改动my.cnf),以使改动马上生效,而且下次重新启动后依旧是相同的值(无论是手动,还是其它原因又一次启动) Webserver 像Apache这种webserver使用多线程来处理. 假设每一个线程打开一个 MySQL连接,可能会超过同意的最大连接数. 确保将webserver的 MaxClients (或相似參数) 设置为一个合理的值(如50以下). 工具MySQLTuner TUNING-PRIMER 上面是几个对内存设置建议的工具. 当中有一个误导性条目: Maximum possible memory usage: 31.3G (266% of installed RAM) 可能使用的内存最大值为: 31.3G (可能是物理内存的 266%) 不要让它吓到你,这些工具使用的公式过于保守了. 他们假设全部 max_connections 都在使用而且处于活跃状态,并正在运行一些内存密集型的工作. Total fragmented tables: 23 有碎片的tables: 23 个 这意味着 OPTIMIZE TABLE 可能会有作用. 我建议对表设置高百分比的 “free space”(见SHOW TABLE STATUS) 或者你知道对什么表做了大量的删除/更新操作. 只是,不必费心频繁地对table进行OPTIMIZE 优化整理. 一个月一次可能就够了. 文章改动记录 2010创建;2012年10月更新,2014年1月更新; 更深入的文章: 通过 联系作者 ——里克·詹姆斯 里克·詹姆斯的MySQL相关文档
提示,调试、howto、优化相关等等……
(Rules of Thumb -- lots of tips)
-- includes differences between them
plus other insights into the mysteries of INDEXing
for time series
-- a common, poorly performing, design patter; plus an alternative
(efficient searching on Latitude + Longitude)
-- how to optimize the schema and code for such
(On beyond ORDER BY RAND())
(with Percona XtraDB Cluster / MariaDB)