【问题标题】:Performance problem on Java DB Derby Blobs & DeleteJava DB Derby Blobs & Delete 的性能问题
【发布时间】:2010-10-27 23:12:10
【问题描述】:

我在删除 derby 中的 blob 时遇到了性能问题,想知道是否有人可以提供任何建议。

这主要是在 windows 和 solaris 下使用 10.4.2.0,虽然我也使用新的 10.5.1.1 候选版本进行了测试(因为它有很多 lob 更改),但这没有显着差异。

问题在于,对于包含许多大 blob 的表,删除单行可能需要很长时间(通常超过一分钟)。

我通过一个小测试重现了这一点,该测试创建了一个表,插入几行不同大小的 blob,然后删除它们。

表架构很简单,只是:

create table blobtest(id integer generated BY DEFAULT as identity, b blob)

然后我创建了 7 行,具有以下 blob 大小:1024 字节、1Mb、10Mb、25Mb、50Mb、75Mb、100Mb。

我已经读回了 blob,以检查它们是否已正确创建并且大小正确。

然后使用 sql 语句(“delete from blobtest where id = X”)删除它们。

如果我按创建顺序删除行,删除单行的平均时间为:

1024 字节:19.5 秒

1Mb:16 秒

10Mb:18 秒

25Mb:15 秒

50Mb:17 秒

75Mb:10 秒

100Mb:1.5 秒

如果我以相反的顺序删除它们,删除单行的平均时间是:

100Mb:20 秒

75Mb:10 秒

50Mb:4 秒

25Mb:0.3 秒

10Mb:0.25 秒

1Mb:0.02 秒

1024 字节:0.005 秒

如果我创建七个小块,删除时间都是瞬时的。

因此,删除时间似乎与表中行的整体大小有关,而不是与被删除的 blob 的大小有关。

我已经运行了几次测试,结果似乎可以重现。

那么,是否有人对性能有任何解释,以及如何解决或修复它的任何建议?它确实使在生产环境中使用大 blob 非常成问题……

【问题讨论】:

  • 我编辑了我的帖子来解释这个性能问题,并提出了另一种解决方法(除了更改数据库):将较大的文件移出数据库。

标签: java performance jdbc derby


【解决方案1】:

我也遇到了和你一样的问题。

我发现当我执行 DELETE 时,derby 实际上完全“读取”了大段文件。我使用 Filemon.exe 来观察它是如何运行的。

我的文件大小为 940MB,删除一行需要 90 秒。

我相信 derby 将表数据存储在单个文件里面。还有一些设计/实现错误如何导致它读取所有内容,而不是使用适当的索引。

我做批量删除而不是解决这个问题。 我重写了我的程序的一部分。它是“哪里 id=?”在自动提交中。 然后我重写了很多东西,现在“ID IN(?,.......?)”包含在事务中。

总时间减少到原来的1/1000。

我建议您可以为“标记为已删除”添加一列,并附上批量实际删除的时间表。

【讨论】:

    【解决方案2】:

    据我所知,Derby 只会将 BLOB 与其他数据库数据内联存储,因此您最终会将 BLOB 拆分为大量单独的数据库页面文件。这种 BLOB 存储机制适用于 ACID,也适用于较小的 BLOB(例如,图像缩略图),但会分解较大的对象。根据 Derby 文档,在操作 BLOB 时关闭自动提交也可能会提高性能,但这只会到此为止。

    如果大型 BLOB 的良好性能很重要,我强烈建议您迁移到 H2 或其他 DBMS,并且 BLOB 必须保留在 DB 中。您可以使用 SQuirrel SQL 客户端及其 DBCopy 插件在 DBMS 之间直接迁移(您只需将其指向 Derby/JavaDB JDBC 驱动程序和 H2 驱动程序)。我很乐意为这部分提供帮助,因为我自己就是这样做的,而且一直没有更快乐。

    如果失败,您可以将 BLOB 移出数据库并移入文件系统。为此,您可以将数据库中的 BLOB 列替换为 BLOB 大小(如果需要)和位置(一个 URI 或平台相关的文件字符串)。创建新 blob 时,您会在文件系统中创建相应的文件。该位置可以基于给定目录,并附加主键。例如,您的数据库位于“DBFolder/DBName”中,而您的 Blob 位于“DBFolder/DBName/Blob”中,文件名为“BLOB_PRIMARYKEY.bin”或类似名称。要编辑或读取 BLOB,请在数据库中查询位置,然后直接读取/写入文件。然后,如果新文件大小发生更改,则将其记录到数据库中。

    【讨论】:

      【解决方案3】:

      我确定这不是您想要的答案,但对于具有吞吐量要求的生产环境,我不会使用 Java DB。 MySQL 同样免费,可以更好地满足您的需求。我认为你真的只是在挑战你所选择的解决方案的局限性。

      我通常只使用 Derby 作为测试用例,尤其是当我的整个数据库可以轻松放入内存时。 YMMV。

      【讨论】:

        【解决方案4】:

        你试过increasing the page size of your database吗?

        Tuning Java DB 手册中提供了相关信息以及更多信息,您可能会发现这些信息很有用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-04-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-08-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多