mysql的设计局限和折中
当使用MyISAM存储引擎的时候,mysql使用多读者单写者的很快速的锁表方式。
但是当你对一个表进行比较慢的select和很多平稳的混合updates的时候,这种存储
引擎就会出大问题,如果是对特定表有这种问题,你可以使用其它存储引擎。
原始的存储引擎是ISAM,是管理non-transactional 表的,不过已经被MyISAM替代了。
从3.23.0开始,引入了MyISAM和HEAP引擎。MyISAM是ISAM的改进替代。HEAP引擎提供了
in-memory 表。从mysql 3.23.25开始加入了MERGE引擎。它可以让相同的MyISAM表
当作一个表来处理。这三个引擎都是用来处理non-transactional 表的。都是mysql
默认带着的。现在HEAP引擎是以 MEMORY 引擎闻名。
InnoDB 和 BDB 引擎处理transaction-safe 表
NDB Cluster 是mysql cluster用来处理多个计算机上分散表的引擎。
ARCHIVE引擎是从4.1.3加入的,用来存储在非常小的footprint里没有index的大两数据。
CSV引擎是4.1.4加入的,存储用逗号分隔的文本格式的数据。
mysql可以在transactional和non-transactional 表上工作,为了在non-transactional
表上平滑工作,(这种表没法roll back)。mysql有以下规则(在没有在strict 模式下
或者你在insert和update里使用了IGNORE:
·所有column 有默认值
·如果你在一列里插入了``incorrect'' value,比如在一个数值类型的列里插入了
超大的数,mysql会把这一值改成最可能的值,而不是报错。对于数值来说,就是0
对字符串来说就是空或者是能放下的最长的字符串。
·所有的计算表达式返回结果而不是出错信息。比如1/0,返回NULL,
设计可移植的程序
由于所有的SQL 服务程序都是实现的标准sql的不同部分,要想写可移植的SQL程序就得花
功夫了,要是只是简单的select 和insert,要达到可移植就很容易,但是如果你要实现
更多功能,那就比较难了。如果再想让程序在数据库系统上跑得快,那就更难了。
要让一个复杂的程序可移植,你需要决定它必须能工作在什么SQL服务器上,然后决定
这些服务器支持什么功能。
所有的数据系统都有弱点,他们有不同的设计折衷导致不同的表现。
你可以使用mysql 的crash-me 程序来查找你可以使用的一类数据库服务的函数,类型和
限制,crash-me 并不查找所有的可能特性,但是仍然相当全面,会执行450项测试。
一个crash-me 提供的类型的信息的例子是你不能让列名超过18个字符,如果你想让他们
在infomix或者DB2上使用的话。
crash-me 程序和 MYSQL benchmarks 是完全数据库独立的。你看看他们是怎么写的,
你就可以对自己应该怎样让程序独立有个认识。你可以在mysql 源码的`sql-bench'
目录下面找到他们,它们是用perl 和 DBI 接口实现的,DBI 用来解决可移植性的
问题,因为它提供了数据库独立访问的函数。
For crash-me results, visit http://dev.mysql.com/tech-resources/crash-me.php.
See http://dev.mysql.com/tech-resources/benchmarks/ for the results from the
benchmarks.
如果你在为数据库独立性而奋斗,你需要对每种SQL 服务程序的瓶颈有较好的认识。
例如,MySQL 可以对MyISAM 表进行非常快速的检索和更新,但是对同样的表在mixing
slow readers and writers 上有问题。 另一方面,Oracle 在你试图访问刚更新过
的几行数据的时候就会出大问题(直到他们被更新到磁盘上), Transactional 数据库
一般来说在从log tables 生成 summary table 的时候不太好,因为这种情况下
row locking 基本没用。
要想让你的程序真的数据库独立,你需要定义一个简单的可扩展的接口来操纵你的数据,
由于C++ 在大多数系统都可用,用C++来作基于类的接口就比较有感觉。
如果你用了一些特定数据库系统的功能。比如Mysql的REPLACE 语句。你要在其他数据库
服务器上执行同样功能就得写一个替代的方法。可能替代方法比较慢,但至少可以让
其他服务器完成同样任务。
使用MySQL,可以在query种加入特有的/*! */句法,/* */之间的代码对其他服务器来说
一般都会被认做是注释,
如果高性能比精确更重要,比如一些WEB 程序,比较可行的是建立一个应用层来cache
查询的结果,这样能带来比较高的性能,让旧的查询结果过一段时间``expire'' ,就
可以让cache刷新,这提供了一个解决高load 峰值的方法。在这种情况下你可以动态
地增加cache和设定过期时间直到变会正常状态。
在这种情况下,建立表的信息应该包含cache的初始化大小和表刷新的时间。
另一个执行程序cache的方法是使用 MySQL query cache. By enabling the query cache
the server handles the details of determining whether a query result can be
reused. This simplifies your application. See section 5.11 The MySQL Query Cache
.
我们用Mysql来作什么
这节我们介绍一个早期的MySQL程序
在MySQL初始开发的时候,MySQL的特性是针对我们最大的客户,两个瑞典最大的零售商
处理数据仓库的。
从所有的商店,我们得到每周的所有bonus card 交易 的摘要,期望能够为所有的商店主
提供有用的信息来帮助他们得出他们的广告宣传对他们的客户是否起作用。
数据量是巨大的(每个月七百万的概要交易),我们有4-10年的数据要提供给用户,
我们每周都得到用户的要求,要从这些数据里得到紧急的报告。
我们每个月存储所有信息到压缩的``transaction'' 表里来解决问题,我们有一套
简单的 macros 来生成按不同标准分组的(产品分组,客户id,商店等等)summary 表,
我们用一个perl的脚本来生成web的报告,这个脚本执行sql语句得到结果生成页面,
我们其实应该用PHP或者mod_perl来代替,不过当时没办法。
对于图形数据,我们用c写了一个简单的工具可以处理SQL的查询结果并根据结果生成
GIF图片。这个工具也是动态执行的perl脚本来生成页面。
在大多数情况下,一个报告可以简单的通过复制一个已有的脚本并修改里面的SQL查询来
产生。在有些情况下,我们需要对已有的summary表增加列或者生成新表,这也十分简单
因为我们把所有的交易存储表放在磁盘上。这意味着50G的交易表和200G的其他客户数据。
我们还让我们的客户直接使用ODBC来访问summary表。这样高级用户可以自己拿数据
作实验。
这个系统工作的很好,我们用很简朴的 Sun Ultra SPARCstation (2x200MHz)运行起来
没有问题,最终这个系统移植到了linux上。
MySQL Benchmark Suite
本节应该包含mysql benchmark suite(以及crash-me) 的技术描述,但是这个介绍还没
写,现在,你可以看看mysql 源码的`sql-bench' 目录下的代码和结果来得到一个比较
好的认识。
这个基准套件用来告诉用户一个操作让mysql执行起来好还是差。
这个测试工具是单线程的,所以它能衡量一个操作执行的最短时间,我们计划在将来
加入多线程测试。
要使用这些套件,下面的必须满足:
这个套件在mysql 源码发布包里提供
测试脚本用perl和DBI模块访问数据库,所以DBI必须安装,你还需要server特定DBD
驱动。例如,如果你需要测试 MySQL, PostgreSQL, and DB2,就需要DBD::mysql,
DBD::Pg, and DBD::DB2 的模块,
After you obtain a MySQL source distribution, you will find the benchmark suite
located in its `sql-bench' directory. To run the benchmark tests, build MySQL, t
hen change location into the `sql-bench' directory and execute the run-all-tests
script:
shell> cd sql-bench
shell> perl run-all-tests --server=server_name
server_name is one of the supported servers. To get a list of all options and su
pported servers, invoke this command:
shell> perl run-all-tests --help
The crash-me script also is located in the `sql-bench' directory. crash-me tries
to determine what features a database supports and what its capabilities and li
mitations are by actually running queries. For example, it determines:
What column types are supported
How many indexes are supported
What functions are supported
How big a query can be
How big a VARCHAR column can be
You can find the results from crash-me for many different database servers at ht
tp://dev.mysql.com/tech-resources/crash-me.php. For more information about bench
mark results, visit http://dev.mysql.com/tech-resources/benchmarks/.