使系统快速运行的最重要因素是其基本设计。您还必须知道系统正在执行哪种处理以及其瓶颈是什么。在大多数情况下,系统瓶颈来自以下来源:
当使用MyISAM存储引擎时,MySQL使用极其快速的表锁定,该锁定允许多个读取器或单个写入器。当您在单个表上有稳定的混合更新流和缓慢的选择流时,将出现此存储引擎的最大问题。如果某些表存在此问题,则可以为它们使用另一个存储引擎。
MySQL可以使用事务表和非事务表。为了使非事务表(在出现问题时无法回滚)的平滑工作变得更加容易,MySQL具有以下规则。请注意,这些规则仅在不以严格的SQL模式运行或将IGNORE说明符用于INSERT或UPDATE时适用。
要更改上述行为,可以通过适当设置服务器SQL模式来启用更严格的数据处理。
由于所有SQL服务器都实现标准SQL的不同部分,因此需要编写可移植的数据库应用程序。对于非常简单的选择和插入,很容易实现可移植性,但是,您需要的功能越多,难度就越大。如果您想要一个与许多数据库系统一起快速运行的应用程序,它将变得更加困难。
所有数据库系统都有一些弱点。即,它们具有导致不同行为的不同设计折衷。
为了使复杂的应用程序具有可移植性,您需要确定它必须使用哪些SQL服务器,然后确定这些服务器支持哪些功能。您可以使用MySQL crash-me程序查找可以与选择的数据库服务器一起使用的函数,类型和限制。crash-me不会检查所有可能的功能,但是它仍然相当全面,可以执行约450次测试。crash-me可以提供的信息类型的一个示例是,如果您希望能够使用Informix或DB2,则不应使用长度超过18个字符的列名。
在碰撞我的程序和MySQL基准都非常独立于数据库。通过查看它们的编写方式,您可以了解为使自己的应用程序数据库独立而必须执行的操作。可以在MySQL源分发的sql-bench目录中找到这些程序。它们是用Perl编写的,并使用DBI数据库接口。使用DBI本身解决了部分可移植性问题,因为它提供了独立于数据库的访问方法。
如果要争取数据库独立性,则需要对每个SQL Server的瓶颈有所了解。例如,MySQL在为MyISAM表检索和更新行时非常快,但是在将慢速的读取器和写入器混合在同一表上时存在问题。另一方面,当您尝试访问最近更新的行(直到将它们刷新到磁盘)时,Oracle遇到了一个大问题。事务数据库系统通常不能很好地从日志表生成摘要表,因为在这种情况下,行锁定几乎没有用。
为了使您的应用程序真正独立于数据库,您应该定义一个易于扩展的接口,您可以通过该接口来操作数据。例如,大多数系统上都可以使用C ++,因此对数据库使用基于C ++类的接口是有意义的。
如果您使用特定于给定数据库系统的某些功能(例如REPLACE语句,该功能特定于MySQL),则应通过编码替代方法为其他SQL Server实现相同的功能。尽管替代方法可能较慢,但它使其他服务器可以执行相同的任务。
使用MySQL,您可以使用/ *!* /语法,用于将MySQL特定关键字添加到语句中。/ * * /中的代码被大多数其他SQL服务器视为注释(并忽略)。
如果对于某些Web应用程序而言,高性能比准确性更重要,则可以创建一个应用程序层来缓存所有结果,从而为您提供更高的性能。通过让旧结果在一段时间后过期,可以合理地保持缓存的新鲜度。这提供了一种处理高负载尖峰的方法,在这种情况下,您可以动态增加缓存大小,并设置更高的过期超时,直到一切恢复正常为止。
在这种情况下,表创建信息应包含有关初始高速缓存大小以及通常应多长时间刷新一次表的信息。
实现应用程序缓存的一种有吸引力的替代方法是使用MySQL查询缓存。通过启用查询缓存,服务器处理确定是否可以重用查询结果的详细信息。这简化了您的应用程序。
本节介绍了MySQL的早期应用程序。
在MySQL的最初开发过程中,MySQL的功能是为了适应我们最大的客户而设计的,该客户为瑞典几个最大的零售商处理数据仓库。
从所有商店,我们每周都会获得所有奖励卡交易的摘要,并有望为商店所有者提供有用的信息,以帮助他们找到广告活动如何影响自己的客户。
数据量非常大(每月约有700万次摘要交易),我们拥有410年需要呈现给用户的数据。我们每周收到客户的请求,这些客户希望立即从该数据访问新报告。
我们通过每月将所有信息存储在压缩的“事务表”中来解决此问题。我们有一组简单的宏,这些宏从存储交易的表中生成按不同条件(产品组,客户ID,商店等)分组的摘要表。这些报告是由小型Perl脚本动态生成的网页。该脚本解析网页,在其中执行SQL语句,然后插入结果。我们本来会使用PHP或mod_perl,但是当时它们不可用。
对于图形数据,我们用C语言编写了一个简单的工具,可以处理SQL查询结果并根据这些结果生成GIF图像。该工具也是从解析Web页面的Perl脚本中动态执行的。
在大多数情况下,只需复制现有脚本并修改其使用的SQL查询即可创建新报告。在某些情况下,我们需要在现有的汇总表中添加更多列或生成一个新的列。这也非常简单,因为我们将所有事务存储表都保留在磁盘上。(这总计约有50GB的交易表和200GB的其他客户数据。)
我们还允许客户使用ODBC直接访问摘要表,以便高级用户可以自己尝试数据。
该系统运行良好,并且使用适度的Sun Ultra SPARCstation硬件(2 x 200MHz)处理数据时,我们没有遇到任何问题。最终,系统被迁移到Linux。
该基准套件旨在告诉任何用户,给定的SQL实现执行的操作好坏。通过查看任何MySQL源代码发行版中sql-bench目录中的代码和结果,可以很好地了解基准测试的工作方式。
请注意,该基准测试是单线程的,因此它测量执行操作的最短时间。我们计划将来将多线程测试添加到基准套件中。
要使用基准套件,必须满足以下要求:
获得MySQL源代码分发后,您可以在其sql-bench目录中找到基准套件。要运行基准测试,请构建MySQL,然后将位置更改为sql-bench目录并执行run-all-tests脚本:
shell> cd sql-bench
shell> perl run-all-tests --server=server_name
server_name应该是受支持服务器之一的名称。要获取所有选项和支持的服务器的列表,请调用以下命令:
shell> perl run-all-tests --help
在碰撞我的脚本也位于SQL-板凳目录。crash-me尝试通过实际运行查询来确定数据库系统支持的功能以及其功能和局限性。例如,它确定:
您可以在该站点上从crash-me找到许多不同数据库服务器的结果。有关基准测试结果的更多信息,请访问此。
您绝对应该对应用程序和数据库进行基准测试,以找出瓶颈所在。在解决了一个瓶颈之后(或通过将其替换为“虚拟”模块),您可以继续确定下一个瓶颈。即使您的应用程序的总体性能目前可以接受,您还是应该至少为每个瓶颈制定一个计划,并在有一天确实需要额外的性能时决定如何解决它。
有关可移植基准测试程序的示例,请查看MySQL基准测试套件中的程序。您可以从此套件中获取任何程序,并根据自己的需要对其进行修改。这样,您可以尝试使用不同的解决方案来解决问题并进行测试,这对于您而言确实是最快的。
另一个免费的基准测试套件是“开放源数据库基准”,可在此链接上获得。
仅当系统负载很重时才发生问题是很常见的。我们有许多客户在生产中(经过测试)系统并且遇到负载问题时与我们联系。在大多数情况下,性能问题可能是由于基本数据库设计问题(例如,表扫描在高负载下效果不佳)或操作系统或库问题引起的。在大多数情况下,如果系统尚未投入生产,这些问题将更容易解决。
为避免出现此类问题,您应在可能的最坏负载下做出一些努力来对整个应用程序进行基准测试。您可以使用此链接上的 Super Smack 。顾名思义,它可以使系统瘫痪,因此请确保仅在开发系统上使用它。
本文主要参考书籍:
《高性能Mysql》第三版
《深入理解Mysql核心技术》