此页面为机器翻译。请阅读英文原文。 English

IBSurgeon 文库

IBAnalyst:了解您的数据库

Dmitri Kuzmenko, [email protected],最后更新于2014年3月31日

自1994年以来,我一直在使用InterBase。那时,大多数数据库都很小,不需要任何调优。当然,有时我不得不更改服务器上的ibconfig,并重新配置硬件或操作系统,但这就是我几乎能为性能调优所做的全部了。

四年前,我们公司开始为InterBase用户提供技术支持和培训。处理许多生产数据库也让我学到了很多不同的东西。然而,我学到的大部分内容都与应用程序有关–事务参数的使用、优化查询和结果集。

当然,我很早就知道gstat–这个提供数据库统计信息的工具。如果你曾经查看过gstat的输出,或者阅读过关于它的opguide.pdf,你就会知道统计输出看起来就像一堆数字,仅此而已。好吧,你可以发现某个特定表或索引的碎片化信息,但还能获得哪些其他有用的信息呢?

幸运的是,在接触InterBase之前,我就对不同数据结构、它们的存储方式以及它们使用的算法感兴趣。这帮助我解读了gstat的输出。那时我决定编写一个工具,可以分析gstat输出,以帮助调优数据库,或者至少找出性能问题的原因。

长话短说,最终结果是创建了IBAnalyst。尽管我有经验,它仍然能让我在不同的数据库中发现非常有趣的事情或性能问题。

真实系统的运行时性能像波浪一样波动。这种“波浪”的振幅可能低也可能高,所以你可以看到性能如何逐日(或逐小时)变化。实际性能取决于许多因素,包括应用程序的设计、服务器配置、事务并发性、数据库中的版本垃圾等。要找出数据库中正在发生的事情(性能的积极和消极方面),你至少应该不时地查看一下数据库统计信息。

真实系统的运行时性能像波浪一样波动。这种“波浪”的振幅可能低也可能高,所以你可以看到性能如何逐日(或逐小时)变化。实际性能取决于许多因素,包括应用程序的设计、服务器配置、事务并发性、数据库中的版本垃圾等。要找出数据库中正在发生的事情(性能的积极和消极方面),你至少应该不时地查看一下数据库统计信息。

让我们来看看IBAnalyst的功能。IBAnalyst可以从gstat或Services API获取统计信息,并将其编译成报告,为你提供关于数据库、其表和索引的完整信息。它在浏览统计信息时提供就地警告;它还包括提示注释和建议报告。

数据库信息

图1 数据库统计信息摘要

图1中显示的摘要提供了关于数据库的通用信息。显示的警告或注释基于从大量真实生产数据库中仔细收集的知识。

注意:本文中的所有图表都包含来自真实生产数据库的gstat统计信息(经其所有者许可)。

正如我之前所说,原始数据库统计信息看起来晦涩难懂,难以解读。IBAnalyst以黄色或红色清晰突出任何潜在问题,问题的详细信息只需将光标悬停在相关条目上并阅读显示的提示即可。

我们能从上面的图表中发现什么?这是一个方言3数据库,页面大小为4096字节。六到八年前,开发人员使用默认的1024字节页面大小,但在更近的时代,如此小的页面大小可能导致许多性能问题。由于此数据库的页面大小为4k,因此没有显示警告,因为这个页面大小是可以的。

接下来,我们可以看到Forced Write参数设置为OFF并标记为红色。InterBase 4.x和5.x默认情况下此参数为ON。Forced Writes本身是一种写缓存方法:当为ON时,它会立即将更改的数据写入磁盘,但OFF意味着写入将由操作系统在其文件缓存中存储不确定的时间。InterBase 6创建的数据库的Forced Writes为OFF。

为什么这在IBAnalyst报告中被标记为红色?答案很简单–使用异步写入在电源、操作系统或服务器故障的情况下可能导致数据库损坏。

提示:有趣的是,现代HDD接口(ATA、SATA、SCSI)在Forced Write设置为On或Off时,性能上没有显示出重大差异(1)。

报告中的下一项是神秘的“sweep interval”。如果为正,它设置了最旧(2)和最旧快照事务之间的间隔大小,当达到此阈值时,引擎会收到需要开始自动垃圾收集的警报。在某些系统上,达到此阈值会导致“突然性能下降”效应,因此有时建议将sweep interval设置为0(完全禁用自动清理)。在这里,sweep interval被标记为黄色,因为sweep gap的值为负,这在InterBase 6.0、Firebird和Yaffil统计中可能出现,但在InterBase 7.x中不会。当sweep gap的值大于sweep interval时(如果sweep interval不为0),报告中sweep interval的条目将被标记为红色并带有适当的提示。

我们将接下来的8行作为一个组来检查,因为它们都显示了数据库事务状态的各个方面:

  • 最旧事务是最旧的未提交事务。任何较低的事务编号都是已提交事务的,并且这些事务没有可用的记录版本。高于最旧事务的事务编号是可能处于任何状态的事务。这也被称为“最旧的有趣事务”,因为当事务以回滚结束时它会冻结,而服务器此时无法撤销其更改。
  • 最旧快照–在当前最旧“有趣”事务开始时存在的最旧活动(即尚未提交)事务。表示对记录版本感兴趣的最低快照事务编号。
  • 最旧活动–当前最旧的活动事务(3)。
  • 下一个事务–将分配给新事务的事务编号。
  • 活动事务–如果最旧活动事务编号比每日事务计数低30%,IBAnalyst将给出警告。统计信息不会告诉在最旧活动和下一个事务之间是否还有其他活动事务,但可能存在这样的事务。通常,如果最旧活动事务卡住,可能有两个原因:a)某个事务长时间处于活动状态,或b)应用程序设计允许事务长时间运行。这两个原因都会阻止垃圾收集并消耗服务器资源。
  • 每日事务数–这是从下一个事务计算得出的,除以自数据库创建到获取统计信息时点所经过的天数。这仅对生产数据库或定期从备份恢复(导致事务编号重置)的数据库才是正确的。

正如你已经了解到的,如果有任何警告,它们会以彩色行显示,并带有清晰、描述性的提示,说明如何修复或预防问题。

应该注意的是,数据库统计信息并不总是有用的。在工作期间和维护操作期间收集的统计信息可能没有意义。

在以下情况下不要收集统计信息:

  • 你刚刚恢复了数据库

  • 执行了备份(gbak -b db.gdb),但未使用 -g 开关

  • 最近执行了手动清理(gfix -sweep)

在这种情况下获得的统计信息实际上毫无用处。同样正确的是,在正常工作期间,有时数据库可能处于完美状态,例如,当应用程序对数据库的负载低于平时(用户正在午餐或业务日处于安静时段)时。

如何判断数据库何时出现问题?

您的应用程序可能设计得非常好,以至于它们始终能正确处理事务和数据,不会产生清理间隙,不会积累大量活动事务,不会保持长时间运行的快照等等。但通常情况并非如此(抱歉,各位同行)。

最常见的原因是开发人员在测试应用程序时只运行两三个并发用户。当应用程序随后在具有十五个或更多并发用户的生产环境中使用时,数据库可能会表现出不可预测的行为。当然,多用户模式可以正常工作,因为大多数多用户冲突可以通过两三个并发运行的应用程序进行测试。然而,随着用户数量的增加,垃圾回收问题可能会出现。如果您在正确的时机收集数据库统计信息,就可以捕捉到这些潜在问题。

表信息

让我们看一下来自 IBAnalyst 的另一个示例输出。

![](/images/article_IBAnalyst (1).jpg)

图 2 表统计信息

IBAnalyst 的表统计信息视图也非常有用。它可以显示哪些表有大量记录版本、哪些表进行了大量更新/删除操作、哪些表存在碎片(由更新/删除或 BLOB 引起的碎片)等等。您可以查看哪些表被频繁更新,以及表的大小(以兆字节为单位)。这些警告中的大多数都是可自定义的。

在此数据库示例中存在几个问题。首先,VerLen 列中的黄色警告表明记录版本占用的空间大于记录本身占用的空间。这可能是由于更新记录中的大量字段或批量删除导致的。请查看 MaxVers 列以蓝色标记的行。这表明每个记录只存储一个版本,因此问题是由批量删除引起的。Versions 列中的值显示了删除了多少条记录。

长期存在的活动事务阻止垃圾回收是性能下降的主要原因。对于某些表,可能仍有大量版本“正在使用中”。服务器无法确定它们是否真的在使用中,因为活动事务可能需要这些版本中的任何一个或全部。因此,服务器不会将这些版本视为垃圾,每当事务读取记录时,从大量版本中构建正确记录所需的时间越来越长。在图 2 中,您可以看到两个表的版本数比记录数高出三倍。利用此信息,您还可以检查应用程序频繁更新这些表是设计使然还是由于错误导致的。

索引视图

索引被数据库引擎用于强制执行主键、外键和唯一约束。它们还加速数据检索。唯一索引最适合数据检索,但非唯一索引的收益程度取决于索引数据的多样性。

例如,查看 ADDR_ADDRESS_IDX6。首先,索引名称本身表明它是手动创建的。如果统计信息是通过 Services API 获取的并包含元数据信息,您可以看到哪些列被索引(在 IBAnalyst 1.83 及更高版本中)。对于所检查的索引,您可以看到它有 34999 个键,TotalDup 为 34995,MaxDup 为 25056。两个重复列都以红色标记。这是因为该索引中所有键中只有 4 个唯一键值,如 Uniques 列所示。此外,最大的重复链(指向具有相同列值的记录的键)为 25056–即几乎所有键都存储了四个唯一值之一。因此,此索引可能:

  • 降低恢复过程的速度。好吧,三万五千个键对于现代数据库和硬件来说不算什么,但仍应注意其影响。
  • 减慢垃圾回收速度。唯一值数量较少的索引与完全唯一的索引相比,可能会使垃圾回收速度降低多达十倍。此问题已在 InterBase 7.1/7.5 和 Firebird 2.0 中解决。
  • 当优化器读取索引时产生不必要的页面读取。这取决于特定查询中搜索的值–通过具有较大 MaxDup 值的索引进行搜索会更慢。通过具有较少重复值的列进行搜索会更快,但只有您知道该列已被索引。

这就是为什么 IBAnalyst 会提醒您注意此类索引,将其标记为红色和黄色,并将其包含在“建议”报告中。不幸的是,大多数“不良”索引是为了强制执行外键约束而自动创建的。在某些情况下,可以通过使用触发器阻止查找表中主键的删除或更新来解决此问题。但如果无法实施此类更改,IBAnalyst 每次查看统计信息时都会在“外键”上显示“不良”索引。

报告

无需每次查看整个报告,通过识别单元格颜色并阅读新警告的提示来获取信息。使用 IBAnalyst 的“建议”功能可以获得更直接、更详细的信息。只需加载统计信息并转到“报告/查看建议”菜单。此报告提供逐步分析,包括关于强制写入、清理间隔、数据库活动、事务状态、数据库页面大小、清理、事务清单页面、碎片表、具有大量记录版本的表、大规模删除/更新、深度索引、不利于优化器的索引、无用索引甚至空表的更详细描述性警告。所有这些信息和相关建议都是根据加载的统计信息动态生成的。

作为报告输出的示例,让我们看一下为本文前面看到的数据库统计信息生成的报告:

“事务清单页面(TIP)的总体大小较大–94 千字节或 23 页。Read_committed 事务使用全局 TIP,但快照事务在内存中制作自己的 TIP 副本。较大的 TIP 大小可能会降低性能。尝试手动运行清理(gfix -sweep)以减小 TIP 大小。”

以下是报告表/索引部分的另一段引用:

“版本化表数量:8。大量记录版本通常会降低性能。如果表中有大量记录版本,则垃圾回收无法正常工作,或者记录未被任何 select 语句读取。您可以尝试在这些表上执行 select count(*) 以强制垃圾回收,但这可能需要很长时间(如果存在大量版本和非唯一索引),并且如果至少有一个事务对这些版本感兴趣,则可能不成功。

以下是版本/记录比率大于 3 的表列表:

表名 记录数 版本数 记录/版本大小
CLIENTS_PR 3388 10944 92%
DICT_PRICE 30 1992 45%
DOCS 9 2225 64%
N_PART 13835 72594 83%
REGISTR_NC 241 4085 56%
SKL_NC 1640 7736 170%
STAT_QUICK 17649 85062 110%
UO_LOCK 283 8490 144%

总结

IBAnalyst 是一款非常宝贵的工具,可帮助用户对 Firebird 或 InterBase 数据库统计信息进行详细分析,并识别数据库在性能、维护以及应用程序与数据库交互方式方面可能存在的问题。它将晦涩难懂的数据库统计信息以易于理解的图形方式显示出来,并自动提出关于改善数据库性能和简化数据库维护的合理建议。

1 InterBase 7.5 和 Firebird 1.5 具有特殊功能,可以在强制写入(Forced Writes)关闭时定期刷新未保存的页面。

2 最旧事务与各处提到的“最旧相关事务”(Oldest interesting transaction)相同。Gstat 输出不会将此事务显示为“相关”(interesting)。

3 Ann Harrison 表示,最旧活动事务是指当前最旧活动事务启动时处于活动状态的最旧事务。对于应用程序而言,这里没有太大区别。