`

MYSQL 调优和使用必读

 
阅读更多

MYSQL 应该是最流行了 WEB 后端数据库。WEB 开发语言最近发展很快,PHP Ruby, Python, Java 各有特点,虽然 NOSQL 最近越來越多的被提到,但是相信大部分架构师还是会选择 MYSQL 来做数据存储。

MYSQL 如此方便和稳定,以至于我们在开发 WEB 程序的时候很少想到它。即使想到优化也是程序级别的,比如,不要写过于消耗资源的 SQL 语句。但是除此之外,在整个系统上仍然有很多可以优化的地方。

1. 选择合适的存储引擎: InnoDB

除非你的数据表使用来做只读或者全文检索 (相信现在提到全文检索,没人会用 MYSQL ),你应该默认选择 InnoDB 

你自己在测试的时候可能会发现 MyISAM  InnoDB 速度快,这是因为: MyISAM 只缓存索引,而 InnoDB 缓存数据和索引,MyISAM 不支持事务。但是 如果你使用 innodb_flush_log_at_trx_commit = 2 可以获得接近的读取性能 (相差百倍

1.1 如何将现有的 MyISAM 数据库转换为 InnoDB:

mysql -u [USER_NAME] -p -e "SHOW TABLES IN [DATABASE_NAME];" | tail -n +2 | xargs -I '{}' echo "ALTER TABLE {} ENGINE=InnoDB;" > alter_table.sql

perl -p -i -e 's/(search_[a-z_]+ ENGINE=)InnoDB/\1MyISAM/g' alter_table.sql

mysql -u [USER_NAME] -p [DATABASE_NAME] < alter_table.sql

1.2 为每个表分别创建 InnoDB FILE

innodb_file_per_table=1

这样可以保证 ibdata1 文件不会过大,失去控制。尤其是在执行 mysqlcheck -o all-databases 的时候。

2. 保证从内存中读取数据,讲数据保存在内存中

2.1 足够大的 innodb_buffer_pool_size

推荐将数据完全保存在 innodb_buffer_pool_size ,即按存储量规划 innodb_buffer_pool_size 的容量。这样你可以完全从内存中读取数据,最大限度减少磁盘操作。

2.1.1 如何确定 innodb_buffer_pool_size 足够大,数据是从内存读取而不是硬盘?

方法 1

mysql> SHOW GLOBAL STATUS LIKE 'innodb_buffer_pool_pages_%';

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

| Variable_name                    | Value  |

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

| Innodb_buffer_pool_pages_data    | 129037 |

| Innodb_buffer_pool_pages_dirty   | 362    |

| Innodb_buffer_pool_pages_flushed | 9998   |

| Innodb_buffer_pool_pages_free    | 0      |  !!!!!!!!

| Innodb_buffer_pool_pages_misc    | 2035   |

| Innodb_buffer_pool_pages_total   | 131072 |

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

6 rows in set (0.00 sec)

发现 Innodb_buffer_pool_pages_free  0,则说明 buffer pool 已经被用光,需要增大 innodb_buffer_pool_size

InnoDB 的其他几个参数:

innodb_additional_mem_pool_size = 1/200 of buffer_pool

innodb_max_dirty_pages_pct 80%

方法 2

或者用iostat -d -x -k 1 命令,查看硬盘的操作。

2.1.2 服务器上是否有足够内存用来规划

执行 echo 1 > /proc/sys/vm/drop_caches 清除操作系统的文件缓存,可以看到真正的内存使用量。

2.2 数据预热

默认情况,只有某条数据被读取一次,才会缓存在 innodb_buffer_pool。所以,数据库刚刚启动,需要进行数据预热,将磁盘上的所有数据缓存到内存中。数据预热可以提高读取速度。

对于 InnoDB 数据库,可以用以下方法,进行数据预热:

1. 将以下脚本保存为 MakeSelectQueriesToLoad.sql

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='InnoDB'

                ) B USING (table_schema,table_name)

            WHERE B.table_schema NOT IN ('information_schema','mysql')

            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

;

2. 执行

mysql -uroot -AN < /root/MakeSelectQueriesToLoad.sql > /root/SelectQueriesToLoad.sql

3. 每次重启数据库,或者整库备份前需要预热的时候执行:

mysql -uroot < /root/SelectQueriesToLoad.sql > /dev/null 2>&1

2.3 不要让数据存到 SWAP 

如果是专用 MYSQL 服务器,可以禁用 SWAP,如果是共享服务器,确定 innodb_buffer_pool_size 足够大。或者使用固定的内存空间做缓存,使用memlock 指令。

 

3. 定期优化重建数据库

mysqlcheck -o all-databases 会让 ibdata1 不断增大,真正的优化只有重建数据表结构:

 

CREATE TABLE mydb.mytablenew LIKE mydb.mytable;

INSERT INTO mydb.mytablenew SELECT * FROM mydb.mytable;

ALTER TABLE mydb.mytable RENAME mydb.mytablezap;

ALTER TABLE mydb.mytablenew RENAME mydb.mytable;

DROP TABLE mydb.mytablezap;

4. 减少磁盘写入操作

4.1 使用足够大的写入缓存 innodb_log_file_size

但是需要注意如果用 1G  innodb_log_file_size ,假如服务器当机,需要 10 分钟来恢复。

推荐 innodb_log_file_size 设置为 0.25 * innodb_buffer_pool_size

4.2 innodb_flush_log_at_trx_commit

这个选项和写磁盘操作密切相关:

innodb_flush_log_at_trx_commit = 1 则每次修改写入磁盘

innodb_flush_log_at_trx_commit = 0/2 每秒写入磁盘

如果你的应用不涉及很高的安全性 (金融系统),或者基础架构足够安全,或者 事务都很小,都可以用 0 或者 2 来降低磁盘操作。

4.3 避免双写入缓冲

innodb_flush_method=O_DIRECT

5. 提高磁盘读写速度

RAID0 尤其是在使用 EC2 这种虚拟磁盘 (EBS) 的时候,使用软 RAID0 非常重要。

6. 充分使用索引

6.1 查看现有表结构和索引

SHOW CREATE TABLE db1.tb1\G

6.2 添加必要的索引

索引是提高查询速度的唯一方法,比如搜索引擎用的倒排索引是一样的原理。

索引的添加需要根据查询来确定,比如通过慢查询日志或者查询日志,或者通过 EXPLAIN 命令分析查询。

ADD UNIQUE INDEX

ADD INDEX

6.2.1 比如,优化用户验证表:

添加索引

ALTER TABLE users ADD UNIQUE INDEX username_ndx (username);

ALTER TABLE users ADD UNIQUE INDEX username_password_ndx (username,password);

每次重启服务器进行数据预热

echo “select username,password from users;” > /var/lib/mysql/upcache.sql

添加启动脚本到 my.cnf

[mysqld]

init-file=/var/lib/mysql/upcache.sql

6.2.2 使用自动加索引的框架或者自动拆分表结构的框架

比如,Rails 这样的框架,会自动添加索引,Drupal 这样的框架会自动拆分表结构。会在你开发的初期指明正确的方向。所以,经验不太丰富的人一开始就追求从 0 开始构建,实际是不好的做法。

7. 分析查询日志和慢查询日志

记录所有查询,这在用 ORM 系统或者生成查询语句的系统很有用。

log=/var/log/mysql.log

注意不要在生产环境用,否则会占满你的磁盘空间。

记录执行时间超过 1 秒的查询:

long_query_time=1

log-slow-queries=/var/log/mysql/log-slow-queries.log

8. 激进的方法,使用内存磁盘

现在基础设施的可靠性已经非常高了,比如 EC2 几乎不用担心服务器硬件当机。而且内存实在是便宜,很容易买到几十G内存的服务器,可以用内存磁盘,定期备份到磁盘。

 MYSQL 目录迁移到 4G 的内存磁盘

mkdir -p /mnt/ramdisk

sudo mount -t tmpfs -o size=4000M tmpfs /mnt/ramdisk/

mv /var/lib/mysql /mnt/ramdisk/mysql

ln -s /tmp/ramdisk/mysql /var/lib/mysql

chown mysql:mysql mysql

9.  NOSQL 的方式使用 MYSQL

B-TREE 仍然是最高效的索引之一,所有 MYSQL 仍然不会过时。

 HandlerSocket 跳过 MYSQL  SQL 解析层,MYSQL 就真正变成了 NOSQL

10. 其他

单条查询最后增加 LIMIT 1,停止全表扫描。

将非”索引”数据分离,比如将大篇文章分离存储,不影响其他自动查询。

不用 MYSQL 内置的函数,因为内置函数不会建立查询缓存。

PHP 的建立连接速度非常快,所有可以不用连接池,否则可能会造成超过连接数。当然不用连接池 PHP 程序也可能将

连接数占满比如用了 @ignore_user_abort(TRUE);

使用 IP 而不是域名做数据库路径,避免 DNS 解析问题

11. 结束

你会发现优化后,数据库的性能提高几倍到几百倍。所以 MYSQL 基本还是可以适用大部分场景的应用的。优化现有系统的成本比系统重构或者迁移到NOSQL 低很多。

免费领取兄弟连IT教育原创linux运维工程师视频/细说linux教程,详情咨询官网客服:http://www.lampbrother.net/linux/

PHPLinuxHTML5UIAndroid等视频教程(课件+笔记+视频)!联系Q2430675018

 

     Linux交流群:478068715 欢迎各位加入!

分享到:
评论

相关推荐

    MySQL开发和DBA必读书

    此外,它还探讨了事务处理、锁机制、崩溃恢复和数据安全性等方面,对于数据库设计和调优至关重要。 其次,《高性能MySQL 第三版》是MySQL性能优化的经典之作。这本书全面涵盖了MySQL的性能提升策略,包括查询优化、...

    MySQLDBA修炼之道

    5. **性能调优与架构篇**:这一部分探讨如何通过优化SQL查询、调整系统参数、使用分区和分片技术来提升MySQL的性能。同时,还会介绍分布式数据库架构、读写分离、缓存策略,以及如何应对大数据场景下的挑战。 6. **...

    mysql 5.1官方简体中文参考手册

    MySQL 5.1是MySQL数据库管理系统的一个重要版本,它提供了高效、可靠且功能丰富的数据库解决方案。这份官方简体中文参考...实际手册将提供详细的操作指南、示例和参考信息,帮助读者深入理解和使用MySQL数据库系统。

    MySQL5.1 简体中文参考文档

    10. **性能监控与调优**:通过监控工具如SHOW STATUS和SHOW VARIABLES,可以评估MySQL的运行状态并进行性能调优。了解如何分析性能瓶颈并进行优化是提升数据库效率的关键。 除了以上核心内容,参考文档可能还会包含...

    oracle新手必读

    ### Oracle新手必读知识点 #### Oracle数据库与SQL的区别 在开始深入探讨Oracle数据库之前,我们需要了解Oracle数据库与标准SQL(Structured Query Language)之间的差异。尽管SQL是大多数数据库系统中的通用查询...

    数据库 database 推荐书目

    针对Oracle数据库,这本书提供了全面的技术指南,包括数据库安装、配置、性能调优及高级特性,适合Oracle数据库管理员和开发人员。 10. 《MySQL数据库应用与开发》(作者:赵立东译;电子工业出版社) 这本MySQL...

    java程序员面试宝典pdf版

    2. 数据类型:包括基本数据类型和引用数据类型,了解它们的存储方式及使用场景。 3. 控制结构:学习if语句、switch语句、for循环、while循环等,以及三元运算符的应用。 4. 函数:理解函数的定义、参数传递、返回值...

    计费管理pb

    3. **使用说明.txt**:这是系统操作手册,详细介绍了如何使用计费管理PB系统,包括登录、操作界面、功能模块的介绍和使用流程。用户在系统运行后需要参考此文档来熟悉各项功能。 4. **20067291668561**:这个文件名...

    大数据 76 道面试题及答案.docx

    大数据76道面试题及答案 ...本资源总结了大数据面试的76个问题及答案,涵盖了Hadoop框架的优化、HBase、Hive、MapReduce、YARN等多个方面的知识点,是大数据开发人员和面试者不可错过的必读资源。

    让我们开始百万年薪架构师的四个阶段

    在学习过程中,阅读《下载地址.txt》和《源码必读.txt》等资料将大有裨益,它们可能包含了业界最佳实践和经典项目的源代码分析,能够帮助你更好地理解和应用所学知识。 总的来说,成为一名百万年薪架构师不仅需要...

    .net门禁识别系统

    2. 识别精度优化:通过算法调优和训练提高人脸识别的准确率,降低误报和漏报。 3. 安全性考虑:保护用户数据安全,防止非法访问和篡改。 4. 性能优化:处理大量并发请求,确保系统在高负载下仍能正常运行。 总结...

    Eclipse开发分布式商城系统+完整视频代码及文档

    │ │ JVM调优实战.doc │ │ Tomcat7优化.docx │ │ 深入理解Java内存模型.pdf │ │ │ └─课后资料 │ ├─笔记 │ │ 淘淘商城_day20_课堂笔记.docx │ │ │ └─视频 │ 07-使用Jedis连接集群操作.avi │ ...

    性能测试核心知识解惑

    性能测试是一个很有前途但又很没前途的职业,很有前途是因为做的好能带来高收益,能解决项目和系统的很多疑难问题,甚至是大问题(现实中有多少系统崩溃的悲惨案例,造成的损失很多时候让人承受不起),而优秀的性能...

Global site tag (gtag.js) - Google Analytics