我正在尝试通过优化 Mysql 服务器来提高网站的性能。除了常规优化之外,我感觉某些写入操作花费的时间太长了。
该服务器是 Mac os x server 10.5.8(我认为这是一个 32 位操作系统),配备 2x2.8 GHz 四核英特尔至强处理器和 8 GB 内存。
有 2 个很少使用的 InnoDB 表,其他 45 个表是 MyISAM。
整个数据库为 1.2 GB,其中包括一个 400 MB 的日志表,该日志表仅被应用程序写入而从不被读取。
我认为将整个数据库放在 RAM 中可以提高性能。此外,我认为在系统发生故障时容忍一些数据丢失可以提高写入性能,但我不知道如何配置它以利用这一点。可能丢失的数据并不重要,如果丢失,用户可以重新创建。
该网站大约有 1 或 2 名同时访问者。
我已经运行了 mysqltuner.pl 的一些迭代。以下是当前结果:
>> MySQLTuner 1.2.0 - Major Hayden <[email protected]>
-------- General Statistics --------------------------------------------------
[--] Skipped version check for MySQLTuner script
[OK] Currently running supported MySQL version 5.0.92-log
[!!] Switch to 64-bit OS - MySQL cannot currently use all of your RAM
-------- Storage Engine Statistics -------------------------------------------
[--] Status: -Archive -BDB -Federated +InnoDB -ISAM -NDBCluster
[!!] InnoDB is enabled but isn't being used
[OK] Total fragmented tables: 0
-------- Security Recommendations -------------------------------------------
ERROR 1142 (42000) at line 1: SELECT command denied to user ''@'localhost' for table 'user'
[OK] All database users have passwords assigned
-------- Performance Metrics -------------------------------------------------
[--] Up for: 16m 57s (4K q [4.126 qps], 122 conn, TX: 6M, RX: 1M)
[--] Reads / Writes: 97% / 3%
[--] Total buffers: 922.0M global + 12.4M per thread (100 max threads)
[!!] Allocating > 2GB RAM on 32-bit systems can cause system instability
[!!] Maximum possible memory usage: 2.1G (26% of installed RAM)
[OK] Slow queries: 0% (0/4K)
[OK] Highest usage of available connections: 2% (2/100)
[!!] Cannot calculate MyISAM index size - re-run script as root user
[OK] Query cache efficiency: 42.5% (1K cached / 3K selects)
[OK] Query cache prunes per day: 0
[OK] Sorts requiring temporary tables: 0% (0 temp sorts / 36 sorts)
[OK] Temporary tables created on disk: 8% (6 on disk / 68 total)
[OK] Thread cache hit rate: 98% (2 created / 122 connections)
[OK] Table cache hit rate: 53% (58 open / 109 opened)
[OK] Open file limit used: 4% (103/2K)
[OK] Table locks acquired immediately: 100% (3K immediate / 3K locks)
-------- Recommendations -----------------------------------------------------
General recommendations:
Add skip-innodb to MySQL configuration to disable InnoDB
MySQL started within last 24 hours - recommendations may be inaccurate
这是我的 my.cnf
# The MySQL server
[mysqld]
port = 3306
socket = /var/mysql/mysql.sock
skip-locking
key_buffer = 384M
max_allowed_packet = 1M
table_cache = 1024
sort_buffer_size = 2M
read_buffer_size = 2M
read_rnd_buffer_size = 8M
myisam_sort_buffer_size = 64M
thread_cache_size = 8
query_cache_size = 512M
# Try number of CPU's*2 for thread_concurrency
thread_concurrency = 8
skip-thread-priority
log_slow_queries = 1
long_query_time = 1
在重新启动 mysql 之前,我有 3 个大概 100K 个查询的慢查询,但是我在哪里可以找到这些查询的日志?
//
答案1
您说“感觉有些写入操作耗时长得令人无法接受”。是什么让您有这种感觉?您是否尝试过措施它有什么?
如果你使用的是 OS X,跟踪是衡量这类事情的绝佳工具。有些人已经做了一些这为你工作。至少,使用vmstat
、iostat
或iotop
来确定您是否看到磁盘计时明显减慢。
您的query_cache_size
缓存可能太大了。写入操作必须使查询缓存中该表的所有条目失效。 查询缓存越大,花费的时间越长这可能是导致写入速度变慢的原因。手册建议“几十兆字节”。您应该逐步将其调低,并在每次更改后测量性能,以确定您的大小应该为多大。
该Table locks acquired immediately: 100% (3K immediate / 3K locks)
值表明 MyISAM 表锁定对您来说不是问题。对于写入与读取比率较高的 MyISAM 表来说,这可能会成为一个严重问题。
写入磁盘的查询包含在慢查询跟踪中,因此如果您看到 INSERT、UPDATE、REPLACE、DELETE、TRUNCATE 等查询很慢,则表明您遇到了问题。
慢查询日志可以是文件或表,也可以是两者。由于您似乎没有为其指定位置,因此应该使用默认值。 来自手册中关于慢查询日志的部分和日志位置部分:
如果您未指定慢查询日志文件的名称,则默认名称为 host_name-slow.log。除非给出绝对路径名来指定其他目录,否则服务器将在数据目录中创建该文件。
答案2
鉴于您提到的这些因素
- MySQL 5.0.92
- 32位操作系统
这很快排除了使用 InnoDB 的可能性,因为 MySQL 5.0 没有可以使用多核的 InnoDB(具有可以使用多核的 InnoDB 的 MySQL 最旧版本是 5.1.38 InnoDB 插件)。
您无法将整个数据库放在 RAM 中,因为 MyISAM 仅缓存索引。但是,您可以将所有 MyISAM 索引加载到键缓冲区中。
你需要做的第一件事是计算正确大小密钥缓冲区大小。这里有一个查询来帮你计算:
SELECT CONCAT(ROUND(KBS/POWER(1024,
IF(PowerOf1024<0,0,IF(PowerOf1024>3,0,PowerOf1024)))+0.4999),
SUBSTR(' KMG',IF(PowerOf1024<0,0,
IF(PowerOf1024>3,0,PowerOf1024))+1,1))
recommended_key_buffer_size FROM
(SELECT LEAST(POWER(2,31),KBS1) KBS
FROM (SELECT SUM(index_length) KBS1
FROM information_schema.tables
WHERE engine='MyISAM' AND
table_schema NOT IN ('information_schema','mysql')) AA ) A,
(SELECT 2 PowerOf1024) B;
请注意,如果所有 MyISAM 索引的总和超过 2G,则建议上限将为 2G。另请注意:SQL 语句包含子句(SELECT 2 PowerOf1024) B
。这将以 MB 为单位输出建议。使用(SELECT 1 PowerOf1024) B
以 KB 为单位的输出。使用(SELECT 3 PowerOf1024) B
以 GB 为单位的输出。
好的,您现在知道 MyISAM 键缓冲区的大小了。如何加载它?
运行这个:
SELECT DISTINCT CONCAT('SELECT ',ndxcollist,' FROM ',
db,'.',tb,' ORDER BY ',ndxcollist,';') SelectQueryToLoadCache
FROM (SELECT engine,table_schema db,table_name tb,index_name,
GROUP_CONCAT(column_name ORDER BY seq_in_index) ndxcollist
FROM (SELECT B.engine,A.table_schema,A.table_name,A.index_name,
A.column_name,A.seq_in_index
FROM information_schema.statistics A INNER JOIN
(SELECT engine,table_schema,table_name FROM information_schema.tables
WHERE engine='MyISAM' AND table_schema NOT IN ('information_schema','mysql')) B
USING (table_schema,table_name)
WHERE A.index_type <> 'FULLTEXT'
ORDER BY table_schema,table_name,index_name,seq_in_index) A
GROUP BY table_schema,table_name,index_name) AA
ORDER BY db,tb;
此查询将显示强制所有 MYI 索引页进入键缓冲区所需运行的每个查询。将此查询输出到脚本并运行该输出:
SQLSTMT="SELECT DISTINCT CONCAT('SELECT ',ndxcollist,' FROM ',db,'.',tb,' ORDER BY ',ndxcollist,';') SelectQueryToLoadCache FROM (SELECT engine,table_schema db,table_name tb,index_name,GROUP_CONCAT(column_name ORDER BY seq_in_index) ndxcollist FROM (SELECT B.engine,A.table_schema,A.table_name,A.index_name,A.column_name,A.seq_in_index FROM information_schema.statistics A INNER JOIN (SELECT engine,table_schema,table_name FROM information_schema.tables WHERE engine='MyISAM' AND table_schema NOT IN ('information_schema','mysql')) B USING (table_schema,table_name) WHERE A.index_type <> 'FULLTEXT' ORDER BY table_schema,table_name,index_name,seq_in_index) A GROUP BY table_schema,table_name,index_name) AA ORDER BY db,tb;"
mysql -u... -p.... -AN -e"${SQLSTMT}" > MyISAMIndexPreload.sql
mysql -u... -p.... -A < MyISAMIndexPreload.sql
试一试 !!!
答案3
如果您有 8Gb 的 RAM,并不意味着将整个 DB 放在 RAM 中。Os 也会使用一些内存进行内部操作。
我建议在 my.cnf 中进行一些设置,它们可能会对你有用
Increase your `key_buffer` from 384M to some high value may be to 512MB as you have sufficien RAM
用于缓存 MyISAM 表的索引块的键缓冲区的大小。不要将其设置为大于可用内存的 30%,因为操作系统也需要一些内存来缓存行。即使您不使用 MyISAM 表,您仍应将其设置为 8-64M,因为它还将用于内部临时磁盘表。
set table_open_cache to 2048
更新
为了正确配置您的 my.cnf,请访问优化 my.cnf
尝试一下它也许会对你有帮助...