mysql innodb 表优化_MYSQL之性能优化 ----INNODB下修改表结构

教训:

解决问题的过程很值得学习!

为什么性能是提升了10倍以上呢?每当日志文件写满后,最差的解决方案:关闭文件、删除文件、新建日志文件、重新开始写(请思考这个过程中的代价,打开、

关闭特别费时间);最好的解决方案:写满后fseek到日志开头重新开始写(一次seek的代价,事实上MySQL使用两个同样的日志文件进行轮回的)。

所以时刻记住fseek是一个奢侈的东西

其实这个问题有点弱智(疏忽),但是解决过程很有意思 :)

和这个问题相关的还有写参数可以调整,但是都不是瓶颈所以不多说了

--------------------------------------------

Unix上在哪里指定选项?

在Unix上,mysqld从下列文件,如果它们存在的话。以下列的顺序读取选项:

·

/etc/my.cnf

全局选项。

·

$MYSQL_HOME/my.cnf

服务器专用选项。

·

defaults-extra-file

--defaults-extra-file选项指定的文件。

·

~/.my.cnf

用户专用选项。

MYSQL_HOME代表环境变量,它内含着到包含服务器专用my.cnf文件的目录的路径。

如果你确信mysqld只从指定文件读取选项,你可以在启动服务器之时在命令行使用--defaults-option作为第一个选项:

mysqld --defaults-file=your_path_to_my_cnf

一个高级的my.cnf例子。假设你有一台Linux计算机,有2GB内存和三个60GB硬盘(在目录路径/,

/dr2和/dr3)。下列例子显示了在my.cnf里对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 = /ibdata/ibdata1:2000M;/dr2/ibdata/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

#

innodb_log_files_in_group = 2

#

# 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 lines if you want to use them

#innodb_thread_concurrency=5

注意,该例子把两个数据文件放在不同磁盘上。InnoDB开始用第一个数据文件填充表空间。在一些情况下,如果所有数据不被放置在同一

物理磁盘上,这样将改善数据库的性能。把日志文件放在与数据文件不同的磁盘上对性能是经常很有好处的。你也可以使用原始磁盘分区(原始设备)作为

InnoDB数据文件,这样可以加速I/O。请参阅15.2.14.2节,“为表空间使用原始设备”。

警告:在32位GNU/Linux

x86上,你必须要小心不要设置过高的内存用量。glibc可能允许进程堆积在线程堆栈上发展,它会造成你的服务器崩溃。如果下列表达式的值接近或者超过2GB,系统会面临危机:

innodb_buffer_pool_size

+ key_buffer_size

+ max_connections*(sort_buffer_size+read_buffer_size+binlog_cache_size)

+ max_connections*2MB

每个线程使用一个堆栈(通常是2MB,但在MySQL

AB二进制分发版里只有256KB)并且在最坏的情况下也使用sort_buffer_size +

read_buffer_size附加内存。

你可以自己编译MySQL,在32位Windows上使用高达64GB物理内存。请参阅15.2.4节,“InnoDB启动选项”里对innodb_buffer_pool_awe_mem_mb的描述。

如何调整其它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

InnoDB性能调节提示

原文来自《MySQL 中文手册

5.1.x》

·

如果Unix的top工具或者Windows任务管理器显示,你的数据库的工作负荷的CPU使用率小于70%,则你的工作负荷可能是磁盘绑定的,可能你正生成太多的事务和提交,或者缓冲池太小。使得缓冲池更大一些会有帮助的,但不要设置缓冲池等于或超过物理内存的80%.

·

把数个修改放在一个事务里。如果事务对数据库修改,InnoDB在该事务提交时必须刷新日志到磁盘。因为磁盘旋转的速度至多167转/秒,如果磁盘没有骗操作系统的话,这就限制提交的数目为同样的每秒167次。

· 如果你可以接受损失一些最近的已提交事务,你可以设置参数

innodb_flush_log_at_trx_commit 为

0。无论如何InnoDB试着每秒刷新一次日志,尽管刷新不被许可。

·

使用大的日志文件,甚至让它与缓冲池一样大。当InnoDB写满日志文件时,它不得不在一个检查点把缓冲池已修改的内容写进磁盘。小日志文件导致许多不必要的吸盘写操作。大日志文件的缺点时恢复时间更长。

·

也让日志缓冲相当大(与8MB相似的数量)。

·

如果你存储变长字符串,或者列可能包含很多NULL值,则使用VARCHAR列类型而不是CHAR类型。一个CHAR(N)列总是占据N个字节来存储,即使字符串更短或字符串的值是NULL。越小的表越好地适合缓冲池并且减少磁盘I/O。

当使用row_format=compact (MySQL

5.1中默认的InnoDB记录格式)和可变长度字符集,比如GB2312或sjis,CHAR(N)将占据可变数量的空间,至少为N

字节。

·

在一些版本的GNU/Linux和Unix上,用Unix的fsync()(InnoDB默认使用的)把文件刷新到磁盘,并且其他相似的方法是惊人的慢。如果你不满意数据库的写性能,你可以试着设置参数

innodb_flush_method 值为 O_DSYNC,虽然 O_DSYNC 在多数系统上看起来更慢。

· 当在Solaris 10上,为x86_64架构(AMD

Opteron)使用InnoDB存储引擎,重要的是使用forcedirectio选项来安装任何为存储与InnoDB相关的文件而使用的数据系统。(默认在Solaris

10/x86_64上不使用这个文件系统安装选项 )。使用forcedirectio

失败会导致InnoDB在这个平台上的速度和性能严重下降。

·

当导入数据到InnoDB中之时,请确信MySQL没有允许autocommit模式,因为允许autocommit模式会需要每次插入都要刷新日志到磁盘。要在导入操作规程中禁止autocommit模式,用SET

AUTOCOMMIT和COMMIT语句来包住导入语句:

SET AUTOCOMMIT=0;

COMMIT;

· 如果你使用mysqldump 选项--opt,即使不用SET

AUTOCOMMIT和COMMIT语句来包裹,你也使得快速的转储文件被导入到InnoDB表中。

·

小心大宗插入的大回滚:InnoDB在插入中使用插入缓冲来节约磁盘I/O,

但是在相应的回滚中没有使用这样的机制。一个磁盘绑定的回滚可以用相应插入花费时间的30倍来执行。杀掉数据库进程没有是帮助的,因为回滚在服务器启动时会再次启动。除掉一个失控的回滚的唯一方法是增大缓冲池使得回滚变成CPU绑定且跑得快,或者使用专用步骤,请参阅15.2.8.1节,“强制恢复”。

· 也要小心其它大的磁盘绑定操作。用 DROP TABLE 或

CREATE TABLE 来清空一个表,而不是用 DELETE FROM tbl_name。

·

如果你需要插入许多行,则使用多行插入语法来减少客户端和服务器之间的通讯开支:

INSERT INTO yourtable VALUES (1,2), (5,5), ...;

这个提示对到任何表类型的插入都是合法的,不仅仅是对InnoDB类型。

·

如果你在第二个键上有UNIQUE约束,你可以在导入会话中暂时关闭唯一性检查以加速表的导入:

SET UNIQUE_CHECKS=0;

对于大表,这节约了大量磁盘I/O,因为InnoDB可以使用它的插入缓冲来在一批内写第二个索引记录。

· 如果你对你的表有FOREIGN

KEY约束,你可以在导入会话过程中通过关闭外键检查来提速表的导入:

SET

FOREIGN_KEY_CHECKS=0;

对于大表,这可以节约大量的磁盘I/O。

·

如果你经常有对不经常更新的表的重发查询,请使用查询缓存:

[mysqld]

query_cache_type = ON

query_cache_size = 10M

你可能感兴趣的:(mysql,innodb,表优化)