[mysql-manual-5.5]7.1 优化概览

translator: selfimpr

blog: http://blog.csdn.net/lgg201

mail: [email protected]


优化

优化是一个复杂的任务, 因为它的目的是整个系统被优化. 虽然你可以利用对你的系统或应用的一些认知做一些局部的优化, 但如果你想要更多的优化, 你就需要了解更多的知识.

本章解释一些优化Mysql的不同方式, 并提供示例.记住, 无论如何, 总会有其他方式让系统变得更快, 不过要达到这个目的需要更多的努力.

优化概要

让一个系统更快最重要的因素是它的基础设计. 你必须知道你的系统进行了怎样的处理, 以及它的瓶颈在哪里. 大多数情况下, 系统的瓶颈在以下几个方面:

  • 磁盘寻道: 磁盘查找一块数据需要时间. 对于现代的磁盘, 这方面的平均时间消耗通常小于10ms, 因此理论上说每秒可以寻道100次. 这种情况下新的磁盘的提升已经很缓慢, 并且对单表优化非常困难. 优化寻道时间的方法就是将数据放到多个磁盘上.
  • 磁盘读写: 当磁盘在正确的位置时, 我们需要读取数据. 对于现代的磁盘, 吞吐量至少在10-20MB/s. 这一点相比于寻道很容易优化, 因为你可以从多个磁盘并行读取.
  • CPU周期: 当我们在主存中有数据时, 我们需要处理它得到结果. 表相比于内存较小是最常见的限制因素. 但是对于小表, 速度通常不是问题.
  • 内存带宽: 当CPU需要的数据多余CPU缓存时, 主存的带宽就成为瓶颈. 这对于多数系统而言并不时常见的瓶颈, 但还是要知道它.

Mysql设计限制和折衷

当使用myisam存储引擎时, mysql使用了非常快速的表锁, 允许多个读者或一个写者. 这个存储引擎最大的问题发生在当你有一个稳定的在同一张表上混合更新和慢的查询操作流时. 如果某个表存在这个问题, 你可以选用其他存储引擎.

mysql同时支持事务表和非事务表. 为了让非事务表可以更容易平稳的工作(发生错误不能回滚), mysql有下面的规则. 注意这些规则仅适用于: a) 运行在非严格SQL模式; b) 未INSERT或UPDATE使用了IGNORE说明符

  • 所有的列都有默认值
  • 如果你向一列插入一个超出范围的值, mysql会将该列设置为最合理的值而不是报告错误. 对于数值, 它将是0, 最小可能值或最大可能值. 对于字符串, 则是空字符串或最大能够存入的字符串.
  • 所有的表达式都将返回一个可用的值, 而不是报告错误条件. 比如1/0返回NULL

要改变预定义行为, 你可以通过设置服务端的SQL模式启用严格数据处理.

为可移植性设计应用

因为所有的SQL服务都实现了标准SQL的不同部分, 因此编写可移植的数据库应用需要下一些功夫. 对于简单的select和insert, 很容易得到可移植性, 但是当你需要更多的能力时就会变得更加复杂. 如果你希望你的应用对于多数数据库系统都很快速, 那就更加困难了.

所有的数据库系统都有一些弱点. 也就是说它们采用了不同的折衷设计导致了不同的行为.

要使得复杂的应用可移植, 你需要确定它必须在哪些SQL服务器上工作, 接着确定那些服务器支持的特性. 你可以使用mysql的crash-me程序找出能用于数据库服务器选择的函数, 类型和限制. crash-me不会检查每个可能的特性, 但它涵盖的范围仍然很广, 执行大约450个测试. crash-me可以提供的信息的一个示例是: 如果你可能使用Informix或DB2, 就不应该使用长于18个字符的列名.

crash-me程序和mysql基准测试都是数据库无关的. 如果看了它们的编写实现, 你可能会有一种感觉: 你必须要让你的应用数据库无关. 程序可以在mysql源码包的sql-bench目录下找到. 他们使用perl和dbi数据库接口编写. 使用dbi解决了它自己的可移植性问题, 因为dbi提供了数据库无关的访问.

如果你为了数据库无关努力, 你需要对各种数据库服务器的瓶颈都有所了解. 比如, mysql在myisam表的取回和更新非常快, 但是在同一张表上混合慢的读者和写者时会有问题. 事务数据库系统通常在从日志表生成汇总表时表现不佳, 因为这种情况下行锁几乎无用.

为了让你的应用真的数据库无关, 你应该通过操纵你的数据定义简单的可扩展接口. 例如, c++在多数系统上都可用, 因此可以使用基于C++的数据库接口.

如果你使用了一些特定数据库系统的特性(比如mysql特有的replace语句), 你应该在其他SQL服务器上编写可选方法实现该特性. 尽管这可能比较慢, 但它至少能让其他服务器执行相同的任务.

对于mysql, 你可以使用/* ! */语法增加mysql特有的关键字到语句中. /* */中的代码被其他多数SQL服务器认为是注释.

如果像一些web应用一样, 高性能比精确性还要重要, 我们就可以创建一个应用层缓存所有可以给你带来高性能的数据. 通过让旧的结果失效可以保持缓存的新鲜度. 这里提供了一种处理高负载的方法, 你可以动态的增加缓存大小并设置失效时间, 直到事情恢复正常.

这种情况下, 表创建信息应该包含初始缓存大小以及表应该多长时间被刷新一次的信息.

相比于实现应用层缓存一个诱人的选择是使用mysql的查询缓存. 通过启用查询缓存, 服务端处理确定一个查询结果集是否可以被重用的细节. 这将简化你的应用.

mysql基准测试套件

这个基准测试套件是为了给出某个操作在给定SQL实现上执行的是好是坏. 你可以查看mysql源代码下的sql-bench目录的代码和结果, 了解基准测试工作.

注意: 这个基准测试是单线程的, 因此它测量了操作执行的最小时间. 我们计划在未来为其增加多线程测试.

要使用基准测试套件, 有以下前置条件:

  • 基准测试由mysql源代码分发包提供, 所以需要下载源码包.
  • 基准测试脚本使用perl以及per dbi模块访问数据库服务器, 因此dbi必须安装. 你还需要为要测试的服务端安装服务端特有的dbd驱动. 例如, 要测试mysql, postgresql, db2, 你必须有dbd:mysql, dbd:pg, dbd:db2模块.

基准测试运行:

$ perl run-all-tests --server=server_name

crash-me脚本也在sql-bench目录下. 它尝试确认数据库系统支持的特性, 以及它的能力和限制. 例如, 它确定:

  • 支持哪些数据类型
  • 支持多少种索引
  • 支持哪些函数
  • 可以有多大的查询
  • varchar列有多大

使用自己的基准测试

你也应该对你的应用和数据库做基准测试, 找出瓶颈. 在修复一个瓶颈后, 你可以着手找下一个瓶颈. 即便你的应用当前总体性能是可接受的, 你也应该至少为每个瓶颈有个计划并判断如果有一天你确实需要解决时该怎样解决.

另外还有一个免费的基准测试套件是: Open Source Database Benchmark.

系统在健康的负载下出现问题是很常见的. 我们有很多客户是在产品碰到负载问题时联系我们的. 多数情况下, 性能问题是由于基础数据库设计(比如, 在高负载下表扫描就不好)或操作系统或类库造成的. 大多数时候, 只要系统还没有产品化, 这些问题都比较容易解决.

为了避免这样的问题, 你应该花费一些精力到最糟糕的负载下你的整个应用的基准测试上:

  • mysqlslap程序通过多个客户端同时执行查询模拟高负载
  • 你还可以尝试Super Smack

上面介绍的这些工具可能会使你的系统瘫痪, 因此请确保在开发环境使用它们.


发布了123 篇原创文章 · 获赞 1149 · 访问量 130万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章