【问题标题】:ServiceStack.OrmLite: Slow write/reads?ServiceStack.OrmLite:写入/读取速度慢?
【发布时间】:2018-06-30 19:37:56
【问题描述】:

6 月 30 日更新 这个问题做了一个更干净的基准测试,Mythz 发现了一个问题并解决了它: ServiceStack benchmark continued: why does persisting a simple (complex) to JSON slow down SELECTs?


写入/读取速度是否合理?

我正在试用 OrmLite,我将测试将我们当前的所有数据/对象从我们自己的实现转换为保存到数据库,然后切换到 OrmLite。

但是,我做了一个简单的基准测试/速度测试,比较了我们当前的序列化和写入 db 以及从 db 读取和反序列化。

我发现 ServiceStack 比我们目前的做法慢得多(我们目前只是使用 FastSerializer 序列化对象,并将 byte[] 数据写入 BLOB 字段,因此它的读写速度很快,但当然缺点明显)。

我做的测试是使用 Customer 类,它有一堆属性(在我们的产品中使用,所以它是我们当前版本中每天都使用的类)。

如果我创建 10 000 个这样的对象,然后测量将这些对象持久化到 MySql 数据库(序列化 + 写入数据库)需要多长时间,结果是:


更新

由于“当前实现”是作弊的(它只是将一个字节 [] BLOB 写入数据库),我实现了一个简单的 RelationDbHandler,它以正常的方式通过一个简单的 SQL 查询来持久化 10 000 个对象。结果添加如下。


写入 10 000 个对象:
当前实施:33 秒
OrmLite(使用 .Save):94 秒
关系方法:24.7 秒
读取 10 000 个对象:
当前实施:1.5 秒
OrmLite(使用 Select):28 秒 关系方法:16 秒

我在本地的 SSD 磁盘上运行它,CPU 或磁盘上没有其他负载。 我预计我们当前的实现会更快,但不会快很多。

我在 ServiceStack 网页 (https://github.com/ServiceStack/ServiceStack/wiki/Real-world-performance) 上阅读了一些基准测试资料,但大部分链接都已失效。读取 25 000 行需要 245 毫秒,但我不知道一行是什么样的。

问题 1:我可以阅读更多关于基准的信息吗?
问题 2:下面指定了 Customer 对象。神话认为上面的写/读时间是合理的吗?

测试用例: 这是 OrmLite 创建表后在数据库中查看的 Customer 对象。我只填充了 5 个属性,一个是“复杂的”(因此只有一个字段在行中具有 JSON 序列化表示),但由于所有字段都已写入,我认为这并不重要?

使用 OrmLite 保存的代码:

 public void MyTestMethod<T>(T coreObject) where T : CoreObject
    {
        long id = 0;
        using (var _db = _dbFactory.Open())
        {
            id = _db.Insert<T>(coreObject, selectIdentity: true);
        }           
    }

从表中读取所有代码:

 internal List<T> FetchAll<T>()
        {
            using (var _db = _dbFactory.Open())
            {
                List<T> list = _db.Select<T>();
                return list;
            }
        }

【问题讨论】:

  • 刚刚又跑了一遍代码;现在,OrmLite 需要 28-36 秒,相同的代码,相同的数据库,相同的一切。
  • 更多调查表明,blobed JSON 对象越复杂,它就越慢(自然)。但它相当多。加载 10k 个对象需要 1500 毫秒;如果我开始删除一些 JSON-blob,它会显着删除我在数据库中清除的每个列/字段。即使使用非常小的 JSON 数据,我清除的到达列也会下降 200-300 毫秒...

标签: servicestack ormlite-servicestack


【解决方案1】:

使用Insert() 插入行。 Save() 将检查现有记录是否存在,如果存在则更新它,它还会填充自动增量主键(如果已创建)。

还有InsertAsync() API 可用,但Oracle 的官方MySql.Data NuGet 包没有适当的异步实现,在这种情况下使用https://github.com/mysql-net/MySqlConnector 可以通过安装 ServiceStack.OrmLite.MySqlConnector NuGet 包并使用其MySqlConnectorDialect.Provider

您还可以使用 .NET Core 获得更好的性能,它将使用最新的 8.x MySql.Data NuGet 包。

注意:https://github.com/tedekeroth/OrmLiteVsFastSerializer 中的结果不可比较,本质上是在比较使用 MySql 作为 NoSQL blob 存储与 OrmLite 中具有多个复杂类型 blob 字段的准关系模型。

在我的测试中,我还注意到几个序列化异常被吞下,这会对性能产生负面影响,您可以通过在启动时配置来冒泡异常:

OrmLiteConfig.ThrowOnError = JsConfig.ThrowOnError = true;

【讨论】:

  • 感谢您的快速回答(一如既往)!我尝试改用 Insert,结果几乎相同,花费了 83.5 秒...您认为这符合您的预期吗?
  • @Ted 我需要查看基准才能评论并确定基准是否相同。如果您将基准源代码上传到 GitHub 上的存储库,我将能够分析和解释差异。
  • 好的,我会尽快尝试,完成后我会在这里评论。
  • 在这里。在 bin/debug 中,有一些你需要引用的必要 DLL。有一个 obj_customer.sql 文件来创建 obj_customer 表。我正在运行 mySql 5.6。 github.com/tedekeroth/OrmLiteVsFastSerializer
  • 调试?基准测试不应该使用调试版本,添加发布版本,我明天凌晨 4 点会研究它
猜你喜欢
  • 2020-04-27
  • 2012-07-15
  • 1970-01-01
  • 2019-03-02
  • 2016-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-09
相关资源
最近更新 更多