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

IBSurgeon 文库

1 TB Firebird 数据库:初步报告

德米特里·库兹缅科,最后更新于2014年3月31日

本文档的翻译版本:葡萄牙语 俄语 中文

阅读我们关于更大(1.7太字节)数据库的文章:关于1.7太字节Firebird SQL数据库的更多详情

为什么要创建太字节级的Firebird数据库?

许多公司使用大型Firebird数据库,并依赖它们来支持重要的业务运营。一些Firebird数据库已经达到数百吉字节的规模,并且还在持续增长(参见“谁是大户?”部分),很容易预测它们何时会变成2倍、3倍或5倍大。因此,数据库管理员和供应商有兴趣研究Firebird在处理大型数据库时的表现,并获得一些管理建议。

此外,我们在创建1Tb Firebird数据库时考虑的一个重要原因是最终消除普遍认为Firebird是“小型数据库”数据库引擎的看法。这个神话现在似乎已经破灭,但一些分析师和记者经常将其从坟墓中挖出,我们希望最终结束这种荒谬的看法。

## 硬件

Firebird以其惊人的可扩展性而闻名,这项调查再次证实了这一点。这个实验的初始目的仅仅是创建一个1Tb大小的Firebird数据库,因此我们使用了普通的台式计算机:

表1:硬件

组件 参数
CPU AMDAthlon 64 x2 5200
内存 4GB
主板 MSI K9N Platinum
硬盘1(操作系统和临时文件) ST3160815AS,160GB,SATA II
硬盘2(辅助) HDT721064SLA360,640GB,SATA II
硬盘2(辅助) HDS728080PLA380,80GB,SATA I
硬盘3(数据库) ST31500341AS,1.5TB,SATA II(固件CC1H)

本质上,我们将1.5Tb硬盘放入办公室的一台台式机中,没有进行任何其他修改。该硬盘格式化的簇大小为16Kb(与数据库页面大小相同,如下所示)。

软件

由于这是一台台式计算机,操作系统为Windows XP Professional SP3,32位。为了实际执行测试,我们使用了基于TPC的工具包中的加载器(可从http://ibdeveloper.com/tests/tpc-c/下载,二进制文件和源代码均可用)。

我们想强调,加载器插入数据的方式与真实场景中的插入方式相同:记录被插入并分布在数据库内部(以及物理磁盘区域)的多个主-从-子从表中,而不是逐表插入。

表2:软件

软件 版本
操作系统 Windows XP Professional SP3,32位
Firebird 2.1.3 SuperServer(快照)
加载器 基于tpc测试的自定义加载器

计划

我们对这个实验有一个非常直接的计划:

  1. 创建数据库并加载1Tb数据,不带索引
  2. 创建主键和适当的索引(因此实际数据库大小超过1Tb)
  3. 收集数据库统计信息
  4. 运行几个SQL查询并评估数据库性能

数据库和Firebird服务器配置

数据库页面大小为16384字节,与硬盘簇大小相同,以最大化磁盘吞吐性能(在一次I/O周期内读/写1页)。

在Firebird配置中,我们配置了额外的临时空间目录,并将其指向640Gb的磁盘(其中约300Gb可用)。

加载步骤

数据通过几个步骤加载到该数据库中。在加载操作期间,计算机被用作普通台式机(我们运行了MS Office、Firefox、IBAnalyst等–大约8-12个程序同时运行)。如果我们只为此任务专用硬件,可能会更快,因此请将这些值仅视为低端示例;它们绝对不是最佳结果。

表3:加载操作

| |

描述
加载时间 约70小时
插入的总记录数 62亿
平均插入速度 24500条记录/秒
平均记录大小 146字节(最小13字节,最大600字节)
事务数 646489

我们花了约4天时间加载,之后我们得到了一个正好1Tb大小的Firebird数据库(即1 099 900 125 184字节)。

下面您可以在FBDataGuard查看器中看到数据库增长和事务动态:

索引

我们逐个创建索引,并记录了它们的创建时间和用于排序的临时文件的大小。

最大的索引是为表ORDER_LINE创建的。其主键包含四个字段(Smallint、Smallint、Integer和Smallint)。此排序索引的临时文件为182Gb,数据库中最终索引大小为29.3Gb。

有趣的是,即使对于拥有38亿条记录的表,索引深度也为3,因为页面大小为16384字节,因此使用主键搜索该表的数据时没有额外开销。

统计信息

之后,我们收集了数据库统计信息。耗时7小时32分45秒。

我们将关键统计信息放入一个表中,并包含了一些查询和时间测量:

表4:1Tb数据库的综合统计信息

表名 记录数 大小,Gb select count(*)的执行时间 索引创建时间 临时文件大小,Gb 索引大小,Gb

| WAREHOUSE | 1240 | 0.002 | 0s | 0 | 0 | 0.0 | | ITEM | 100000 | 0.012 | 0.7s | - | - | 0.0 | | DISTRICT | 124000 | 0.017 | 0.7s | 6 | - | 0.0 | | NEW_ORDER | 111600000 | 32 | 20m 00s | 23m 00s | 4.56 | 0.8 | | CUSTOMER | 372000000 | 224 | - | 41m 00s | - | 2.6 | | customer_last | | | | 1h 52m 32s | 12.4 | 2.3 | | fk_cust_ware | | | | 2h 10m 51s | - | 2.3 | | HISTORY | 372000000 | 32 | - | - | - | - | | ORDERS | 372000000 | 25 | 32m 00s | 45m 41s | 15.2 | 2.5 | | STOCK | 1240000000 | 404 | - | 3h 34m 44s | 41.5 | 9.2 | | ORDER_LINE | 3720051796 | 359 | - | 12h 6m 18s | 182.0 | 29.3 |

数据库统计信息可从此处下载。

您可以使用免费的 FBDataGuard Community Edition 查看器来解读文本数据,不仅可以看到数据库性能指标,还能了解 CPU 和内存消耗情况。

查询

首先,我们对几个表执行了 select count(*) 查询(见上表第 4 列)。众所周知,由于 Firebird 的多版本特性,对整个表执行 select count(*) 对服务器来说是一项昂贵的操作,因为它需要访问每一页数据,经验丰富的 Firebird 开发者通常不会使用 select count(*),但我们使用它来展示数据库和硬件的整体性能比率。

执行完 select count 查询后,我们运行了来自真实场景的查询,说实话,我们对如此出色的结果感到惊讶。请自行查看:

查询 统计信息 描述
select w_id, w_name, c_id, c_last
from WAREHOUSE, customer
where c_w_id = w_id
PLAN JOIN (WAREHOUSE NATURAL, CUSTOMER INDEX (FK_CUST_WARE))
------ 性能信息 ——
准备时间 = 15ms
执行时间 = 79ms
平均获取时间 = 6.08 ms
当前内存 = 272 264 476
最大内存 = 272 514 048
内存缓冲区 = 16 384
从磁盘读取到缓存 = 82
从缓存写入磁盘 = 0
从缓存获取 = 3 648
对包含 12400 和 372000000 条记录的表进行简单连接,无 WHERE 条件。“平均获取时间 = 6.08 ms” 指获取第一行的时间。
select w_id, w_name, c_id, c_last
from WAREHOUSE, customer
where c_w_id = w_id and c_w_id = 10000
PLAN JOIN (WAREHOUSE INDEX (WAREHOUSE_PK), CUSTOMER INDEX (FK_CUST_WARE))
------ 性能信息 ——
准备时间 = 16ms
执行时间 = 78ms
平均获取时间 = 6.00 ms
当前内存 = 272 266 148
最大内存 = 272 514 048
内存缓冲区 = 16 384
从磁盘读取到缓存 = 88
从缓存写入磁盘 = 0
从缓存获取 = 3 656
对相同表进行连接,条件强制选择近期记录。“平均获取时间 = 6.00 ms” 指获取第一行的时间。
select count(*)
from WAREHOUSE, customer
where c_w_id = w_id and c_w_id = 10000
结果 = 30000
PLAN JOIN (WAREHOUSE INDEX (WAREHOUSE_PK), CUSTOMER INDEX (FK_CUST_WARE))
------ 性能信息 ——
准备时间 = 0ms
执行时间 = 453ms
平均获取时间 = 453.00 ms
当前内存 = 272 263 844
最大内存 = 272 514 048
内存缓冲区 = 16 384
从磁盘读取到缓存 = 1 048
从缓存写入磁盘 = 0
从缓存获取 = 60 024
统计上一个查询的记录数
SELECT * FROM ORDER_LINE
WHERE OL_W_ID = 500
Plan
PLAN (ORDER_LINE INDEX (ORDER_LINE_PK))
------ 性能信息 ——
准备时间 = 0ms
执行时间 = 94ms
平均获取时间 = 7.23 ms
当前内存 = 136 445 536
最大内存 = 136 592 176
内存缓冲区 = 8 192
从磁盘读取到缓存 = 150
从缓存写入磁盘 = 0
从缓存获取 = 2 402
对最大表(38 亿条记录)的查询。“平均获取时间 = 7.23 ms” 指获取第一行的时间。
<br>Plan<br>
<br>PLAN (ORDER_LINE INDEX (ORDER_LINE_PK))<br>
<br> <br>
<br>------ 性能信息 ------<br>
<br>准备时间 = 0ms<br>
<br>执行时间 = 3s 438ms<br>
<br>平均获取时间 = 0.01 ms<br>
<br>当前内存 = 136 445 496<br>
<br>最大内存 = 136 592 176<br>
<br>内存缓冲区 = 8 192<br>
<br>从磁盘读取到缓存 = 1 840<br>
<br>从缓存写入磁盘 = 0<br>
<br>从缓存获取 = 598 636<br>
SELECT * FROM ORDER_LINE
WHERE OL_W_ID = 500
对最大表(38 亿条记录)的相同查询,但这次我们获取了所有记录(共获取 299245 条记录)。
select w_id, w_name, c_id, c_last
from WAREHOUSE, customer
where c_w_id = w_id and (c_w_id > 8000) and (c_w_id < 10000)
Plan
PLAN JOIN (WAREHOUSE INDEX (WAREHOUSE_PK), CUSTOMER INDEX (FK_CUST_WARE))
------ 性能信息 ——
准备时间 = 0ms
执行时间 = 125ms
平均获取时间 = 9.62 ms
当前内存 = 272 270 824
最大内存 = 272 514 048
内存缓冲区 = 16 384
从磁盘读取到缓存 = 91
从缓存写入磁盘 = 0
从缓存获取 = 3 659
连接包含 1240 条记录和 3.72 亿条记录的表。
select count(*)
from WAREHOUSE, customer
where c_w_id = w_id and (c_w_id > 8000) and (c_w_id < 10000)
结果 = 59 970 000
Plan
PLAN JOIN (WAREHOUSE INDEX (WAREHOUSE_PK), CUSTOMER INDEX (FK_CUST_WARE))
------ 性能信息 ——
准备时间 = 0ms
执行时间 = 13m 4s 718ms
平均获取时间 = 784 718.00 ms
当前内存 = 272 268 532
最大内存 = 272 514 048
内存缓冲区 = 16 384
从磁盘读取到缓存 = 2 332 583
从缓存写入磁盘 = 0
从缓存获取 = 119 977 902
统计上一个查询的记录数

总结

在此实验中,Firebird 展示了以下结果:

  1. 毫无疑问能够处理大型数据库。我们相当确信,在合适的硬件上可以创建和使用 32 Tb 的数据库,Firebird 将展现出与较小数据库(即 1Tb 及以下)相同的高性能。

  2. 良好的可扩展性和令人惊叹的小内存占用。1Tb 数据库是在普通台式电脑上创建的,更重要的是,它可以用于执行常规查询:如果您不获取数百万条记录,查询速度与中等规模数据库(10-15Gb)相同。

这并非本实验的终点:我们计划运行一些查询,收集更多统计信息,并很快发布更详细的报告。请持续关注。

联系方式

请将所有问题和咨询发送至 [email protected]